From: Andre Noll Date: Sat, 31 Dec 2016 15:50:02 +0000 (+0100) Subject: Merge branch 'refs/heads/t/simple_error_codes' X-Git-Tag: v0.5.7~2 X-Git-Url: http://git.tuebingen.mpg.de/?a=commitdiff_plain;h=21c6e0b09b42e61e72b741bd726856ab0bcd1d64;hp=53d5ac455d0616a5ee8867c986631ed34c177a42;p=paraslash.git Merge branch 'refs/heads/t/simple_error_codes' Two patches which get rid of the concept of per-subsystem error codes. The host-compiled error2.c program can be removed, configure.ac and error.h simplified. The merge conflicted because both sides modified error.h, but this was easy to resolve. * refs/heads/t/simple_error_codes: Sort errors alphabetically. Simplify the error subsystem, get rid of error2.[ch]. --- diff --git a/Doxyfile b/Doxyfile index f6476603..c607b8ea 100644 --- a/Doxyfile +++ b/Doxyfile @@ -797,7 +797,6 @@ EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = *.cmdline.* \ gcc-compat.h \ - fade.c \ *.command_list.h \ *.completion.h diff --git a/Makefile.real b/Makefile.real index 980192ec..9d10e184 100644 --- a/Makefile.real +++ b/Makefile.real @@ -125,6 +125,13 @@ ifeq ($(uname_s),Linux) LDFLAGS += -Wl,--gc-sections endif +cc-option = $(shell \ + $(CC) $(1) -Werror -c -x c /dev/null -o /dev/null > /dev/null 2>&1 \ + && echo "$(1)" \ +) + +STRICT_CFLAGS += $(call cc-option, -Wformat-signedness) + # To put more focus on warnings, be less verbose as default # Use 'make V=1' to see the full commands ifeq ("$(origin V)", "command line") diff --git a/NEWS.md b/NEWS.md index b0862d5f..449a3a1f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -8,6 +8,16 @@ NEWS - One of the two source browsers has been removed from the web pages. The doxygen API reference still contains an HTML version of each source file. +- Two race conditions in para_server have been fixed. +- ls -p is now deprecated in favor of -F or -b. See the help text of + the ls command for details. +- The openssl code has been adjusted to work also with openssl-1.1. +- The wma decoder and audio format handler now correctly decodes + files with unusual block sizes. +- We now compile with -Wformat-signedness if possible. +- The touch command now refuses to set an invalid image or lyrics ID. +- New section on contributing for the user manual. +- Major simplification of the error subsystem. Download: [tarball](./releases/paraslash-git.tar.bz2) @@ -35,6 +45,7 @@ not mentioned here have accumulated and are also part of the release. - para_gui no longer reports 100% playing time at the stream start. - Opus cleanups. +Downloads: [tarball](./releases/paraslash-0.5.6.tar.bz2), [signature](./releases/paraslash-0.5.6.tar.bz2.asc) diff --git a/aac.h b/aac.h index f31d723a..eeed2528 100644 --- a/aac.h +++ b/aac.h @@ -9,12 +9,6 @@ #include NeAACDecHandle aac_open(void); -int aac_find_esds(unsigned char *buf, size_t buflen, size_t *skip, +int aac_find_esds(char *buf, size_t buflen, size_t *skip, unsigned long *decoder_length); -ssize_t aac_find_entry_point(unsigned char *buf, size_t buflen, size_t *skip); - -static inline unsigned aac_read_int32(unsigned char *buf) -{ - uint8_t *d = (uint8_t*)buf; - return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3]; -} +ssize_t aac_find_entry_point(char *buf, size_t buflen, size_t *skip); diff --git a/aac_afh.c b/aac_afh.c index c49f30de..1c7fd706 100644 --- a/aac_afh.c +++ b/aac_afh.c @@ -15,44 +15,44 @@ #include "para.h" #include "error.h" +#include "portable_io.h" #include "afh.h" #include "string.h" #include "aac.h" #include "fd.h" -static int aac_find_stsz(unsigned char *buf, size_t buflen, off_t *skip) +static int aac_find_stsz(char *buf, size_t buflen, off_t *skip) { int i; for (i = 0; i + 16 < buflen; i++) { - unsigned char *p = buf + i; + char *p = buf + i; unsigned sample_count, sample_size; if (p[0] != 's' || p[1] != 't' || p[2] != 's' || p[3] != 'z') continue; PARA_DEBUG_LOG("found stsz@%d\n", i); i += 8; - sample_size = aac_read_int32(buf + i); - PARA_DEBUG_LOG("sample size: %d\n", sample_size); + sample_size = read_u32_be(buf + i); + PARA_DEBUG_LOG("sample size: %u\n", sample_size); i += 4; - sample_count = aac_read_int32(buf + i); + sample_count = read_u32_be(buf + i); i += 4; - PARA_DEBUG_LOG("sample count: %d\n", sample_count); + PARA_DEBUG_LOG("sample count: %u\n", sample_count); *skip = i; return sample_count; } return -E_STSZ; } -static int atom_cmp(const unsigned char *buf1, const char *buf2) +static int atom_cmp(const char *buf1, const char *buf2) { return memcmp(buf1, buf2, 4)? 1 : 0; } -static int read_atom_header(unsigned char *buf, uint64_t *subsize, unsigned char type[5]) +static int read_atom_header(char *buf, uint64_t *subsize, char type[5]) { - int i; - uint64_t size = aac_read_int32(buf); + uint64_t size = read_u32_be(buf); memcpy(type, buf + 4, 4); type[4] = '\0'; @@ -64,13 +64,12 @@ static int read_atom_header(unsigned char *buf, uint64_t *subsize, unsigned char } buf += 4; size = 0; - for (i = 0; i < 8; i++) - size |= ((uint64_t)buf[i]) << ((7 - i) * 8); + size = read_u64_be(buf); *subsize = size; return 16; } -static char *get_tag(unsigned char *p, int size) +static char *get_tag(char *p, int size) { char *buf; @@ -83,12 +82,12 @@ static char *get_tag(unsigned char *p, int size) return buf; } -static void read_tags(unsigned char *buf, size_t buflen, struct afh_info *afhi) +static void read_tags(char *buf, size_t buflen, struct afh_info *afhi) { - unsigned char *p = buf; + char *p = buf; while (p + 32 < buf + buflen) { - unsigned char *q, type1[5], type2[5]; + char *q, type1[5], type2[5]; uint64_t size1, size2; int ret, ret2; @@ -117,9 +116,9 @@ static void read_tags(unsigned char *buf, size_t buflen, struct afh_info *afhi) } } -static void read_meta(unsigned char *buf, size_t buflen, struct afh_info *afhi) +static void read_meta(char *buf, size_t buflen, struct afh_info *afhi) { - unsigned char *p = buf; + char *p = buf; while (p + 4 < buf + buflen) { @@ -132,15 +131,14 @@ static void read_meta(unsigned char *buf, size_t buflen, struct afh_info *afhi) } } -static void aac_get_taginfo(unsigned char *buf, size_t buflen, - struct afh_info *afhi) +static void aac_get_taginfo(char *buf, size_t buflen, struct afh_info *afhi) { int i; uint64_t subsize; - unsigned char type[5]; + char type[5]; for (i = 0; i + 24 < buflen; i++) { - unsigned char *p = buf + i; + char *p = buf + i; if (p[0] != 'm' || p[1] != 'e' || p[2] != 't' || p[3] != 'a') continue; PARA_INFO_LOG("found metadata at offset %d\n", i); @@ -154,7 +152,7 @@ static void aac_get_taginfo(unsigned char *buf, size_t buflen, } static ssize_t aac_compute_chunk_table(struct afh_info *afhi, - unsigned char *map, size_t numbytes) + char *map, size_t numbytes) { int ret, i; size_t sum = 0; @@ -169,7 +167,7 @@ static ssize_t aac_compute_chunk_table(struct afh_info *afhi, for (i = 1; i <= afhi->chunks_total; i++) { if (skip + 4 > numbytes) break; - sum += aac_read_int32(map + skip); + sum += read_u32_be(map + skip); afhi->chunk_table[i] = sum; skip += 4; // if (i < 10 || i + 10 > afhi->chunks_total) @@ -212,32 +210,33 @@ static int aac_get_file_info(char *map, size_t numbytes, __a_unused int fd, unsigned char channels = 0; mp4AudioSpecificConfig mp4ASC; NeAACDecHandle handle = NULL; - unsigned char *umap = (unsigned char *) map; - ret = aac_find_esds(umap, numbytes, &skip, &decoder_len); + ret = aac_find_esds(map, numbytes, &skip, &decoder_len); if (ret < 0) goto out; - aac_get_taginfo(umap, numbytes, afhi); + aac_get_taginfo(map, numbytes, afhi); handle = aac_open(); ret = -E_AAC_AFH_INIT; - if (NeAACDecInit(handle, umap + skip, decoder_len, &rate, &channels)) + if (NeAACDecInit(handle, (unsigned char *)map + skip, decoder_len, + &rate, &channels)) goto out; if (!channels) goto out; PARA_DEBUG_LOG("rate: %lu, channels: %d\n", rate, channels); ret = -E_MP4ASC; - if (NeAACDecAudioSpecificConfig(umap + skip, numbytes - skip, &mp4ASC)) + if (NeAACDecAudioSpecificConfig((unsigned char *)map + skip, + numbytes - skip, &mp4ASC)) goto out; if (!mp4ASC.samplingFrequency) goto out; - ret = aac_compute_chunk_table(afhi, umap, numbytes); + ret = aac_compute_chunk_table(afhi, map, numbytes); if (ret < 0) goto out; skip = ret; ret = aac_set_chunk_tv(afhi, &mp4ASC, &afhi->seconds_total); if (ret < 0) goto out; - ret = aac_find_entry_point(umap + skip, numbytes - skip, &skip); + ret = aac_find_entry_point(map + skip, numbytes - skip, &skip); if (ret < 0) goto out; afhi->chunk_table[0] = ret; diff --git a/aac_common.c b/aac_common.c index fe9b7295..812c742c 100644 --- a/aac_common.c +++ b/aac_common.c @@ -13,6 +13,7 @@ #include "para.h" #include "aac.h" #include "error.h" +#include "portable_io.h" /** * Get a new libfaad decoder handle. @@ -31,7 +32,7 @@ NeAACDecHandle aac_open(void) return h; } -static unsigned long aac_read_decoder_length(unsigned char *buf, int *description_len) +static unsigned long aac_read_decoder_length(char *buf, int *description_len) { uint8_t b; uint8_t numBytes = 0; @@ -59,31 +60,31 @@ static unsigned long aac_read_decoder_length(unsigned char *buf, int *descriptio * * \return positive on success, negative on errors */ -int aac_find_esds(unsigned char *buf, size_t buflen, size_t *skip, +int aac_find_esds(char *buf, size_t buflen, size_t *skip, unsigned long *decoder_length) { size_t i; for (i = 0; i + 4 < buflen; i++) { - unsigned char *p = buf + i; + char *p = buf + i; int description_len; if (p[0] != 'e' || p[1] != 's' || p[2] != 'd' || p[3] != 's') continue; i += 8; p = buf + i; - PARA_INFO_LOG("found esds@%zu, next: %x\n", i, *p); + PARA_INFO_LOG("found esds@%zu, next: %x\n", i, (unsigned)*p); if (*p == 3) i += 8; else i += 6; p = buf + i; - PARA_INFO_LOG("next: %x\n", *p); + PARA_INFO_LOG("next: %x\n", (unsigned)*p); if (*p != 4) continue; i += 18; p = buf + i; - PARA_INFO_LOG("next: %x\n", *p); + PARA_INFO_LOG("next: %x\n", (unsigned)*p); if (*p != 5) continue; i++; @@ -108,19 +109,19 @@ int aac_find_esds(unsigned char *buf, size_t buflen, size_t *skip, * \return the position of the first entry in the table on success, * -E_STCO on errors. */ -ssize_t aac_find_entry_point(unsigned char *buf, size_t buflen, size_t *skip) +ssize_t aac_find_entry_point(char *buf, size_t buflen, size_t *skip) { ssize_t ret; size_t i; for (i = 0; i + 20 < buflen; i++) { - unsigned char *p = buf + i; + char *p = buf + i; if (p[0] != 's' || p[1] != 't' || p[2] != 'c' || p[3] != 'o') continue; PARA_INFO_LOG("found stco@%zu\n", i); i += 12; - ret = aac_read_int32(buf + i); /* first offset */ + ret = read_u32_be(buf + i); /* first offset */ i += 4; PARA_INFO_LOG("entry point: %zd\n", ret); *skip = i; diff --git a/aacdec_filter.c b/aacdec_filter.c index ac8148e8..5725ce04 100644 --- a/aacdec_filter.c +++ b/aacdec_filter.c @@ -86,7 +86,7 @@ static int aacdec_post_select(__a_unused struct sched *s, void *context) struct btr_node *btrn = fn->btrn; struct private_aacdec_data *padd = fn->private_data; int i, ret; - unsigned char *p, *inbuf, *outbuffer; + char *p, *inbuf, *outbuffer; char *btr_buf; size_t len, skip, consumed, loaded; @@ -97,7 +97,7 @@ next_buffer: if (ret == 0) return 0; btr_merge(btrn, fn->min_iqs); - len = btr_next_buffer(btrn, (char **)&inbuf); + len = btr_next_buffer(btrn, &inbuf); len = PARA_MIN(len, (size_t)8192); consumed = 0; if (!padd->initialized) { @@ -106,7 +106,7 @@ next_buffer: ret = aac_find_esds(inbuf, len, &skip, &padd->decoder_length); if (ret < 0) { PARA_INFO_LOG("%s\n", para_strerror(-ret)); - ret = NeAACDecInit(padd->handle, inbuf, + ret = NeAACDecInit(padd->handle, (unsigned char *)inbuf, len, &rate, &channels); PARA_INFO_LOG("decoder init: %d\n", ret); if (ret < 0) { @@ -120,14 +120,14 @@ next_buffer: consumed += skip; p = inbuf + consumed; ret = -E_AACDEC_INIT; - if (NeAACDecInit2(padd->handle, p, + if (NeAACDecInit2(padd->handle, (unsigned char *)p, padd->decoder_length, &rate, &channels) != 0) goto out; } padd->sample_rate = rate; padd->channels = channels; - PARA_INFO_LOG("rate: %u, channels: %d\n", + PARA_INFO_LOG("rate: %u, channels: %u\n", padd->sample_rate, padd->channels); padd->initialized = 1; } @@ -158,8 +158,8 @@ next_buffer: p = inbuf + consumed; //PARA_CRIT_LOG("consumed: %zu (%zu + %zu), have: %zu\n", padd->consumed_total + consumed, // padd->consumed_total, consumed, len - consumed); - outbuffer = NeAACDecDecode(padd->handle, &padd->frame_info, p, - len - consumed); + outbuffer = NeAACDecDecode(padd->handle, &padd->frame_info, + (unsigned char *)p, len - consumed); if (padd->frame_info.error) { int err = padd->frame_info.error; ret = -E_AAC_DECODE; @@ -171,7 +171,7 @@ next_buffer: goto success; } PARA_ERROR_LOG("%s\n", NeAACDecGetErrorMessage(err)); - PARA_ERROR_LOG("consumed: %zu + %zd + %lu\n", + PARA_ERROR_LOG("consumed: %zu + %zu + %lu\n", padd->consumed_total, consumed, padd->frame_info.bytesconsumed); if (consumed < len) diff --git a/acl.c b/acl.c index 5ef9a51c..560ff999 100644 --- a/acl.c +++ b/acl.c @@ -87,7 +87,7 @@ static void acl_add_entry(struct list_head *acl, char *addr, int netmask) inet_pton(AF_INET, addr, &ai->addr); ai->netmask = netmask; - PARA_INFO_LOG("adding %s/%i to access list\n", addr, ai->netmask); + PARA_INFO_LOG("adding %s/%u to access list\n", addr, ai->netmask); para_list_add(&ai->node, acl); } @@ -109,7 +109,7 @@ static void acl_del_entry(struct list_head *acl, char *addr, unsigned netmask) if (v4_addr_match(to_delete.s_addr, ai->addr.s_addr, PARA_MIN(netmask, ai->netmask))) { - PARA_NOTICE_LOG("removing %s/%i from access list\n", + PARA_NOTICE_LOG("removing %s/%u from access list\n", addr, ai->netmask); list_del(&ai->node); free(ai); @@ -131,7 +131,7 @@ char *acl_get_contents(struct list_head *acl) char *ret = NULL; list_for_each_entry_safe(ai, tmp_ai, acl, node) { - char *tmp = make_message("%s%s/%d ", ret? ret : "", + char *tmp = make_message("%s%s/%u ", ret? ret : "", inet_ntoa(ai->addr), ai->netmask); free(ret); ret = tmp; diff --git a/afh.h b/afh.h index dad67351..a6f9c500 100644 --- a/afh.h +++ b/afh.h @@ -36,9 +36,9 @@ struct afh_info { /** Id3 tags, vorbis comments, aac tags. */ struct taginfo tags; /** - * The table that specifies the offset of the individual pieces in - * the current audio file. - */ + * The table that specifies the offset of the individual pieces in + * the current audio file. + */ uint32_t *chunk_table; /** Period of time between sending data chunks. */ struct timeval chunk_tv; @@ -48,7 +48,7 @@ struct afh_info { * which means that this audio format does not need any special header * treatment. The audio format handler does not need to set this to * zero in this case. - */ + */ uint32_t header_len; /** The number of channels. */ uint8_t channels; diff --git a/afh_common.c b/afh_common.c index f36c32e2..dfbf7513 100644 --- a/afh_common.c +++ b/afh_common.c @@ -295,8 +295,8 @@ int32_t afh_get_start_chunk(int32_t approx_chunk_num, for (k = PARA_MAX(0, approx_chunk_num); k >= 0; k--) if (get_chunk_len(k, afhi) > 0) - break; - return k; + return k; + return 0; } /** diff --git a/afh_recv.c b/afh_recv.c index 16463463..28d8f398 100644 --- a/afh_recv.c +++ b/afh_recv.c @@ -205,7 +205,7 @@ static int afh_recv_post_select(__a_unused struct sched *s, void *context) afh_get_chunk(pard->first_chunk, afhi, pard->map, &start, &size); afh_get_chunk(pard->last_chunk, afhi, pard->map, &end, &size); end += size; - PARA_INFO_LOG("adding %zu bytes\n", end - start); + PARA_INFO_LOG("adding %td bytes\n", end - start); btr_add_output_dont_free(start, end - start, btrn); ret = -E_RECV_EOF; goto out; diff --git a/afs.c b/afs.c index 0accc451..0946b6df 100644 --- a/afs.c +++ b/afs.c @@ -706,7 +706,7 @@ static int open_afs_tables(void) int i, ret; get_database_dir(); - PARA_NOTICE_LOG("opening %u osl tables in %s\n", NUM_AFS_TABLES, + PARA_NOTICE_LOG("opening %d osl tables in %s\n", NUM_AFS_TABLES, database_dir); for (i = 0; i < NUM_AFS_TABLES; i++) { ret = afs_tables[i].open(database_dir); @@ -1024,6 +1024,13 @@ __noreturn void afs_init(uint32_t cookie, int socket_fd) register_command_task(cookie, &s); s.default_timeout.tv_sec = 0; s.default_timeout.tv_usec = 999 * 1000; + ret = write(socket_fd, "\0", 1); + if (ret != 1) { + if (ret == 0) + errno = EINVAL; + ret = -ERRNO_TO_PARA_ERROR(errno); + goto out_close; + } ret = schedule(&s); sched_shutdown(&s); out_close: @@ -1195,7 +1202,7 @@ __must_check int afs_event(enum afs_events event, struct para_buffer *pb, continue; ret = t->event_handler(event, pb, data); if (ret < 0) { - PARA_CRIT_LOG("table %s, event %d: %s\n", t->name, + PARA_CRIT_LOG("table %s, event %u: %s\n", t->name, event, para_strerror(-ret)); return ret; } diff --git a/afs.cmd b/afs.cmd index 584ba809..76b5f4dc 100644 --- a/afs.cmd +++ b/afs.cmd @@ -51,8 +51,13 @@ H: p: parser-friendly mode H: m: mbox listing mode H: c: chunk-table listing mode H: -H: -p List full paths. If this option is not specified, only the basename +H: -F List full paths. If this option is not specified, only the basename H: of each file is printed. +H: -p Synonym for -F. Deprecated. +H: +H: -b Print only the basename of each matching file. This is the default, so +H: the option is currently a no-op. It is recommended to specify this option, +H: though, as the default might change in a future release. H: H: -a List only files that are admissible with respect to the current mood or H: playlist. @@ -61,7 +66,8 @@ H: -r Reverse sort order. H: H: -d Print dates as seconds after the epoch. H: -H: -s=order Change sort order. Defaults to alphabetical path sort if not given. +H: -s=order +H: Change sort order. Defaults to alphabetical path sort if not given. H: H: Possible values for order: H: p: by path diff --git a/aft.c b/aft.c index f14440e6..bfcd1fb0 100644 --- a/aft.c +++ b/aft.c @@ -738,11 +738,11 @@ static void get_duration_buf(int seconds, char *buf, struct ls_options *opts) if (!hours) { /* m:ss or mm:ss */ max_width = opts->mode == LS_MODE_LONG? opts->widths.duration_width : 4; - sprintf(buf, "%*u:%02u", max_width - 3, mins, seconds % 60); + sprintf(buf, "%*u:%02d", max_width - 3, mins, seconds % 60); } else { /* more than one hour => h:mm:ss, hh:mm:ss, hhh:mm:ss, ... */ max_width = opts->mode == LS_MODE_LONG? opts->widths.duration_width : 7; - sprintf(buf, "%*u:%02u:%02u", max_width - 6, hours, mins, + sprintf(buf, "%*u:%02u:%02d", max_width - 6, hours, mins, seconds % 60); } } @@ -876,14 +876,14 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts, para_printf(b, "%s " /* attributes */ "%*u " /* amp */ - "%*d " /* image_id */ - "%*d " /* lyrics_id */ - "%*d " /* bitrate */ + "%*u " /* image_id */ + "%*u " /* lyrics_id */ + "%*u " /* bitrate */ "%*s " /* audio format */ - "%*d " /* frequency */ - "%d " /* channels */ + "%*u " /* frequency */ + "%u " /* channels */ "%s " /* duration */ - "%*d " /* num_played */ + "%*u " /* num_played */ "%s " /* last_played */ "%s\n", /* path */ att_buf, @@ -930,7 +930,7 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts, WRITE_STATUS_ITEM(b, SI_SECONDS_TOTAL, "%" PRIu32 "\n", afhi->seconds_total); WRITE_STATUS_ITEM(b, SI_LAST_PLAYED, "%s\n", last_played_time); - WRITE_STATUS_ITEM(b, SI_NUM_PLAYED, "%d\n", afsi->num_played); + WRITE_STATUS_ITEM(b, SI_NUM_PLAYED, "%u\n", afsi->num_played); WRITE_STATUS_ITEM(b, SI_AMPLIFICATION, "%u\n", afsi->amp); WRITE_STATUS_ITEM(b, SI_CHUNK_TIME, "%lu\n", tv2ms(&afhi->chunk_tv)); WRITE_STATUS_ITEM(b, SI_NUM_CHUNKS, "%" PRIu32 "\n", @@ -1410,10 +1410,14 @@ int com_ls(struct command_context *cc) return -E_AFT_SYNTAX; } } - if (!strcmp(arg, "-p")) { + if (!strcmp(arg, "-p") || !strcmp(arg, "-F")) { flags |= LS_FLAG_FULL_PATH; continue; } + if (!strcmp(arg, "-b")) { + flags &= ~LS_FLAG_FULL_PATH; + continue; + } if (!strcmp(arg, "-a")) { flags |= LS_FLAG_ADMISSIBLE_ONLY; continue; @@ -2040,6 +2044,22 @@ static int com_touch_callback(struct afs_callback_arg *aca) .data = aca, .action = touch_audio_file }; + if (cto->image_id >= 0) { + ret = img_get_name_by_id(cto->image_id, NULL); + if (ret < 0) { + para_printf(&aca->pbout, "invalid image ID: %d\n", + cto->image_id); + return ret; + } + } + if (cto->lyrics_id >= 0) { + ret = lyr_get_name_by_id(cto->lyrics_id, NULL); + if (ret < 0) { + para_printf(&aca->pbout, "invalid lyrics ID: %d\n", + cto->lyrics_id); + return ret; + } + } if (cto->flags & TOUCH_FLAG_FNM_PATHNAME) pmd.fnmatch_flags |= FNM_PATHNAME; ret = for_each_matching_row(&pmd); @@ -2621,7 +2641,7 @@ static int aft_open(const char *dir) if (ret >= 0) { unsigned num; osl_get_num_rows(audio_file_table, &num); - PARA_INFO_LOG("audio file table contains %d files\n", num); + PARA_INFO_LOG("audio file table contains %u files\n", num); return ret; } PARA_NOTICE_LOG("failed to open audio file table\n"); diff --git a/alsa_mix.c b/alsa_mix.c index cad58af0..3adee929 100644 --- a/alsa_mix.c +++ b/alsa_mix.c @@ -142,7 +142,7 @@ static int alsa_mix_set_channel(struct mixer_handle *h, snd_mixer_selem_id_set_name(sid, mixer_channel); h->elem = snd_mixer_find_selem(h->mixer, sid); if (!h->elem) { - PARA_NOTICE_LOG("unable to find simple control '%s',%i\n", + PARA_NOTICE_LOG("unable to find simple control '%s',%u\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid)); ret = -E_BAD_CHANNEL; diff --git a/alsa_write.c b/alsa_write.c index 63a7055b..fd3b404c 100644 --- a/alsa_write.c +++ b/alsa_write.c @@ -303,7 +303,7 @@ again: get_btr_sample_format(btrn, &val); pad->sample_format = get_alsa_pcm_format(val); - PARA_INFO_LOG("%d channel(s), %dHz\n", pad->channels, + PARA_INFO_LOG("%u channel(s), %uHz\n", pad->channels, pad->sample_rate); ret = alsa_init(pad, wn->conf); if (ret < 0) { diff --git a/audiod.c b/audiod.c index 0f082e26..db69cf14 100644 --- a/audiod.c +++ b/audiod.c @@ -765,7 +765,7 @@ static void compute_time_diff(const struct timeval *status_time) if (count > 5) { int s = tv_diff(&diff, &stat_task->sa_time_diff, &tmp); if (tv_diff(&max_deviation, &tmp, NULL) < 0) - PARA_WARNING_LOG("time diff jump: %lims\n", + PARA_WARNING_LOG("time diff jump: %lums\n", s * tv2ms(&tmp)); } count++; @@ -1379,7 +1379,7 @@ static int status_post_select(struct sched *s, void *context) if (st->clock_diff_count) { /* get status only one time */ char *argv[] = {"audiod", "--", "stat", "-p", "-n=1", NULL}; int argc = 5; - PARA_INFO_LOG("clock diff count: %d\n", st->clock_diff_count); + PARA_INFO_LOG("clock diff count: %u\n", st->clock_diff_count); st->clock_diff_count--; client_open(argc, argv, &st->ct, NULL, NULL, st->btrn, s); set_stat_task_restart_barrier(2); diff --git a/blob.c b/blob.c index ca39de0d..ed684428 100644 --- a/blob.c +++ b/blob.c @@ -262,7 +262,7 @@ static int com_rmblob_callback(struct osl_table *table, if (pmd.num_matches == 0) ret = -E_NO_MATCH; else { - para_printf(&aca->pbout, "removed %d blob(s)\n", + para_printf(&aca->pbout, "removed %u blob(s)\n", pmd.num_matches); ret = afs_event(BLOB_REMOVE, NULL, table); } @@ -487,7 +487,8 @@ static int blob_get_name_by_id(struct osl_table *table, uint32_t id, struct osl_object obj = {.data = &id, .size = sizeof(id)}; int ret; - *name = NULL; + if (name) + *name = NULL; if (!id) return 1; ret = osl(osl_get_row(table, BLOBCOL_ID, &obj, &row)); @@ -498,7 +499,8 @@ static int blob_get_name_by_id(struct osl_table *table, uint32_t id, return ret; if (*(char *)obj.data == '\0') return -E_DUMMY_ROW; - *name = (char *)obj.data; + if (name) + *name = (char *)obj.data; return 1; } diff --git a/check_wav.c b/check_wav.c index d1d27872..1a47f946 100644 --- a/check_wav.c +++ b/check_wav.c @@ -177,7 +177,7 @@ int check_wav_post_select(struct check_wav_context *cwc) else cwc->sample_format = (a[3] == 'F')? SF_S16_LE : SF_S16_BE; - PARA_NOTICE_LOG("%dHz, %s, %s\n", cwc->sample_rate, + PARA_NOTICE_LOG("%uHz, %s, %s\n", cwc->sample_rate, cwc->channels == 1? "mono" : "stereo", sample_formats[cwc->sample_format]); btr_consume(btrn, WAV_HEADER_LEN); diff --git a/client.c b/client.c index d70bdb93..f1100df4 100644 --- a/client.c +++ b/client.c @@ -279,7 +279,7 @@ static void ls_completer(struct i9e_completion_info *ci, char *opts[] = { "--", "-l", "-l=s", "-l=l", "-l=v", "-l=p", "-l=m", "-l=c", "-p", "-a", "-r", "-d", "-s=p", "-s=l", "-s=s", "-s=n", "-s=f", - "-s=c", "-s=i", "-s=y", "-s=b", "-s=d", "-s=a", NULL + "-s=c", "-s=i", "-s=y", "-s=b", "-s=d", "-s=a", "-F", "-b", NULL }; if (ci->word[0] == '-') i9e_complete_option(opts, ci, cr); diff --git a/command.c b/command.c index 0eb4efc2..fe4b9232 100644 --- a/command.c +++ b/command.c @@ -473,7 +473,7 @@ static unsigned empty_status_items(int parser_friendly, char **result) #define ITEM(x) "0004 %02x:\n" EMPTY_STATUS_ITEMS #undef ITEM - #define ITEM(x) , SI_ ## x + #define ITEM(x) , (unsigned) SI_ ## x EMPTY_STATUS_ITEMS #undef ITEM ); @@ -767,7 +767,7 @@ static int com_jmp(struct command_context *cc) i = 100; PARA_INFO_LOG("jumping to %lu%%\n", i); mmd->repos_request = (mmd->afd.afhi.chunks_total * i + 50) / 100; - PARA_INFO_LOG("sent: %lu, offset before jmp: %lu\n", + PARA_INFO_LOG("sent: %lu, offset before jmp: %li\n", mmd->chunks_sent, mmd->offset); mmd->new_vss_status_flags |= VSS_REPOS; mmd->new_vss_status_flags &= ~VSS_NEXT; @@ -964,7 +964,7 @@ __noreturn void handle_connect(int fd, const char *peername) numbytes = 256; get_random_bytes_or_die((unsigned char *)buf, numbytes); } - PARA_DEBUG_LOG("sending %u byte challenge + session key (%zu bytes)\n", + PARA_DEBUG_LOG("sending %d byte challenge + session key (%zu bytes)\n", CHALLENGE_SIZE, numbytes); ret = send_sb(&cc->scc, buf, numbytes, SBD_CHALLENGE, false); buf = NULL; diff --git a/configure.ac b/configure.ac index ffb06934..0b00cc2a 100644 --- a/configure.ac +++ b/configure.ac @@ -99,6 +99,10 @@ LIB_ARG_WITH([openssl], [-lssl -lcrypto]) AC_CHECK_HEADER(openssl/ssl.h, [], [HAVE_OPENSSL=no]) AC_CHECK_LIB([crypto], [RAND_bytes], [], [HAVE_OPENSSL=no]) LIB_SUBST_FLAGS(openssl) +if test $HAVE_OPENSSL = yes; then + AC_CHECK_LIB([crypto], [RSA_set0_key], + AC_DEFINE([HAVE_RSA_SET0_KEY], [1], [openssl-1.1])) +fi UNSTASH_FLAGS ######################################################################### gcrypt STASH_FLAGS diff --git a/crypt.c b/crypt.c index f227eb39..8116fb6e 100644 --- a/crypt.c +++ b/crypt.c @@ -134,18 +134,25 @@ static int read_rsa_bignums(const unsigned char *blob, int blen, RSA **result) { int ret; RSA *rsa; + BIGNUM *n, *e; const unsigned char *p = blob, *end = blob + blen; rsa = RSA_new(); if (!rsa) return -E_BIGNUM; - ret = read_bignum(p, end - p, &rsa->e); + ret = read_bignum(p, end - p, &e); if (ret < 0) goto fail; p += ret; - ret = read_bignum(p, end - p, &rsa->n); + ret = read_bignum(p, end - p, &n); if (ret < 0) goto fail; +#ifdef HAVE_RSA_SET0_KEY + RSA_set0_key(rsa, n, e, NULL); +#else + rsa->n = n; + rsa->e = e; +#endif *result = rsa; return 1; fail: @@ -256,27 +263,18 @@ int pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf, return ret < 0? -E_ENCRYPT : ret; } -struct aes_ctr_128_context { - AES_KEY key; - unsigned char ivec[AES_CRT128_BLOCK_SIZE]; - unsigned char ecount[AES_CRT128_BLOCK_SIZE]; - unsigned int num; -}; - struct stream_cipher { bool use_aes; union { RC4_KEY rc4_key; - struct aes_ctr_128_context aes; + EVP_CIPHER_CTX *aes; } context; }; struct stream_cipher *sc_new(const unsigned char *data, int len, bool use_aes) { - int ret; struct stream_cipher *sc = para_malloc(sizeof(*sc)); - struct aes_ctr_128_context *aes; sc->use_aes = use_aes; if (!use_aes) { @@ -284,17 +282,17 @@ struct stream_cipher *sc_new(const unsigned char *data, int len, return sc; } assert(len >= 2 * AES_CRT128_BLOCK_SIZE); - aes = &sc->context.aes; - ret = AES_set_encrypt_key(data, AES_CRT128_BLOCK_SIZE * 8 /* bits */, - &aes->key); - assert(ret == 0); - memcpy(aes->ivec, data + AES_CRT128_BLOCK_SIZE, AES_CRT128_BLOCK_SIZE); - aes->num = 0; + sc->context.aes = EVP_CIPHER_CTX_new(); + EVP_EncryptInit_ex(sc->context.aes, EVP_aes_128_ctr(), NULL, data, + data + AES_CRT128_BLOCK_SIZE); return sc; } void sc_free(struct stream_cipher *sc) { + if (!sc) + return; + EVP_CIPHER_CTX_free(sc->context.aes); free(sc); } @@ -328,25 +326,29 @@ static void rc4_crypt(RC4_KEY *key, struct iovec *src, struct iovec *dst) ((char *)dst->iov_base)[len] = '\0'; } -static void aes_ctr128_crypt(struct aes_ctr_128_context *aes, struct iovec *src, +static void aes_ctr128_crypt(EVP_CIPHER_CTX *ctx, struct iovec *src, struct iovec *dst) { - size_t len = src->iov_len; + int ret, inlen = src->iov_len, outlen, tmplen; *dst = (typeof(*dst)) { /* Add one for the terminating zero byte. */ - .iov_base = para_malloc(len + 1), - .iov_len = len + .iov_base = para_malloc(inlen + 1), + .iov_len = inlen }; - AES_ctr128_encrypt(src->iov_base, dst->iov_base, len, - &aes->key, aes->ivec, aes->ecount, &aes->num); - ((char *)dst->iov_base)[len] = '\0'; + ret = EVP_EncryptUpdate(ctx, dst->iov_base, &outlen, src->iov_base, inlen); + assert(ret != 0); + ret = EVP_EncryptFinal_ex(ctx, dst->iov_base + outlen, &tmplen); + assert(ret != 0); + outlen += tmplen; + ((char *)dst->iov_base)[outlen] = '\0'; + dst->iov_len = outlen; } void sc_crypt(struct stream_cipher *sc, struct iovec *src, struct iovec *dst) { if (sc->use_aes) - return aes_ctr128_crypt(&sc->context.aes, src, dst); + return aes_ctr128_crypt(sc->context.aes, src, dst); return rc4_crypt(&sc->context.rc4_key, src, dst); } diff --git a/crypt_common.c b/crypt_common.c index b39ee5e4..a05572df 100644 --- a/crypt_common.c +++ b/crypt_common.c @@ -96,7 +96,7 @@ int check_ssh_key_header(const unsigned char *blob, int blen) return -E_SSH_KEY_HEADER; if (rlen < strlen(KEY_TYPE_TXT)) return -E_SSH_KEY_HEADER; - PARA_DEBUG_LOG("type: %s, rlen: %d\n", p, rlen); + PARA_DEBUG_LOG("type: %s, rlen: %u\n", p, rlen); if (strncmp((char *)p, KEY_TYPE_TXT, strlen(KEY_TYPE_TXT))) return -E_SSH_KEY_HEADER; return 4 + rlen; diff --git a/daemon.c b/daemon.c index 7c625bbe..20cdc6ae 100644 --- a/daemon.c +++ b/daemon.c @@ -155,10 +155,6 @@ static bool daemon_test_flag(unsigned flag) return me->flags & flag; } -static void dummy_sighandler(__a_unused int s) -{ -} - /** * Do the usual stuff to become a daemon. * @@ -166,30 +162,42 @@ static void dummy_sighandler(__a_unused int s) * * Fork, become session leader, cd to /, and dup fd 0, 1, 2 to /dev/null. If \a * parent_waits is false, the parent process terminates immediately. - * Otherwise, it calls pause() to sleep until it receives \p SIGTERM or \p - * SIGCHLD and exits successfully thereafter. This behaviour is useful if the - * daemon process should not detach from the console until the child process - * has completed its setup. + * Otherwise, a pipe is created prior to the fork() and the parent tries to + * read a single byte from the reading end of the pipe. The child is supposed + * to write to the writing end of the pipe after it completed its setup + * procedure successfully. This behaviour is useful to let the parent process + * die with an error if the child process aborts early, since in this case the + * read() will return non-positive. + * + * \return This function either succeeds or calls exit(3). If parent_waits is + * true, the return value is the file descriptor of the writing end of the + * pipe. Otherwise the function returns zero. * * \sa fork(2), setsid(2), dup(2), pause(2). */ -void daemonize(bool parent_waits) +int daemonize(bool parent_waits) { pid_t pid; - int null; + int null, pipe_fd[2]; - PARA_INFO_LOG("daemonizing\n"); + if (parent_waits && pipe(pipe_fd) < 0) + goto err; + PARA_INFO_LOG("subsequent log messages go to %s\n", me->logfile_name? + me->logfile_name : "/dev/null"); pid = fork(); if (pid < 0) goto err; - if (pid) { + if (pid) { /* parent exits */ if (parent_waits) { - signal(SIGTERM, dummy_sighandler); - signal(SIGCHLD, dummy_sighandler); - pause(); + char c; + close(pipe_fd[1]); + exit(read(pipe_fd[0], &c, 1) <= 0? + EXIT_FAILURE : EXIT_SUCCESS); } - exit(EXIT_SUCCESS); /* parent exits */ + exit(EXIT_SUCCESS); } + if (parent_waits) + close(pipe_fd[0]); /* become session leader */ if (setsid() < 0) goto err; @@ -205,7 +213,7 @@ void daemonize(bool parent_waits) if (dup2(null, STDERR_FILENO) < 0) goto err; close(null); - return; + return parent_waits? pipe_fd[1] : 0; err: PARA_EMERG_LOG("fatal: %s\n", strerror(errno)); exit(EXIT_FAILURE); diff --git a/daemon.h b/daemon.h index c7153605..989678df 100644 --- a/daemon.h +++ b/daemon.h @@ -1,7 +1,7 @@ /** \file daemon.h exported symbols from daemon.c */ -void daemonize(bool parent_waits); +int daemonize(bool parent_waits); void daemon_open_log_or_die(void); void daemon_close_log(void); void daemon_log_welcome(const char *whoami); diff --git a/error.h b/error.h index 24a2e3d9..899c574b 100644 --- a/error.h +++ b/error.h @@ -15,7 +15,6 @@ PARA_ERROR(ADD_CALLBACK, "can not add callback"), \ PARA_ERROR(ADDRESS_LOOKUP, "can not resolve requested address"),\ PARA_ERROR(AFH_RECV_BAD_FILENAME, "no file name given"), \ - PARA_ERROR(AFH_SYNTAX, "afh syntax error"), \ PARA_ERROR(AFS_SHORT_READ, "short read from afs socket"), \ PARA_ERROR(AFS_SIGNAL, "afs caught deadly signal"), \ PARA_ERROR(AFS_SOCKET, "afs socket not writable"), \ @@ -52,6 +51,7 @@ PARA_ERROR(AUDIO_FORMAT, "audio format not recognized"), \ PARA_ERROR(AUTH_REQUEST, "did not receive auth request"), \ PARA_ERROR(BAD_AFSI, "invalid afs info"), \ + PARA_ERROR(BAD_ASF_FILE_PROPS, "invalid ASF file properties"), \ PARA_ERROR(BAD_AUTH, "authentication failure"), \ PARA_ERROR(BAD_BAND, "invalid or unexpected band designator"), \ PARA_ERROR(BAD_CHANNEL_COUNT, "channel count not supported"), \ diff --git a/fade.c b/fade.c index 2ade4710..67dc4d54 100644 --- a/fade.c +++ b/fade.c @@ -69,7 +69,7 @@ static int fade(struct mixer *m, struct mixer_handle *h, int new_vol, int fade_t if (ret < 0) goto out; vol = ret; - PARA_NOTICE_LOG("fading %s from %d to %d in %d seconds\n", + PARA_NOTICE_LOG("fading %s from %d to %d in %u seconds\n", conf.mixer_channel_arg, vol, new_vol, secs); diff = new_vol - vol; if (!diff) { @@ -205,7 +205,7 @@ static int sweet_dreams(struct mixer *m, struct mixer_handle *h) tm = localtime(&t1); } wake_time_epoch = mktime(tm); - PARA_INFO_LOG("waketime: %u:%02u\n", tm->tm_hour, tm->tm_min); + PARA_INFO_LOG("waketime: %d:%02d\n", tm->tm_hour, tm->tm_min); client_cmd("stop"); sleep(1); if (fot) { @@ -335,6 +335,17 @@ __noreturn static void print_help_and_die(void) exit(0); } +/** + * The main function of para_fade. + * + * The executable is linked with the alsa or the oss mixer API, or both. It has + * a custom log function which prefixes log messages with the current date. + * + * \param argc Argument counter. + * \param argv Argument vector. + * + * \return EXIT_SUCCESS or EXIT_FAILURE. + */ int main(int argc, char *argv[]) { int ret; diff --git a/fecdec_filter.c b/fecdec_filter.c index 26ea24a6..1c3a3784 100644 --- a/fecdec_filter.c +++ b/fecdec_filter.c @@ -171,7 +171,7 @@ static struct fecdec_group *free_oldest_group(struct private_fecdec_data *pfd) oldest = fg; } if (!group_complete(oldest) && !group_empty(oldest)) - PARA_WARNING_LOG("Clearing incomplete group %d " + PARA_WARNING_LOG("Clearing incomplete group %u " "(contains %d slices)\n", oldest->h.group_num, oldest->num_received_slices); if (oldest == pfd->first_complete_group) @@ -224,7 +224,7 @@ static int add_slice(char *buf, struct fecdec_group *fg) uint8_t slice_num = fg->h.slice_num; if (group_complete(fg)) { - PARA_DEBUG_LOG("group %d complete, ignoring slice %d\n", + PARA_DEBUG_LOG("group %u complete, ignoring slice %d\n", fg->h.group_num, slice_num); return 0; } @@ -236,7 +236,7 @@ static int add_slice(char *buf, struct fecdec_group *fg) r = fg->num_received_slices; /* Check if we already have this slice. */ if (test_and_set_slice_bit(fg, slice_num)) { - PARA_INFO_LOG("ignoring duplicate slice %d:%d\n", fg->h.group_num, + PARA_INFO_LOG("ignoring duplicate slice %u:%d\n", fg->h.group_num, slice_num); return 0; } @@ -293,10 +293,10 @@ static int decode_group(struct fecdec_group *fg, struct filter_node *fn) char *buf = NULL; if (u == FEC_GROUP_UNUSABLE) { - PARA_INFO_LOG("dropping unusable group %d\n", fg->h.group_num); + PARA_INFO_LOG("dropping unusable group %u\n", fg->h.group_num); return 0; } - PARA_DEBUG_LOG("decoding group %d (%d slices)\n", fg->h.group_num, + PARA_DEBUG_LOG("decoding group %u (%d slices)\n", fg->h.group_num, fg->h.data_slices_per_group); ret = fec_decode(pfd->fec, fg->data, fg->idx, sb); if (ret < 0) @@ -307,7 +307,7 @@ static int decode_group(struct fecdec_group *fg, struct filter_node *fn) i = DIV_ROUND_UP(fg->h.audio_header_size, fg->h.slice_bytes); PARA_DEBUG_LOG("skipping %d header slices\n", i); } - PARA_DEBUG_LOG("writing group %d (%d/%d decoded data bytes)\n", + PARA_DEBUG_LOG("writing group %u (%u/%d decoded data bytes)\n", fg->h.group_num, fg->h.group_bytes, fg->h.data_slices_per_group * sb); need = (fg->h.data_slices_per_group - i) * sb; diff --git a/file_write.c b/file_write.c index ef25b0f5..5e66607e 100644 --- a/file_write.c +++ b/file_write.c @@ -39,7 +39,7 @@ __must_check __malloc static char *random_filename(void) char *result, *home = para_homedir(); srandom(clock_get_realtime(NULL)->tv_usec); - result = make_message("%s/.paraslash/%08lu", home, + result = make_message("%s/.paraslash/%08ld", home, para_random(99999999)); free(home); return result; diff --git a/filter_common.c b/filter_common.c index 84863b39..e9b97e54 100644 --- a/filter_common.c +++ b/filter_common.c @@ -204,7 +204,7 @@ int decoder_execute(const char *cmd, unsigned sample_rate, unsigned channels, return 1; } if (!strcmp(cmd, "sample_format")) { - *result = make_message("%u", DECODER_SAMPLE_FORMAT); + *result = make_message("%d", DECODER_SAMPLE_FORMAT); return 1; } return -ERRNO_TO_PARA_ERROR(ENOTSUP); diff --git a/flac_afh.c b/flac_afh.c index 2e2842b1..385d4f0c 100644 --- a/flac_afh.c +++ b/flac_afh.c @@ -468,7 +468,7 @@ static int flac_write_chain(FLAC__Metadata_Chain *chain, if (!ok) { FLAC__Metadata_ChainStatus st; st = FLAC__metadata_chain_status(chain); - PARA_ERROR_LOG("chain status: %d\n", st); + PARA_ERROR_LOG("chain status: %u\n", st); if (st == FLAC__METADATA_CHAIN_STATUS_READ_ERROR) PARA_ERROR_LOG("read error\n"); return -E_FLAC_WRITE_CHAIN; diff --git a/gcrypt.c b/gcrypt.c index 289748e8..7c19aeb0 100644 --- a/gcrypt.c +++ b/gcrypt.c @@ -388,7 +388,7 @@ static int read_bignum(unsigned char *start, unsigned char *end, gcry_mpi_t *bn, for (i = 0; i < num_bytes; i++, cp++) bn_size = (bn_size << 8) + *cp; } - PARA_DEBUG_LOG("bn_size %d (0x%x)\n", bn_size, bn_size); + PARA_DEBUG_LOG("bn_size %d (0x%x)\n", bn_size, (unsigned)bn_size); gret = gcry_mpi_scan(bn, GCRYMPI_FMT_STD, cp, bn_size, NULL); if (gret) { PARA_ERROR_LOG("%s while scanning n\n", @@ -586,7 +586,7 @@ static int get_asn_public_key(const char *key_file, struct asymmetric_key **resu key->num_bytes = n_size; *result = key; ret = n_size; - PARA_INFO_LOG("successfully read %u bit asn public key\n", n_size * 8); + PARA_INFO_LOG("successfully read %d bit asn public key\n", n_size * 8); release_e: gcry_mpi_release(e); @@ -648,7 +648,7 @@ static int get_ssh_public_key(unsigned char *data, int size, gcry_sexp_t *result goto release_n; } ret = nr_scanned / 32 * 32; - PARA_INFO_LOG("successfully read %u bit ssh public key\n", ret * 8); + PARA_INFO_LOG("successfully read %d bit ssh public key\n", ret * 8); release_n: gcry_mpi_release(n); release_e: diff --git a/gui.c b/gui.c index 63afca07..8e83cc53 100644 --- a/gui.c +++ b/gui.c @@ -1161,7 +1161,7 @@ static void print_scroll_msg(void) unsigned lines_total, filled = ringbuffer_filled(bot_win_rb); int first_rbe = first_visible_rbe(&lines_total); - print_in_bar(COLOR_MSG, "scrolled view: %d-%d/%d\n", filled - first_rbe, + print_in_bar(COLOR_MSG, "scrolled view: %u-%u/%u\n", filled - first_rbe, filled - scroll_position, ringbuffer_filled(bot_win_rb)); } diff --git a/mood.c b/mood.c index 940d72a1..79f47e5a 100644 --- a/mood.c +++ b/mood.c @@ -747,7 +747,7 @@ static int mood_update_audio_file(const struct osl_row *aft_row, percent = 100; else if (percent < 0) percent = 0; - PARA_DEBUG_LOG("moving from rank %u to %lu%%\n", rank, percent); + PARA_DEBUG_LOG("moving from rank %u to %li%%\n", rank, percent); return score_update(aft_row, percent); } diff --git a/mp3_afh.c b/mp3_afh.c index 70f2ec9f..2115f71c 100644 --- a/mp3_afh.c +++ b/mp3_afh.c @@ -238,7 +238,7 @@ static int replace_tag(char const *id, const char *val, struct id3_tag *id3_t, if (!val || !*val) return 0; fr = id3_frame_new(id); - PARA_DEBUG_LOG("frame desc: %s, %d fields\n", fr->description, fr->nfields); + PARA_DEBUG_LOG("frame desc: %s, %u fields\n", fr->description, fr->nfields); /* Frame 0 contains the encoding. We always use UTF-8. */ field = id3_frame_field(fr, 0); diff --git a/net.c b/net.c index 13694989..fa7cd4b8 100644 --- a/net.c +++ b/net.c @@ -376,7 +376,7 @@ int lookup_address(unsigned l4type, bool passive, const char *host, struct addrinfo *addr = NULL, hints; *result = NULL; - sprintf(port, "%u", port_number & 0xffff); + sprintf(port, "%d", port_number & 0xffff); /* Set up address hint structure */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; diff --git a/ogg_afh.c b/ogg_afh.c index 29f08965..2ddf0ee3 100644 --- a/ogg_afh.c +++ b/ogg_afh.c @@ -95,7 +95,7 @@ static void add_ogg_page(ogg_page *og, struct vorbis_get_header_data *vghd) memcpy(p + og->header_len, og->body, og->body_len); vghd->buf = buf; vghd->len = new_len; - PARA_DEBUG_LOG("header/body/old/new: %lu/%lu/%zu/%zu\n", + PARA_DEBUG_LOG("header/body/old/new: %li/%li/%zu/%zu\n", og->header_len, og->body_len, old_len, new_len); } diff --git a/ogg_afh_common.c b/ogg_afh_common.c index e49b803b..adab7f48 100644 --- a/ogg_afh_common.c +++ b/ogg_afh_common.c @@ -193,7 +193,7 @@ static int write_ogg_page(int fd, const ogg_page *op) { int ret; - PARA_DEBUG_LOG("header/body: %lu/%lu\n", op->header_len, op->body_len); + PARA_DEBUG_LOG("header/body: %li/%li\n", op->header_len, op->body_len); ret = xwrite(fd, (const char *)op->header, op->header_len); if (ret < 0) return ret; @@ -288,7 +288,7 @@ int ogg_rewrite_tags(const char *map, size_t map_sz, int fd, goto out; continue; } - PARA_DEBUG_LOG("packet: bytes: %d, granule: %d, packetno: %u\n", + PARA_DEBUG_LOG("packet: bytes: %d, granule: %d, packetno: %d\n", (int)packet.bytes, (int)packet.granulepos, (int)packet.packetno); /* ignore meta data packet which we replaced */ @@ -309,7 +309,7 @@ int ogg_rewrite_tags(const char *map, size_t map_sz, int fd, #endif if (ret <= 0) break; - PARA_DEBUG_LOG("writing page (%lu bytes)\n", + PARA_DEBUG_LOG("writing page (%li bytes)\n", op.header_len + op.body_len); ret = write_ogg_page(fd, &op); if (ret < 0) diff --git a/oggdec_filter.c b/oggdec_filter.c index 4b801356..04be7020 100644 --- a/oggdec_filter.c +++ b/oggdec_filter.c @@ -162,7 +162,7 @@ open: goto out; pod->channels = ov_info(vf, 0)->channels; pod->sample_rate = ov_info(vf, 0)->rate; - PARA_NOTICE_LOG("%d channels, %d Hz\n", pod->channels, + PARA_NOTICE_LOG("%u channels, %u Hz\n", pod->channels, pod->sample_rate); ret = 1; out: diff --git a/opus_afh.c b/opus_afh.c index b1469b47..64eeb03c 100644 --- a/opus_afh.c +++ b/opus_afh.c @@ -55,7 +55,7 @@ static int opus_get_comments(char *comments, int length, p += 4; if (p + ntags * 4 > end) return -E_OPUS_COMMENT; - PARA_INFO_LOG("found %d tag(s)\n", ntags); + PARA_INFO_LOG("found %u tag(s)\n", ntags); for (i = 0; i < ntags; i++, p += val) { char *tag; diff --git a/oss_write.c b/oss_write.c index 12cf8b69..20186667 100644 --- a/oss_write.c +++ b/oss_write.c @@ -165,7 +165,7 @@ static int oss_init(struct writer_node *wn, unsigned sample_rate, ret = -E_BAD_SAMPLERATE; if (100 * max > 110 * min) /* more than 10% deviation */ goto err; - PARA_NOTICE_LOG("using %dHz rather than %dHz\n", rate, + PARA_NOTICE_LOG("using %uHz rather than %uHz\n", rate, sample_rate); } wn->min_iqs = powd->bytes_per_frame; diff --git a/play.c b/play.c index 034e0f6f..fac551aa 100644 --- a/play.c +++ b/play.c @@ -328,8 +328,7 @@ static int open_new_file(struct play_task *pt) pt->rn.receiver = afh_recv; ret = afh_recv->open(&pt->rn); if (ret < 0) { - PARA_ERROR_LOG("could not open %s: %s\n", path, - para_strerror(-ret)); + PARA_ERROR_LOG("could not open %s\n", path); goto fail; } pt->audio_format_num = ret; @@ -388,6 +387,7 @@ static int load_file(struct play_task *pt) /* set up decoding filter */ af = audio_format_name(pt->audio_format_num); tmp = make_message("%sdec", af); + PARA_INFO_LOG("decoder: %s\n", tmp); ret = check_filter_arg(tmp, &pt->fn.conf); freep(&tmp); if (ret < 0) @@ -399,6 +399,8 @@ static int load_file(struct play_task *pt) .handler = decoder->execute, .context = &pt->fn)); if (decoder->open) decoder->open(&pt->fn); + PARA_INFO_LOG("buffer tree:\n"); + btr_log_tree(pt->rn.btrn, LL_INFO); /* setup default writer */ pt->wn.conf = check_writer_arg_or_die(NULL, &pt->wn.writer_num); @@ -453,6 +455,8 @@ again: pt->next_file = pt->current_file; ret = load_file(pt); if (ret < 0) { + PARA_ERROR_LOG("%s: marking file as invalid\n", + para_strerror(-ret)); pt->invalid[pt->next_file] = true; pt->rq = CRT_NONE; goto again; @@ -784,7 +788,7 @@ static void list_file(struct play_task *pt, int num) char *buf; size_t sz; - sz = xasprintf(&buf, "%s %4u %s\n", num == pt->current_file? + sz = xasprintf(&buf, "%s %4d %s\n", num == pt->current_file? "*" : " ", num, conf.inputs[num]); btr_add_output(buf, sz, pt->btrn); } diff --git a/portable_io.h b/portable_io.h index f1a38929..4e10c2e3 100644 --- a/portable_io.h +++ b/portable_io.h @@ -4,7 +4,7 @@ * Licensed under the GPL v2. For licencing details see COPYING. */ -/** \file portable_io.h Inline functions for endian-independent binary IO. */ +/** \file portable_io.h Inline functions for binary IO. */ static inline uint64_t read_portable(unsigned bits, const char *buf) { @@ -18,6 +18,18 @@ static inline uint64_t read_portable(unsigned bits, const char *buf) return ret; } +static inline uint64_t read_portable_be(unsigned bits, const char *buf) +{ + uint64_t ret = 0; + int i, num_bytes = bits / 8; + + for (i = 0; i < num_bytes; i++) { + unsigned char c = buf[i]; + ret += ((uint64_t)c << (8 * (num_bytes - i - 1))); + } + return ret; +} + static inline uint64_t read_u64(const char *buf) { return read_portable(64, buf); @@ -38,13 +50,35 @@ static inline uint8_t read_u8(const char *buf) return read_portable(8, buf); } +static inline uint64_t read_u64_be(const char *buf) +{ + return read_portable_be(64, buf); +} + +static inline uint32_t read_u32_be(const char *buf) +{ + return read_portable_be(32, buf); +} + +static inline uint16_t read_u16_be(const char *buf) +{ + return read_portable_be(16, buf); +} + static inline void write_portable(unsigned bits, char *buf, uint64_t val) { int i, num_bytes = bits / 8; -// fprintf(stderr, "val: %lu\n", val); for (i = 0; i < num_bytes; i++) { buf[i] = val & 0xff; -// fprintf(stderr, "buf[%d]=%x\n", i, buf[i]); + val = val >> 8; + } +} + +static inline void write_portable_be(unsigned bits, char *buf, uint64_t val) +{ + int i, num_bytes = bits / 8; + for (i = 0; i < num_bytes; i++) { + buf[num_bytes - i - 1] = val & 0xff; val = val >> 8; } } @@ -68,3 +102,18 @@ static inline void write_u8(char *buf, uint8_t val) { write_portable(8, buf, (uint64_t) val); } + +static inline void write_u64_be(char *buf, uint64_t val) +{ + write_portable_be(64, buf, val); +} + +static inline void write_u32_be(char *buf, uint32_t val) +{ + write_portable_be(32, buf, (uint64_t) val); +} + +static inline void write_u16_be(char *buf, uint16_t val) +{ + write_portable_be(16, buf, (uint64_t) val); +} diff --git a/resample_filter.c b/resample_filter.c index 6a285ec3..1699ed2c 100644 --- a/resample_filter.c +++ b/resample_filter.c @@ -128,13 +128,7 @@ static int resample_init(struct filter_node *fn) int ret, converter; struct resample_context *ctx = fn->private_data; struct resample_filter_args_info *conf = fn->conf; - struct btr_node *btrn = fn->btrn; - ret = -E_RESAMPLE_EOF; - if (btr_no_parent(btrn)) - return ret; - if (btr_get_input_queue_size(btrn) == 0) - return 0; ret = resample_set_params(fn); if (ret < 0) return ret; @@ -216,14 +210,14 @@ static int resample_post_select(__a_unused struct sched *s, void *context) ret = check_wav_post_select(ctx->cwc); if (ret < 0) goto out; + ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL); + if (ret <= 0) + goto out; if (!ctx->src_state) { ret = resample_init(fn); if (ret <= 0) goto out; } - ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL); - if (ret <= 0) - goto out; if (ctx->source_sample_rate == conf->dest_sample_rate_arg) { /* * No resampling necessary. We do not splice ourselves out diff --git a/sched.c b/sched.c index 1db9169b..bc301778 100644 --- a/sched.c +++ b/sched.c @@ -66,7 +66,10 @@ static void sched_preselect(struct sched *s) static void unlink_and_free_task(struct task *t) { - PARA_INFO_LOG("freeing task %s\n", t->name); + PARA_INFO_LOG("freeing task %s (%s)\n", t->name, t->status < 0? + para_strerror(-t->status) : + (t->status == TS_DEAD? "[dead]" : "[running]")); + list_del(&t->node); free(t->name); free(t); diff --git a/server.c b/server.c index 59a62047..a023b152 100644 --- a/server.c +++ b/server.c @@ -411,8 +411,9 @@ static int init_afs(int argc, char **argv) { int ret, afs_server_socket[2]; pid_t afs_pid; + char c; - ret = socketpair(PF_UNIX, SOCK_DGRAM, 0, afs_server_socket); + ret = socketpair(PF_UNIX, SOCK_STREAM, 0, afs_server_socket); if (ret < 0) exit(EXIT_FAILURE); get_random_bytes_or_die((unsigned char *)&afs_socket_cookie, @@ -422,6 +423,7 @@ static int init_afs(int argc, char **argv) exit(EXIT_FAILURE); if (afs_pid == 0) { /* child (afs) */ int i; + for (i = argc - 1; i >= 0; i--) memset(argv[i], 0, strlen(argv[i])); sprintf(argv[0], "para_server (afs)"); @@ -430,6 +432,10 @@ static int init_afs(int argc, char **argv) } mmd->afs_pid = afs_pid; close(afs_server_socket[1]); + if (read(afs_server_socket[0], &c, 1) <= 0) { + PARA_EMERG_LOG("early afs exit\n"); + exit(EXIT_FAILURE); + } ret = mark_fd_nonblocking(afs_server_socket[0]); if (ret < 0) exit(EXIT_FAILURE); @@ -457,7 +463,7 @@ static void server_init(int argc, char **argv) .check_ambiguity = 0, .print_errors = 1 }; - int afs_socket; + int afs_socket, daemon_pipe = -1; valid_fd_012(); init_random_seed_or_die(); @@ -477,7 +483,7 @@ static void server_init(int argc, char **argv) init_user_list(user_list_file); /* become daemon */ if (conf.daemon_given) - daemonize(true /* parent waits for SIGTERM */); + daemon_pipe = daemonize(true /* parent waits for us */); PARA_NOTICE_LOG("initializing audio format handlers\n"); afh_init(); @@ -503,8 +509,13 @@ static void server_init(int argc, char **argv) PARA_NOTICE_LOG("initializing virtual streaming system\n"); init_vss_task(afs_socket, &sched); init_server_command_task(argc, argv); - if (conf.daemon_given) - kill(getppid(), SIGTERM); + if (daemon_pipe >= 0) { + if (write(daemon_pipe, "\0", 1) < 0) { + PARA_EMERG_LOG("daemon_pipe: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + close(daemon_pipe); + } PARA_NOTICE_LOG("server init complete\n"); } @@ -526,7 +537,7 @@ out: prev_uptime = uptime; prev_events = mmd->events; mmd->vss_status_flags = mmd->new_vss_status_flags; - PARA_DEBUG_LOG("%d events, forcing status update\n", mmd->events); + PARA_DEBUG_LOG("%u events, forcing status update\n", mmd->events); killpg(0, SIGUSR1); } diff --git a/signal.h b/signal.h index b5b06f35..742f677a 100644 --- a/signal.h +++ b/signal.h @@ -16,6 +16,22 @@ struct signal_task { struct task *task; }; +/** + * A generic pre-select method for signal tasks. + * + * \param s Passed to para_fd_set(). + * \param context Signal task pointer. + * + * This convenience helper is called from several programs which need to handle + * signals, including para_server and para_audiod. These programs define a + * signal task structure and set its ->pre_select method to this function which + * adds the file descriptor of the signal task to the set of descriptors to be + * watched in the next select() call. + * + * Although the second parameter must be in fact a pointer to a signal_task + * structure, the parameter is specified as void * here to match the + * ->pre_select method of struct task. + */ _static_inline_ void signal_pre_select(struct sched *s, void *context) { struct signal_task *st = context; diff --git a/spx_afh.c b/spx_afh.c index b780635b..4e318af1 100644 --- a/spx_afh.c +++ b/spx_afh.c @@ -88,7 +88,7 @@ static int spx_get_comments(unsigned char *comments, int length, if (c + 4 > end) return -E_SPX_COMMENT; nb_fields = read_u32(c); - PARA_DEBUG_LOG("%d comment(s)\n", nb_fields); + PARA_DEBUG_LOG("%u comment(s)\n", nb_fields); c += 4; for (i = 0; i < nb_fields; i++, c += len) { char *tag; diff --git a/string.h b/string.h index aa8292fd..52f98941 100644 --- a/string.h +++ b/string.h @@ -63,7 +63,7 @@ int for_each_line(unsigned flags, char *buf, size_t size, #define WRITE_STATUS_ITEM(b, n, f, ...) (\ { \ if ((b)->flags & PBF_SIZE_PREFIX) { \ - para_printf((b), "%02x:" f, n, ## __VA_ARGS__); \ + para_printf((b), "%02x:" f, (unsigned)n, ## __VA_ARGS__); \ } else { \ para_printf((b), "%s: " f, status_item_list[(n)], \ ## __VA_ARGS__); \ diff --git a/t/t0004-server.sh b/t/t0004-server.sh index c2e809cb..1963748f 100755 --- a/t/t0004-server.sh +++ b/t/t0004-server.sh @@ -45,7 +45,7 @@ bad[$i]='.' let i++ commands[$i]="ls_ogg" required_objects[$i]='ogg_afh' -cmdline[$i]="ls -l=v ${oggs_base[@]}" +cmdline[$i]="ls -l=v -b ${oggs_base[@]}" good[$i]='^basename:' let i++ @@ -69,7 +69,7 @@ bad[$i]='.' let i++ commands[$i]="ls" required_objects[$i]='ogg_afh' -cmdline[$i]="ls -l=v -p ${oggs[@]}" +cmdline[$i]="ls -l=v -F ${oggs[@]}" good[$i]='^attributes_txt: 33' let i++ diff --git a/vss.c b/vss.c index 2acff1cb..5484db9d 100644 --- a/vss.c +++ b/vss.c @@ -611,7 +611,7 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst) for (; i < k; i++) fc->src_data[i] = (const unsigned char *)buf; } - PARA_DEBUG_LOG("FEC group %d: %d chunks (%d - %d), %d bytes\n", + PARA_DEBUG_LOG("FEC group %u: %u chunks (%u - %u), %u bytes\n", g->num, g->num_chunks, g->first_chunk, g->first_chunk + g->num_chunks - 1, g->bytes ); @@ -1027,7 +1027,7 @@ static void vss_send(struct vss_task *vsst) } if (compute_next_fec_slice(fc, vsst) <= 0) continue; - PARA_DEBUG_LOG("sending %d:%d (%u bytes)\n", fc->group.num, + PARA_DEBUG_LOG("sending %u:%u (%u bytes)\n", fc->group.num, fc->current_slice_num, fc->group.slice_bytes); fc->fcp->send_fec(fc->sc, (char *)fc->enc_buf, fc->group.slice_bytes + FEC_HEADER_SIZE); diff --git a/wav_filter.c b/wav_filter.c index 07423a14..88047adb 100644 --- a/wav_filter.c +++ b/wav_filter.c @@ -31,7 +31,7 @@ static void make_wav_header(unsigned int channels, unsigned int sample_rate, int bytespersec = channels * sample_rate * BITS / 8; int align = channels * BITS / 8; - PARA_DEBUG_LOG("writing wave header: %d channels, %d KHz\n", channels, sample_rate); + PARA_DEBUG_LOG("writing wave header: %u channels, %u KHz\n", channels, sample_rate); memset(headbuf, 0, WAV_HEADER_LEN); memcpy(headbuf, "RIFF", 4); write_u32(headbuf + 4, size - 8); diff --git a/web/download.in.html b/web/download.in.html index dd0b9c78..a09fd1c8 100644 --- a/web/download.in.html +++ b/web/download.in.html @@ -19,7 +19,7 @@ provided at this point. There are several ways to download the source: check out any of the four integration branches maint, master, next, pu (see the - git_branches + Git branches section of the manual). All previous releases correspond to tagged commits and may be checked out diff --git a/web/manual.md b/web/manual.md index 15386134..12454ee2 100644 --- a/web/manual.md +++ b/web/manual.md @@ -1813,6 +1813,33 @@ Examples Development =========== +Contributing +------------ + +Paraslash is an open source project and contributions are +welcome. Here's a list of things you can do to help the project: + +- Report problems with building, installing or running the software. + In particular, test the experimental git branches ("next" and "pu"). + This helps to identify and fix problems before the code gets merged + and thus keeps the master branch as stable as possible. +- Proofread the documentation (manual, web pages, man pages, source + code documentation) and point out unclear or poorly written parts. If + you are a native English speaker you will easily find a lot of text + that could be improved. +- Run analysis tools (coverity, afl, sparse, etc.) and report issues + found by those tools. +- Suggest new features you would like to see implemented. +- Compile and test on your favorite architecture or operating + system. The code is tested only on a limited set of systems, so you + will probably encounter problems when building on different systems. +- Post about about paraslash on your blog or on social networks. +- Build and maintain Debian/RPM packages for your favorite distribution. + +Note that there is no mailing list, no bug tracker and no discussion +forum for paraslash. If you'd like to contribute, or have questions +about contributing, send email to Andre Noll . + Tools ----- @@ -1934,7 +1961,7 @@ Coding Style The preferred coding style for paraslash coincides more or less with the style of the Linux kernel. So rather than repeating what is -written [there](http://www.kernel.org/doc/Documentation/CodingStyle), +written [there](http://www.kernel.org/doc/Documentation/process/coding-style.rst), here are the most important points. - Burn the GNU coding standards. diff --git a/wma.h b/wma.h index 15b9c5d4..b260feb9 100644 --- a/wma.h +++ b/wma.h @@ -28,6 +28,8 @@ struct asf_header_info { bool use_bit_reservoir; /** Whether blocks are of variable or of constant size. */ bool use_variable_block_len; + /** Obtained from the file properties object. */ + uint32_t packet_size; }; /* wma_common.c */ diff --git a/wma_afh.c b/wma_afh.c index 929e732b..4c9d87e0 100644 --- a/wma_afh.c +++ b/wma_afh.c @@ -18,22 +18,22 @@ #include "wma.h" #include "fd.h" -#define FOR_EACH_FRAME(_f, _buf, _size, _ba) for (_f = (_buf); \ - _f + (_ba) + WMA_FRAME_SKIP < (_buf) + (_size); \ - _f += (_ba) + WMA_FRAME_SKIP) +#define FOR_EACH_FRAME(_f, _buf, _size, _ps) for (_f = (_buf); \ + _f + (_ps) < (_buf) + (_size); \ + _f += (_ps)) /* * Must be called on a frame boundary, e.g. start + header_len. * \return Frame count, superframe count via *num_superframes. */ -static int count_frames(const char *buf, int buf_size, int block_align, +static int count_frames(const char *buf, int buf_size, uint32_t packet_size, int *num_superframes) { int fc = 0, sfc = 0; /* frame count, superframe count */ const uint8_t *p; - FOR_EACH_FRAME(p, (uint8_t *)buf, buf_size, block_align) { + FOR_EACH_FRAME(p, (uint8_t *)buf, buf_size, packet_size) { fc += p[WMA_FRAME_SKIP] & 0x0f; sfc++; } @@ -192,7 +192,7 @@ static void set_chunk_tv(int frames_per_chunk, int frequency, } /* Must be called on a frame boundary. */ -static int wma_make_chunk_table(char *buf, size_t buf_size, int block_align, +static int wma_make_chunk_table(char *buf, size_t buf_size, uint32_t packet_size, struct afh_info *afhi) { const uint8_t *f, *start = (uint8_t *)buf; @@ -204,7 +204,7 @@ static int wma_make_chunk_table(char *buf, size_t buf_size, int block_align, afhi->chunk_table[0] = 0; afhi->chunk_table[1] = afhi->header_len; - num_frames = count_frames(buf, buf_size, block_align, + num_frames = count_frames(buf, buf_size, packet_size, &num_superframes); ret = -E_NO_WMA; if (num_frames == 0 || num_superframes == 0) @@ -214,7 +214,7 @@ static int wma_make_chunk_table(char *buf, size_t buf_size, int block_align, frames_per_chunk = num_frames / num_superframes / 2; PARA_INFO_LOG("%d frames per chunk\n", frames_per_chunk); j = 1; - FOR_EACH_FRAME(f, start, buf_size, block_align) { + FOR_EACH_FRAME(f, start, buf_size, packet_size) { count += f[WMA_FRAME_SKIP] & 0x0f; while (count > j * frames_per_chunk) { j++; @@ -224,7 +224,8 @@ static int wma_make_chunk_table(char *buf, size_t buf_size, int block_align, afhi->chunk_table, ct_size * sizeof(uint32_t)); } - afhi->chunk_table[j] = f - start + afhi->header_len + block_align + WMA_FRAME_SKIP; + afhi->chunk_table[j] = f - start + afhi->header_len + + packet_size; } } afhi->chunks_total = j; @@ -262,7 +263,7 @@ static int wma_get_file_info(char *map, size_t numbytes, __a_unused int fd, ahi.use_variable_block_len? "vbl" : "" ); wma_make_chunk_table(map + ahi.header_len, numbytes - ahi.header_len, - ahi.block_align, afhi); + ahi.packet_size, afhi); read_asf_tags(map, ahi.header_len, &afhi->tags); return 0; } diff --git a/wma_common.c b/wma_common.c index 8886a061..6d57c00b 100644 --- a/wma_common.c +++ b/wma_common.c @@ -42,6 +42,17 @@ const char *search_pattern(const char *pattern, int pattern_len, return NULL; } +static int find_file_properties(const char *buf, int len) +{ + const char pattern[] = {0xa1, 0xdc, 0xab, 0x8c}; + const char *p = search_pattern(pattern, sizeof(pattern), buf, len); + + if (!p) + return -E_WMA_NO_GUID; + PARA_DEBUG_LOG("found file property guid@%0x\n", (unsigned)(p - buf)); + return p - buf + 16; +} + /* 40 9e 69 f8 4d 5b cf 11 a8 fd 00 80 5f 5c 44 2b */ @@ -52,7 +63,7 @@ static int find_audio_stream_info(const char *buf, int len) if (!p) return -E_WMA_NO_GUID; - PARA_DEBUG_LOG("found audio stream guid@%0x\n", (int)(p - buf)); + PARA_DEBUG_LOG("found audio stream guid@%0x\n", (unsigned)(p - buf)); return p - buf + 16; } @@ -100,18 +111,33 @@ int read_asf_header(const char *buf, int loaded, struct asf_header_info *ahi) ahi->sample_rate); ahi->bit_rate = 8 * read_u16(start + 46); - PARA_INFO_LOG("bit rate: %d\n", ahi->bit_rate); + PARA_INFO_LOG("bit rate: %u\n", ahi->bit_rate); ahi->block_align = read_u16(start + 50); PARA_INFO_LOG("block_align: %d\n", ahi->block_align); ahi->flags1 = read_u32(start + 56); ahi->flags2 = read_u16(start + 60); - PARA_INFO_LOG("read_asf_header: flags1: %d, flag2: %d\n", + PARA_INFO_LOG("read_asf_header: flags1: %u, flags2: %u\n", ahi->flags1, ahi->flags2); ahi->use_exp_vlc = ahi->flags2 & 0x0001; ahi->use_bit_reservoir = ahi->flags2 & 0x0002; ahi->use_variable_block_len = ahi->flags2 & 0x0004; + + ret = find_file_properties(buf, ahi->header_len); + if (ret < 0) + return ret; + /* file property header is always 88 bytes (sans GUID) */ + if (ret + 88 > loaded) + return 0; + start = buf + ret; + ahi->packet_size = read_u32(start + 76); /* min packet size */ + /* we only support fixed packet sizes */ + if (ahi->packet_size != read_u32(start + 80)) /* min != max */ + return -E_BAD_ASF_FILE_PROPS; + if (ahi->packet_size <= ahi->block_align) + return -E_BAD_ASF_FILE_PROPS; + PARA_INFO_LOG("packet size: %u\n", ahi->packet_size); return 1; } diff --git a/wmadec_filter.c b/wmadec_filter.c index 0dff2b79..4c7c047a 100644 --- a/wmadec_filter.c +++ b/wmadec_filter.c @@ -371,8 +371,8 @@ static int wma_init(struct private_wmadec_data *pwd) else high_freq = high_freq * 0.5; } - PARA_INFO_LOG("channels=%d sample_rate=%d " - "bitrate=%d block_align=%d\n", + PARA_INFO_LOG("channels=%u sample_rate=%u " + "bitrate=%u block_align=%d\n", ahi->channels, ahi->sample_rate, ahi->bit_rate, ahi->block_align); PARA_INFO_LOG("frame_len=%d, bps=%f bps1=%f " @@ -1028,7 +1028,7 @@ static inline int16_t av_clip_int16(int a) /* Decode a frame of frame_len samples. */ static int wma_decode_frame(struct private_wmadec_data *pwd, int16_t *samples) { - int ret, i, n, ch, incr; + int ret, i, ch; int16_t *ptr; float *iptr; @@ -1043,15 +1043,13 @@ static int wma_decode_frame(struct private_wmadec_data *pwd, int16_t *samples) } /* convert frame to integer */ - n = pwd->frame_len; - incr = pwd->ahi.channels; for (ch = 0; ch < pwd->ahi.channels; ch++) { ptr = samples + ch; iptr = pwd->frame_out[ch]; - for (i = 0; i < n; i++) { + for (i = 0; i < pwd->frame_len; i++) { *ptr = av_clip_int16(lrintf(*iptr++)); - ptr += incr; + ptr += pwd->ahi.channels; } /* prepare for next block */ memmove(&pwd->frame_out[ch][0], &pwd->frame_out[ch][pwd->frame_len], @@ -1068,10 +1066,13 @@ static int wma_decode_superframe(struct private_wmadec_data *pwd, void *data, if (buf_size == 0) { pwd->last_superframe_len = 0; + *data_size = 0; return 0; } - if (buf_size < pwd->ahi.block_align) + if (buf_size < pwd->ahi.block_align) { + *data_size = 0; return 0; + } buf_size = pwd->ahi.block_align; samples = data; init_get_bits(&pwd->gb, buf, buf_size); @@ -1209,7 +1210,7 @@ next_buffer: if (ret == 0) return 0; btr_merge(btrn, fn->min_iqs); - len = btr_next_buffer(btrn, (char **)&in); + len = btr_next_buffer(btrn, &in); ret = -E_WMADEC_EOF; if (len < fn->min_iqs) goto err; @@ -1221,12 +1222,12 @@ next_buffer: fn->min_iqs += 4096; goto next_buffer; } - fn->min_iqs = 2 * (WMA_FRAME_SKIP + pwd->ahi.block_align); + fn->min_iqs = 2 * pwd->ahi.packet_size; fn->private_data = pwd; converted = pwd->ahi.header_len; goto success; } - fn->min_iqs = WMA_FRAME_SKIP + pwd->ahi.block_align; + fn->min_iqs = pwd->ahi.packet_size; if (fn->min_iqs > len) goto success; out_size = WMA_OUTPUT_BUFFER_SIZE; @@ -1237,10 +1238,12 @@ next_buffer: free(out); goto err; } - out = para_realloc(out, out_size); - if (out_size > 0) + if (out_size > 0) { + out = para_realloc(out, out_size); btr_add_output(out, out_size, btrn); - converted += ret + WMA_FRAME_SKIP; + } else + free(out); + converted += pwd->ahi.packet_size; success: btr_consume(btrn, converted); return 0;