Merge branch 'refs/heads/t/invalid-ids'
authorAndre Noll <maan@tuebingen.mpg.de>
Fri, 30 Dec 2016 14:58:41 +0000 (15:58 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Fri, 30 Dec 2016 15:00:38 +0000 (16:00 +0100)
A single patch that was in misc for a while, and two follow up fixups
that were detected after the branch was merged into next.

* refs/heads/t/invalid-ids (cooking for two weeks):
  Makefile: Don't compile with -Wformat-signedness unconditionally.
  aft.c: Use correct format string for error output.
  touch: Refuse to set an invalid image or lyrics ID.

62 files changed:
Doxyfile
Makefile.real
NEWS.md
aac.h
aac_afh.c
aac_common.c
aacdec_filter.c
acl.c
afh.h
afh_common.c
afh_recv.c
afs.c
afs.cmd
aft.c
alsa_mix.c
alsa_write.c
audiod.c
base64.c [new file with mode: 0644]
base64.h [new file with mode: 0644]
blob.c
check_wav.c
client.c
client_common.c
command.c
configure.ac
crypt.c
crypt_backend.h
crypt_common.c
daemon.c
daemon.h
error.h
fade.c
fecdec_filter.c
file_write.c
filter_common.c
flac_afh.c
gcrypt.c
gui.c
mood.c
mp3_afh.c
net.c
ogg_afh.c
ogg_afh_common.c
oggdec_filter.c
opus_afh.c
oss_write.c
play.c
portable_io.h
resample_filter.c
sched.c
server.c
spx_afh.c
string.h
t/t0004-server.sh
vss.c
wav_filter.c
web/documentation.in.html
web/download.in.html
wma.h
wma_afh.c
wma_common.c
wmadec_filter.c

index 50c7469..df6c87f 100644 (file)
--- a/Doxyfile
+++ b/Doxyfile
@@ -797,7 +797,6 @@ EXCLUDE_SYMLINKS       = NO
 
 EXCLUDE_PATTERNS       = *.cmdline.* \
                          gcc-compat.h \
-                         fade.c \
                          *.command_list.h \
                          *.completion.h
 
index ce4881d..464cd68 100644 (file)
@@ -128,6 +128,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 71eb6cb..3d00528 100644 (file)
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,6 +1,24 @@
 NEWS
 ====
 
+------------------------------------------
+0.5.7 (to be announced) "semantic density"
+------------------------------------------
+- Speedup of the base64 decoder.
+- 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.
+
+Download: [tarball](./releases/paraslash-git.tar.bz2)
+
 ---------------------------------------
 0.5.6 (2016-07-10) "cascading gradient"
 ---------------------------------------
@@ -25,6 +43,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 f31d723..eeed252 100644 (file)
--- a/aac.h
+++ b/aac.h
@@ -9,12 +9,6 @@
 #include <neaacdec.h>
 
 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);
index c49f30d..1c7fd70 100644 (file)
--- a/aac_afh.c
+++ b/aac_afh.c
 
 #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;
index fe9b729..812c742 100644 (file)
@@ -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;
index ac8148e..5725ce0 100644 (file)
@@ -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 5ef9a51..560ff99 100644 (file)
--- 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 dad6735..a6f9c50 100644 (file)
--- 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;
index f36c32e..dfbf751 100644 (file)
@@ -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;
 }
 
 /**
index 1646346..28d8f39 100644 (file)
@@ -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 0accc45..0946b6d 100644 (file)
--- 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 584ba80..76b5f4d 100644 (file)
--- 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 e48708a..bfcd1fb 100644 (file)
--- 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;
@@ -2637,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");
index cad58af..3adee92 100644 (file)
@@ -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;
index 63a7055..fd3b404 100644 (file)
@@ -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) {
index 285d276..bd97f15 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -764,7 +764,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++;
@@ -1378,7 +1378,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/base64.c b/base64.c
new file mode 100644 (file)
index 0000000..7b8fe29
--- /dev/null
+++ b/base64.c
@@ -0,0 +1,205 @@
+/*
+ * The code in this file was taken from openssh-5.2p1, Copyright (c) 1996 by
+ * Internet Software Consortium.  Portions Copyright (c) 1995 by International
+ * Business Machines, Inc.
+ */
+
+/** \file base64.c Uudecode and base64decode implementation. */
+
+#include <regex.h>
+
+#include "para.h"
+#include "error.h"
+#include "base64.h"
+#include "string.h"
+
+static const char Base64[] =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const unsigned char base64_tab[256] = {
+       255, 255, 255, 255, 255, 255, 255, 255, /* 00-07 */
+       255, 255, 255, 255, 255, 255, 255, 255, /* 08-0f */
+       255, 255, 255, 255, 255, 255, 255, 255, /* 10-17 */
+       255, 255, 255, 255, 255, 255, 255, 255, /* 18-1f */
+       255, 255, 255, 255, 255, 255, 255, 255, /* 20-2f */
+       255, 255, 255,  62, 255, 255, 255,  63, /* 28-2f */
+       52 ,  53,  54,  55,  56,  57,  58,  59, /* 30-37 */
+       60 ,  61, 255, 255, 255, 255, 255, 255, /* 38-3f */
+       255,   0,   1,   2,   3,   4,   5,   6, /* 40-47 */
+       7  ,   8,   9,  10,  11,  12,  13,  14, /* 48-4f */
+       15 ,  16,  17,  18,  19,  20,  21,  22, /* 50-57 */
+       23 ,  24,  25, 255, 255, 255, 255, 255, /* 58-5f */
+       255,  26,  27,  28,  29,  30,  31,  32, /* 60-6f */
+       33 ,  34,  35,  36,  37,  38,  39,  40, /* 68-6f */
+       41 ,  42,  43,  44,  45,  46,  47,  48, /* 70-77 */
+       49 ,  50,  51, 255, 255, 255, 255, 255, /* 78-7f */
+       255, 255, 255, 255, 255, 255, 255, 255, /* 80-87 */
+       255, 255, 255, 255, 255, 255, 255, 255, /* 88-8f */
+       255, 255, 255, 255, 255, 255, 255, 255, /* 90-97 */
+       255, 255, 255, 255, 255, 255, 255, 255, /* 98-9f */
+       255, 255, 255, 255, 255, 255, 255, 255, /* a0-a7 */
+       255, 255, 255, 255, 255, 255, 255, 255, /* a8-af */
+       255, 255, 255, 255, 255, 255, 255, 255, /* b0-b7 */
+       255, 255, 255, 255, 255, 255, 255, 255, /* b8-bf */
+       255, 255, 255, 255, 255, 255, 255, 255, /* c0-c7 */
+       255, 255, 255, 255, 255, 255, 255, 255, /* c8-cf */
+       255, 255, 255, 255, 255, 255, 255, 255, /* d0-d7 */
+       255, 255, 255, 255, 255, 255, 255, 255, /* d8-df */
+       255, 255, 255, 255, 255, 255, 255, 255, /* e0-e7 */
+       255, 255, 255, 255, 255, 255, 255, 255, /* e8-ef */
+       255, 255, 255, 255, 255, 255, 255, 255, /* f0-f7 */
+       255, 255, 255, 255, 255, 255, 255, 255, /* f8-ff */
+};
+
+/** Maximal possible size of the decoded data. */
+#define BASE64_MAX_DECODED_SIZE(_encoded_size) ((_encoded_size) / 4 * 3)
+
+#define PAD64 '='
+/**
+ * base64-decode a buffer.
+ *
+ * \param src The buffer to decode.
+ * \param encoded_size The special value -1 means: look for terminating zero byte.
+ * \param result Points to dynamically allocated target buffer on success.
+ * \param decoded_size Number of bytes written to \a result.
+ *
+ * Skips all whitespace anywhere. Converts characters, four at a time, starting
+ * at (or after) src from base - 64 numbers into three 8 bit bytes in the
+ * target area.
+ *
+ * It is OK to pass a \p NULL pointer as \a decoded_size. The result is
+ * terminated with a zero byte.
+ *
+ * \return Standard. The contents of result \a and \a decoded_size are
+ * undefined on failure.
+ */
+int base64_decode(char const *src, size_t encoded_size, char **result,
+               size_t *decoded_size)
+{
+       size_t i, j, state; /* source/target indices */
+       const char *end = src + encoded_size, *p;
+       unsigned char *target, uch;
+
+       if (encoded_size == (size_t)-1)
+               encoded_size = strlen(src);
+       target = para_malloc(BASE64_MAX_DECODED_SIZE(encoded_size) + 1);
+
+       for (
+               i = 0, j = 0, state = 0;
+               i < encoded_size && (uch = src[i]) != '\0';
+               i++
+       ) {
+               if (para_isspace(uch)) /* Skip whitespace anywhere. */
+                       continue;
+               if (uch == PAD64)
+                       break;
+               if (base64_tab[uch] == 255) /* A non-base64 character. */
+                       goto fail;
+               uch = base64_tab[uch];
+               switch (state) {
+               case 0:
+                       target[j] = uch << 2;
+                       break;
+               case 1:
+                       target[j] |= uch >> 4;
+                       j++;
+                       target[j] = (uch & 0x0f) << 4;
+                       break;
+               case 2:
+                       target[j] |= uch >> 2;
+                       j++;
+                       target[j] = (uch & 0x03) << 6;
+                       break;
+               case 3:
+                       target[j] |= uch;
+                       j++;
+                       break;
+               }
+               state = (state + 1) % 4;
+       }
+       p = (i < encoded_size)? src + i : NULL;
+       /*
+        * We are done decoding Base-64 chars.  Let's see if we ended
+        * on a byte boundary, and/or with erroneous trailing characters.
+        */
+       if (p && *p == PAD64) { /* We got a pad char. Skip it, get next. */
+               p++;
+               switch (state) {
+               case 0: /* Invalid = in first position */
+               case 1: /* Invalid = in second position */
+                       goto fail;
+
+               case 2: /* Valid, means one byte of info */
+                       /* Skip any number of spaces. */
+                       for (; p < end && *p != '\0'; p++)
+                               if (!para_isspace(*p))
+                                       break;
+                       /* Make sure there is another trailing = sign. */
+                       if (*p != PAD64)
+                               goto fail;
+                       /* Fall through to "single trailing =" case. */
+                       p++;
+
+               case 3: /* Valid, means two bytes of info */
+                       /*
+                        * We know this char is an =.  Is there anything but
+                        * whitespace after it?
+                        */
+                       for (; p < end && *p != '\0'; p++)
+                               if (!para_isspace(*p))
+                                       goto fail;
+                       /*
+                        * Now make sure for cases 2 and 3 that the "extra"
+                        * bits that slopped past the last full byte were
+                        * zeros.  If we don't check them, they become a
+                        * subliminal channel.
+                        */
+                       if (target[j] != 0)
+                               goto fail;
+               }
+       } else {
+               /*
+                * We ended by seeing the end of the string.  Make sure we
+                * have no partial bytes lying around.
+                */
+               if (state != 0)
+                       goto fail;
+       }
+       /* success */
+       target[j] = '\0'; /* just to be sure */
+       if (decoded_size)
+               *decoded_size = j;
+       *result = (char *)target;
+       return 1;
+fail:
+       free(target);
+       return -E_BASE64;
+}
+
+/**
+ * Decode a buffer using the uuencode Base64 algorithm.
+ *
+ * \param src The buffer to decode.
+ * \param encoded_size Number of input bytes in the source buffer.
+ * \param result Contains the decoded data on success.
+ * \param decoded_size Number of output bytes on success.
+ *
+ * This is just a simple wrapper for \ref base64_decode() which strips
+ * whitespace.
+ *
+ * \return The return value of the underlying call to \ref base64_decode().
+ *
+ * \sa uuencode(1), uudecode(1).
+ */
+int uudecode(char const *src, size_t encoded_size, char **result,
+               size_t *decoded_size)
+{
+       const char *end = src + encoded_size, *p;
+
+       /* skip whitespace and data */
+       for (p = src; p < end && (*p == ' ' || *p == '\t'); p++)
+               ;
+       for (; p < end && *p != '\0' && *p != ' ' && *p != '\t'; p++)
+               ;
+       /* and remove trailing whitespace because base64_decode needs this */
+       return base64_decode(src, p - src, result, decoded_size);
+}
diff --git a/base64.h b/base64.h
new file mode 100644 (file)
index 0000000..4bfaa99
--- /dev/null
+++ b/base64.h
@@ -0,0 +1,4 @@
+int uudecode(char const *src, size_t encoded_size, char **result,
+               size_t *decoded_size);
+int base64_decode(char const *src, size_t encoded_size, char **result,
+               size_t *decoded_size);
diff --git a/blob.c b/blob.c
index 737f198..ed68442 100644 (file)
--- 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);
        }
index d1d2787..1a47f94 100644 (file)
@@ -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);
index 31cfff0..64b1553 100644 (file)
--- a/client.c
+++ b/client.c
@@ -278,7 +278,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);
index cd1ccc6..eea7510 100644 (file)
@@ -292,11 +292,6 @@ static int client_post_select(struct sched *s, void *context)
                if (ret < 0 || n == 0)
                        goto out;
                ct->features = parse_features(buf);
-               if (!has_feature("sideband", ct)) {
-                       PARA_ERROR_LOG("server has no sideband support\n");
-                       ret = -E_INCOMPAT_FEAT;
-                       goto out;
-               }
                ct->status = CL_RECEIVED_WELCOME;
                return 0;
        case CL_RECEIVED_WELCOME: /* send auth command */
index 93de2d2..fe4b923 100644 (file)
--- 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;
@@ -807,7 +807,6 @@ static void reset_signals(void)
 }
 
 struct connection_features {
-       bool sideband_requested;
        bool aes_ctr128_requested;
 };
 
@@ -835,8 +834,8 @@ static int parse_auth_request(char *buf, int len, struct user **u,
                create_argv(p, ",", &features);
                for (i = 0; features[i]; i++) {
                        if (strcmp(features[i], "sideband") == 0)
-                               cf->sideband_requested = true;
-                       else if (strcmp(features[i], "aes_ctr128") == 0)
+                               continue;
+                       if (strcmp(features[i], "aes_ctr128") == 0)
                                cf->aes_ctr128_requested = true;
                        else {
                                ret = -E_BAD_FEATURE;
@@ -949,11 +948,6 @@ __noreturn void handle_connect(int fd, const char *peername)
        ret = parse_auth_request(buf, ret, &cc->u, &cf);
        if (ret < 0)
                goto net_err;
-       if (!cf.sideband_requested) { /* sideband is mandatory */
-               PARA_ERROR_LOG("client did not request sideband\n");
-               ret = -E_BAD_FEATURE;
-               goto net_err;
-       }
        if (cc->u) {
                get_random_bytes_or_die(rand_buf, sizeof(rand_buf));
                ret = pub_encrypt(cc->u->pubkey, rand_buf, sizeof(rand_buf),
@@ -970,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;
index f9115fd..74f3fd9 100644 (file)
@@ -116,6 +116,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
@@ -418,6 +422,7 @@ if test -n "$CRYPTOLIB" && test $HAVE_OSL = yes; then
                close_on_fork
                mm
                crypt_common
+               base64
                ipc
                dccp_send
                fd
@@ -480,6 +485,7 @@ if test -n "$CRYPTOLIB"; then
                client_common
                buffer_tree
                crypt_common
+               base64
                version
                ggo
        "
@@ -523,6 +529,7 @@ if test -n "$CRYPTOLIB"; then
                stat
                net
                crypt_common
+               base64
                sideband
                time
                grab_client
diff --git a/crypt.c b/crypt.c
index 610d205..8116fb6 100644 (file)
--- a/crypt.c
+++ b/crypt.c
@@ -23,6 +23,7 @@
 #include "crypt.h"
 #include "fd.h"
 #include "crypt_backend.h"
+#include "base64.h"
 
 struct asymmetric_key {
        RSA *rsa;
@@ -133,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:
@@ -158,7 +166,7 @@ int get_asymmetric_key(const char *key_file, int private,
        struct asymmetric_key *key = NULL;
        void *map = NULL;
        unsigned char *blob = NULL;
-       size_t map_size, blob_size, decoded_size;
+       size_t map_size, encoded_size, decoded_size;
        int ret, ret2;
        char *cp;
 
@@ -180,16 +188,11 @@ int get_asymmetric_key(const char *key_file, int private,
                goto out;
        }
        cp = map + ret;
+       encoded_size = map_size - ret;
        PARA_INFO_LOG("decoding public rsa-ssh key %s\n", key_file);
-       ret = -ERRNO_TO_PARA_ERROR(EOVERFLOW);
-       if (map_size > INT_MAX / 4)
-               goto out_unmap;
-       blob_size = 2 * map_size;
-       blob = para_malloc(blob_size);
-       ret = uudecode(cp, blob, blob_size);
+       ret = uudecode(cp, encoded_size, (char **)&blob, &decoded_size);
        if (ret < 0)
                goto out_unmap;
-       decoded_size = ret;
        ret = check_ssh_key_header(blob, decoded_size);
        if (ret < 0)
                goto out_unmap;
@@ -260,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) {
@@ -288,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);
 }
 
@@ -332,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);
 }
 
index 06c86d7..f9a69d9 100644 (file)
@@ -13,7 +13,5 @@
 
 size_t is_ssh_rsa_key(char *data, size_t size);
 uint32_t read_ssh_u32(const void *vp);
-int uudecode(const char *src, unsigned char *target, size_t targsize);
 int check_ssh_key_header(const unsigned char *blob, int blen);
 int check_key_file(const char *file, bool private_key);
-int base64_decode(char const *src, unsigned char *target, size_t targsize);
index 022692a..a05572d 100644 (file)
@@ -45,166 +45,6 @@ size_t is_ssh_rsa_key(char *data, size_t size)
        return cp - data;
 }
 
-/*
- * This base64/uudecode stuff below is taken from openssh-5.2p1, Copyright (c)
- * 1996 by Internet Software Consortium.  Portions Copyright (c) 1995 by
- * International Business Machines, Inc.
- */
-
-static const char Base64[] =
-       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static const char Pad64 = '=';
-
-/**
- * base64-decode a buffer.
- *
- * \param src The buffer to decode.
- * \param target Result is stored here.
- * \param targsize Number of bytes of \a target.
- *
- * Skips all whitespace anywhere. Converts characters, four at a time, starting
- * at (or after) src from base - 64 numbers into three 8 bit bytes in the
- * target area.
- *
- * \return The number of data bytes stored at the target, -E_BASE64 on errors.
- */
-int base64_decode(char const *src, unsigned char *target, size_t targsize)
-{
-       unsigned int tarindex, state;
-       int ch;
-       char *pos;
-
-       state = 0;
-       tarindex = 0;
-
-       while ((ch = *src++) != '\0') {
-               if (para_isspace(ch)) /* Skip whitespace anywhere. */
-                       continue;
-
-               if (ch == Pad64)
-                       break;
-
-               pos = strchr(Base64, ch);
-               if (pos == NULL) /* A non-base64 character. */
-                       return -E_BASE64;
-
-               switch (state) {
-               case 0:
-                       if (tarindex >= targsize)
-                               return -E_BASE64;
-                       target[tarindex] = (pos - Base64) << 2;
-                       state = 1;
-                       break;
-               case 1:
-                       if (tarindex + 1 >= targsize)
-                               return -E_BASE64;
-                       target[tarindex] |= (pos - Base64) >> 4;
-                       target[tarindex + 1] = ((pos - Base64) & 0x0f) << 4;
-                       tarindex++;
-                       state = 2;
-                       break;
-               case 2:
-                       if (tarindex + 1 >= targsize)
-                               return -E_BASE64;
-                       target[tarindex] |= (pos - Base64) >> 2;
-                       target[tarindex + 1] = ((pos - Base64) & 0x03) << 6;
-                       tarindex++;
-                       state = 3;
-                       break;
-               case 3:
-                       if (tarindex >= targsize)
-                               return -E_BASE64;
-                       target[tarindex] |= pos - Base64;
-                       tarindex++;
-                       state = 0;
-                       break;
-               }
-       }
-
-       /*
-        * We are done decoding Base-64 chars.  Let's see if we ended
-        * on a byte boundary, and/or with erroneous trailing characters.
-        */
-
-       if (ch == Pad64) {              /* We got a pad char. */
-               ch = *src++;            /* Skip it, get next. */
-               switch (state) {
-               case 0:         /* Invalid = in first position */
-               case 1:         /* Invalid = in second position */
-                       return -E_BASE64;
-
-               case 2:         /* Valid, means one byte of info */
-                       /* Skip any number of spaces. */
-                       for (; ch != '\0'; ch = *src++)
-                               if (!isspace(ch))
-                                       break;
-                       /* Make sure there is another trailing = sign. */
-                       if (ch != Pad64)
-                               return -E_BASE64;
-                       ch = *src++;            /* Skip the = */
-                       /* Fall through to "single trailing =" case. */
-                       /* FALLTHROUGH */
-
-               case 3:         /* Valid, means two bytes of info */
-                       /*
-                        * We know this char is an =.  Is there anything but
-                        * whitespace after it?
-                        */
-                       for (; ch != '\0'; ch = *src++)
-                               if (!isspace(ch))
-                                       return -E_BASE64;
-
-                       /*
-                        * Now make sure for cases 2 and 3 that the "extra"
-                        * bits that slopped past the last full byte were
-                        * zeros.  If we don't check them, they become a
-                        * subliminal channel.
-                        */
-                       if (target[tarindex] != 0)
-                               return -E_BASE64;
-               }
-       } else {
-               /*
-                * We ended by seeing the end of the string.  Make sure we
-                * have no partial bytes lying around.
-                */
-               if (state != 0)
-                       return -E_BASE64;
-       }
-
-       return tarindex;
-}
-
-/**
- * uudecode a buffer.
- *
- * \param src The buffer to decode.
- * \param target Result buffer.
- * \param targsize The length of \a target in bytes.
- *
- * This is just a simple wrapper for base64_decode() which strips whitespace.
- *
- * \return The return value of the underlying call to base64_decode().
- */
-int uudecode(const char *src, unsigned char *target, size_t targsize)
-{
-       int len;
-       char *encoded, *p;
-
-       /* copy the 'readonly' source */
-       encoded = para_strdup(src);
-       /* skip whitespace and data */
-       for (p = encoded; *p == ' ' || *p == '\t'; p++)
-               ;
-       for (; *p != '\0' && *p != ' ' && *p != '\t'; p++)
-               ;
-       /* and remove trailing whitespace because base64_decode needs this */
-       *p = '\0';
-       len = base64_decode(encoded, target, targsize);
-       free(encoded);
-       return len;
-}
-
 /**
  * Read a 4-byte number from a buffer in big-endian format.
  *
@@ -256,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;
index 7c625bb..20cdc6a 100644 (file)
--- 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);
index c715360..989678d 100644 (file)
--- 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 337160c..a2f719f 100644 (file)
--- a/error.h
+++ b/error.h
@@ -148,6 +148,7 @@ extern const char **para_errlist[];
 
 
 #define WMA_COMMON_ERRORS \
+       PARA_ERROR(BAD_ASF_FILE_PROPS, "invalid ASF file properties"), \
        PARA_ERROR(WMA_NO_GUID, "audio stream guid not found"), \
 
 
@@ -306,7 +307,6 @@ extern const char **para_errlist[];
        PARA_ERROR(SERVER_EOF, "connection closed by para_server"), \
        PARA_ERROR(SERVER_CMD_SUCCESS, "command terminated successfully"), \
        PARA_ERROR(SERVER_CMD_FAILURE, "command failed"), \
-       PARA_ERROR(INCOMPAT_FEAT, "client/server incompatibility"), \
 
 
 #define NET_ERRORS \
@@ -440,9 +440,10 @@ extern const char **para_errlist[];
 
 #define CRYPT_COMMON_ERRORS \
        PARA_ERROR(SSH_KEY_HEADER, "ssh key header not found"), \
-       PARA_ERROR(BASE64, "failed to base64-decode ssh public key"), \
        PARA_ERROR(KEY_PERM, "unprotected private key"), \
 
+#define BASE64_ERRORS \
+       PARA_ERROR(BASE64, "base64 decode error"), \
 
 #define CRYPT_ERRORS \
        PARA_ERROR(PRIVATE_KEY, "can not read private key"), \
diff --git a/fade.c b/fade.c
index e05e317..2a001eb 100644 (file)
--- a/fade.c
+++ b/fade.c
@@ -67,7 +67,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) {
@@ -203,7 +203,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) {
@@ -333,6 +333,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;
index 26ea24a..1c3a378 100644 (file)
@@ -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;
index ef25b0f..5e66607 100644 (file)
@@ -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;
index 84863b3..e9b97e5 100644 (file)
@@ -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);
index 2e2842b..385d4f0 100644 (file)
@@ -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;
index 3c6c1ad..7c19aeb 100644 (file)
--- a/gcrypt.c
+++ b/gcrypt.c
@@ -15,6 +15,7 @@
 #include "crypt.h"
 #include "crypt_backend.h"
 #include "fd.h"
+#include "base64.h"
 
 //#define GCRYPT_DEBUG 1
 
@@ -239,12 +240,11 @@ static int decode_key(const char *key_file, const char *header_str,
                key[j++] = begin[i];
        }
        key[j] = '\0';
-       blob_size = key_size * 2;
-       blob = para_malloc(blob_size);
-       ret = base64_decode(key, blob, blob_size);
+       ret = base64_decode(key, j, (char **)&blob, &blob_size);
        free(key);
        if (ret < 0)
                goto free_unmap;
+       ret = blob_size;
        goto unmap;
 free_unmap:
        free(blob);
@@ -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);
@@ -606,13 +606,9 @@ static int get_ssh_public_key(unsigned char *data, int size, gcry_sexp_t *result
        gcry_mpi_t e = NULL, n = NULL;
 
        PARA_DEBUG_LOG("decoding %d byte public rsa-ssh key\n", size);
-       if (size > INT_MAX / 4)
-               return -ERRNO_TO_PARA_ERROR(EOVERFLOW);
-       blob = para_malloc(2 * size);
-       ret = uudecode((char *)data, blob, 2 * size);
+       ret = uudecode((char *)data, size, (char **)&blob, &decoded_size);
        if (ret < 0)
                goto free_blob;
-       decoded_size = ret;
        end = blob + decoded_size;
        dump_buffer("decoded key", blob, decoded_size);
        ret = check_ssh_key_header(blob, decoded_size);
@@ -652,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 b0eae64..3e01340 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -1160,7 +1160,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 940d72a..79f47e5 100644 (file)
--- 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);
 }
 
index 70f2ec9..2115f71 100644 (file)
--- 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 1369498..fa7cd4b 100644 (file)
--- 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;
index 29f0896..2ddf0ee 100644 (file)
--- 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);
 }
 
index e49b803..adab7f4 100644 (file)
@@ -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)
index 4b80135..04be702 100644 (file)
@@ -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:
index b1469b4..64eeb03 100644 (file)
@@ -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;
 
index 12cf8b6..2018666 100644 (file)
@@ -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 d2539ee..46e8ff7 100644 (file)
--- 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);
 }
index f1a3892..4e10c2e 100644 (file)
@@ -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);
+}
index 6a285ec..1699ed2 100644 (file)
@@ -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 1db9169..bc30177 100644 (file)
--- 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);
index 088cc8b..1f93194 100644 (file)
--- 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);
 }
 
index b780635..4e318af 100644 (file)
--- 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;
index aa8292f..52f9894 100644 (file)
--- 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__); \
index c2e809c..1963748 100755 (executable)
@@ -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 2acff1c..5484db9 100644 (file)
--- 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);
index 07423a1..88047ad 100644 (file)
@@ -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);
index f292af2..b226943 100644 (file)
 <h2> Source code documentation </h2>
 
 <ul>
-
-       <li> <a href="doxygen/html/index.html">API
-       Reference</a>. </li>
-
-       <li> <a href="HTML/index.html">Browsable source</a>. </li>
-
+       <li> <a href="doxygen/html/index.html">API Reference</a> </li>
 </ul>
index dd0b9c7..a09fd1c 100644 (file)
@@ -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
 
-               <a href="manual.html#git_branches">git_branches</a>
+               <a href="manual.html#Git.branches">Git branches</a>
 
                section of the manual). All previous releases
                correspond to tagged commits and may be checked out
diff --git a/wma.h b/wma.h
index 15b9c5d..b260feb 100644 (file)
--- 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 */
index 929e732..4c9d87e 100644 (file)
--- a/wma_afh.c
+++ b/wma_afh.c
 #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;
 }
index 8886a06..6d57c00 100644 (file)
@@ -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;
 }
 
index 0dff2b7..4c7c047 100644 (file)
@@ -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;