EXCLUDE_PATTERNS = *.cmdline.* \
gcc-compat.h \
- fade.c \
*.command_list.h \
*.completion.h
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")
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"
---------------------------------------
- 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)
#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);
#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';
}
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;
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;
}
}
-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) {
}
}
-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);
}
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;
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)
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;
#include "para.h"
#include "aac.h"
#include "error.h"
+#include "portable_io.h"
/**
* Get a new libfaad decoder handle.
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;
*
* \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++;
* \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;
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;
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) {
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) {
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;
}
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;
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)
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);
}
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);
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;
/** 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;
* 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;
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;
}
/**
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;
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);
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:
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;
}
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.
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
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);
}
}
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,
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",
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;
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");
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;
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) {
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++;
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);
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+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);
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);
}
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);
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);
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 */
#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
);
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;
}
struct connection_features {
- bool sideband_requested;
bool aes_ctr128_requested;
};
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;
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),
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;
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
close_on_fork
mm
crypt_common
+ base64
ipc
dccp_send
fd
client_common
buffer_tree
crypt_common
+ base64
version
ggo
"
stat
net
crypt_common
+ base64
sideband
time
grab_client
#include "crypt.h"
#include "fd.h"
#include "crypt_backend.h"
+#include "base64.h"
struct asymmetric_key {
RSA *rsa;
{
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:
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;
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;
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) {
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);
}
((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);
}
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);
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.
*
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;
return me->flags & flag;
}
-static void dummy_sighandler(__a_unused int s)
-{
-}
-
/**
* Do the usual stuff to become a daemon.
*
*
* 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;
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);
/** \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);
#define WMA_COMMON_ERRORS \
+ PARA_ERROR(BAD_ASF_FILE_PROPS, "invalid ASF file properties"), \
PARA_ERROR(WMA_NO_GUID, "audio stream guid not found"), \
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 \
#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"), \
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) {
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) {
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;
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)
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;
}
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;
}
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)
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;
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;
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);
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;
#include "crypt.h"
#include "crypt_backend.h"
#include "fd.h"
+#include "base64.h"
//#define GCRYPT_DEBUG 1
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);
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",
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);
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);
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:
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));
}
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);
}
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);
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;
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);
}
{
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;
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 */
#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)
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:
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;
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;
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;
/* 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)
.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);
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;
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);
}
* 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)
{
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);
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;
}
}
{
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);
+}
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;
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
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);
{
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,
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)");
}
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);
.check_ambiguity = 0,
.print_errors = 1
};
- int afs_socket;
+ int afs_socket, daemon_pipe = -1;
valid_fd_012();
init_random_seed_or_die();
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();
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");
}
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);
}
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;
#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__); \
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++
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++
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
);
}
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);
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);
<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>
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
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 */
#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++;
}
}
/* 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;
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)
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++;
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;
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;
}
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
*/
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;
}
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;
}
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 "
/* 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;
}
/* 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],
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);
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;
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;
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;