Coverage Report

Created: 2024-07-27 06:25

/src/mpg123/src/libmpg123/readers.c
Line
Count
Source (jump to first uncovered line)
1
/* TODO: Check all read calls (in loops, especially!) for return value 0 (EOF)! */
2
/* Check if get_fileinfo should read ID3 info or not, seems a bit out of place here. */
3
/* #define EXTRA_DEBUG */
4
/*
5
  readers.c: reading input data
6
7
  copyright ?-2023 by the mpg123 project - free software under the terms of the LGPL 2.1
8
  see COPYING and AUTHORS files in distribution or http://mpg123.org
9
  initially written by Michael Hipp
10
*/
11
12
#include "mpg123lib_intern.h"
13
14
#include "../common/debug.h"
15
16
static int stream_init(mpg123_handle *fr);
17
static int64_t get_fileinfo(mpg123_handle *);
18
19
static ptrdiff_t plain_fullread(mpg123_handle *fr,unsigned char *buf, ptrdiff_t count);
20
21
#ifndef NO_FEEDER
22
/* Bufferchain methods. */
23
static void bc_init(struct bufferchain *bc);
24
static void bc_reset(struct bufferchain *bc);
25
static int bc_append(struct bufferchain *bc, ptrdiff_t size);
26
#if 0
27
static void bc_drop(struct bufferchain *bc);
28
#endif
29
static int bc_add(struct bufferchain *bc, const unsigned char *data, ptrdiff_t size);
30
static ptrdiff_t bc_give(struct bufferchain *bc, unsigned char *out, ptrdiff_t size);
31
static ptrdiff_t bc_skip(struct bufferchain *bc, ptrdiff_t count);
32
static ptrdiff_t bc_seekback(struct bufferchain *bc, ptrdiff_t count);
33
static void bc_forget(struct bufferchain *bc);
34
#endif
35
36
// This is only for streams, so READER_HANDLEIO must be set.
37
static ptrdiff_t fdread(mpg123_handle *fr, void *buf, size_t count)
38
0
{
39
0
  if((fr->rdat.flags & READER_HANDLEIO) && fr->rdat.r_read64)
40
0
  {
41
0
    size_t got = 0;
42
0
    int ret = fr->rdat.r_read64(fr->rdat.iohandle, buf, count, &got);
43
0
    if(ret<0)
44
0
    {
45
0
      if(NOQUIET) merror("error reading %zu bytes", count);
46
0
      return -1;
47
0
    }
48
0
    if(VERBOSE3) mdebug("read %zu bytes of %zu", got, count);
49
    // Stupid handling, but at least some handling of never-occuring case.
50
0
    return (ptrdiff_t)(got > PTRDIFF_MAX ? PTRDIFF_MAX : got);
51
0
  }
52
0
  if(NOQUIET) error("no reader setup");
53
0
  return -1;
54
0
}
55
56
static int64_t fdseek(mpg123_handle *fr, int64_t offset, int whence)
57
0
{
58
0
  if((fr->rdat.flags & READER_HANDLEIO) && fr->rdat.r_lseek64)
59
0
    return (fr->rdat.flags & READER_NOSEEK)
60
0
    ? -1
61
0
    : fr->rdat.r_lseek64(fr->rdat.iohandle, offset, whence);
62
0
  if(NOQUIET) error("no reader setup");
63
0
  return -1;
64
0
}
65
66
#ifndef NO_ICY
67
/* stream based operation  with icy meta data*/
68
static ptrdiff_t icy_fullread(mpg123_handle *fr, unsigned char *buf, ptrdiff_t count)
69
0
{
70
0
  ptrdiff_t ret,cnt;
71
0
  cnt = 0;
72
0
  if(fr->rdat.flags & READER_SEEKABLE)
73
0
  {
74
0
    if(NOQUIET) error("mpg123 programmer error: I don't do ICY on seekable streams.");
75
0
    return -1;
76
0
  }
77
  /*
78
    There used to be a check for expected file end here (length value or ID3 flag).
79
    This is not needed:
80
    1. EOF is indicated by fdread returning zero bytes anyway.
81
    2. We get false positives of EOF for either files that grew or
82
    3. ... files that have ID3v1 tags in between (stream with intro).
83
  */
84
85
0
  while(cnt < count)
86
0
  {
87
    /* all icy code is inside this if block, everything else is the plain fullread we know */
88
    /* debug1("read: %li left", (long) count-cnt); */
89
0
    if(fr->icy.next < count-cnt)
90
0
    {
91
0
      unsigned char temp_buff;
92
0
      size_t meta_size;
93
0
      ptrdiff_t cut_pos;
94
95
      /* we are near icy-metaint boundary, read up to the boundary */
96
0
      if(fr->icy.next > 0)
97
0
      {
98
0
        cut_pos = fr->icy.next;
99
0
        ret = fdread(fr,buf+cnt,cut_pos);
100
0
        if(ret < 1)
101
0
        {
102
0
          if(ret == 0) break; /* Just EOF. */
103
0
          if(NOQUIET) error("icy boundary read");
104
105
0
          return READER_ERROR;
106
0
        }
107
108
0
        if(!(fr->rdat.flags & READER_BUFFERED))
109
0
          SATURATE_ADD(fr->rdat.filepos, ret, INT64_MAX);
110
0
        cnt += ret;
111
0
        fr->icy.next -= ret;
112
0
        if(fr->icy.next > 0)
113
0
        {
114
0
          debug1("another try... still %li left", (long)fr->icy.next);
115
0
          continue;
116
0
        }
117
0
      }
118
      /* now off to read icy data */
119
120
      /* one byte icy-meta size (must be multiplied by 16 to get icy-meta length) */
121
      
122
0
      ret = fdread(fr,&temp_buff,1); /* Getting one single byte hast to suceed. */
123
0
      if(ret < 0){ if(NOQUIET) error("reading icy size"); return READER_ERROR; }
124
0
      if(ret == 0) break;
125
126
0
      debug2("got meta-size byte: %u, at filepos %li", temp_buff, (long)fr->rdat.filepos );
127
0
      if(!(fr->rdat.flags & READER_BUFFERED))
128
0
        SATURATE_ADD(fr->rdat.filepos, ret, INT64_MAX); /* 1... */
129
130
0
      if((meta_size = ((size_t) temp_buff) * 16))
131
0
      {
132
        /* we have got some metadata */
133
0
        char *meta_buff;
134
        /* TODO: Get rid of this malloc ... perhaps hooking into the reader buffer pool? */
135
0
        meta_buff = malloc(meta_size+1);
136
0
        if(meta_buff != NULL)
137
0
        {
138
0
          ptrdiff_t left = meta_size;
139
0
          while(left > 0)
140
0
          {
141
0
            ret = fdread(fr,meta_buff+meta_size-left,left);
142
            /* 0 is error here, too... there _must_ be the ICY data, the server promised! */
143
0
            if(ret < 1){ if(NOQUIET) error("reading icy-meta"); return READER_ERROR; }
144
0
            left -= ret;
145
0
          }
146
0
          meta_buff[meta_size] = 0; /* string paranoia */
147
0
          if(!(fr->rdat.flags & READER_BUFFERED))
148
0
            SATURATE_ADD(fr->rdat.filepos, ret, INT64_MAX);
149
150
0
          if(fr->icy.data) free(fr->icy.data);
151
0
          fr->icy.data = meta_buff;
152
0
          fr->metaflags |= MPG123_NEW_ICY;
153
0
          debug2("icy-meta: %s size: %d bytes", fr->icy.data, (int)meta_size);
154
0
        }
155
0
        else
156
0
        {
157
0
          if(NOQUIET) error1("cannot allocate memory for meta_buff (%lu bytes) ... trying to skip the metadata!", (unsigned long)meta_size);
158
0
          fr->rd->skip_bytes(fr, meta_size);
159
0
        }
160
0
      }
161
0
      fr->icy.next = fr->icy.interval;
162
0
    }
163
0
    else
164
0
    {
165
0
      ret = plain_fullread(fr, buf+cnt, count-cnt);
166
0
      if(ret < 0){ if(NOQUIET) error1("reading the rest of %li", (long)(count-cnt)); return READER_ERROR; }
167
0
      if(ret == 0) break;
168
169
0
      cnt += ret;
170
0
      fr->icy.next -= ret;
171
0
    }
172
0
  }
173
  /* debug1("done reading, got %li", (long)cnt); */
174
0
  return cnt;
175
0
}
176
#else
177
#define icy_fullread NULL
178
#endif /* NO_ICY */
179
180
/* stream based operation */
181
static ptrdiff_t plain_fullread(mpg123_handle *fr,unsigned char *buf, ptrdiff_t count)
182
0
{
183
0
  ptrdiff_t ret,cnt=0;
184
185
#ifdef EXTRA_DEBUG
186
  mdebug("plain fullread of %td", count);
187
#endif
188
  /*
189
    There used to be a check for expected file end here (length value or ID3 flag).
190
    This is not needed:
191
    1. EOF is indicated by fdread returning zero bytes anyway.
192
    2. We get false positives of EOF for either files that grew or
193
    3. ... files that have ID3v1 tags in between (stream with intro).
194
  */
195
0
  while(cnt < count)
196
0
  {
197
0
    ret = fdread(fr,buf+cnt,count-cnt);
198
0
    if(ret < 0) return READER_ERROR;
199
0
    if(ret == 0) break;
200
0
    if(!(fr->rdat.flags & READER_BUFFERED))
201
0
      SATURATE_ADD(fr->rdat.filepos, ret, INT64_MAX);
202
0
    cnt += ret;
203
0
  }
204
0
  return cnt;
205
0
}
206
207
static int64_t stream_lseek(mpg123_handle *fr, int64_t pos, int whence)
208
0
{
209
0
  int64_t ret = fdseek(fr, pos, whence);
210
0
  if (ret >= 0)
211
0
    fr->rdat.filepos = ret;
212
0
  else
213
0
  {
214
0
    fr->err = MPG123_LSEEK_FAILED;
215
0
    ret = READER_ERROR; /* not the original value */
216
0
  }
217
0
  return ret;
218
0
}
219
220
static void stream_close(mpg123_handle *fr)
221
0
{
222
0
#ifndef NO_FEEDER
223
0
  if(fr->rdat.flags & READER_BUFFERED)  bc_reset(&fr->rdat.buffer);
224
0
#endif
225
0
  if(fr->rdat.flags & READER_HANDLEIO)
226
0
  {
227
0
    if(fr->rdat.cleanup_handle != NULL)
228
0
      fr->rdat.cleanup_handle(fr->rdat.iohandle);
229
230
0
    fr->rdat.iohandle = NULL;
231
0
  }
232
0
}
233
234
static int stream_seek_frame(mpg123_handle *fr, int64_t newframe)
235
0
{
236
0
  debug2("seek_frame to %"PRIi64" (from %"PRIi64")", newframe, fr->num);
237
  /* Seekable streams can go backwards and jump forwards.
238
     Non-seekable streams still can go forward, just not jump. */
239
0
  if((fr->rdat.flags & READER_SEEKABLE) || (newframe >= fr->num))
240
0
  {
241
0
    int64_t preframe; /* a leading frame we jump to */
242
0
    int64_t seek_to;  /* the byte offset we want to reach */
243
0
    int64_t to_skip;  /* bytes to skip to get there (can be negative) */
244
    /*
245
      now seek to nearest leading index position and read from there until newframe is reached.
246
      We use skip_bytes, which handles seekable and non-seekable streams
247
      (the latter only for positive offset, which we ensured before entering here).
248
    */
249
0
    seek_to = INT123_frame_index_find(fr, newframe, &preframe);
250
    /* No need to seek to index position if we are closer already.
251
       But I am picky about fr->num == newframe, play safe by reading the frame again.
252
       If you think that's stupid, don't call a seek to the current frame. */
253
0
    if(fr->num >= newframe || fr->num < preframe)
254
0
    {
255
0
      to_skip = seek_to - fr->rd->tell(fr);
256
0
      if(fr->rd->skip_bytes(fr, to_skip) != seek_to)
257
0
      return READER_ERROR;
258
259
0
      debug2("going to %lu; just got %lu", (long unsigned)newframe, (long unsigned)preframe);
260
0
      fr->num = preframe-1; /* Watch out! I am going to read preframe... fr->num should indicate the frame before! */
261
0
    }
262
0
    while(fr->num < newframe)
263
0
    {
264
      /* try to be non-fatal now... frameNum only gets advanced on success anyway */
265
0
      if(!INT123_read_frame(fr)) break;
266
0
    }
267
    /* Now the wanted frame should be ready for decoding. */
268
0
    debug1("arrived at %"PRIi64, fr->num);
269
270
0
    return MPG123_OK;
271
0
  }
272
0
  else
273
0
  {
274
0
    fr->err = MPG123_NO_SEEK;
275
0
    return READER_ERROR; /* invalid, no seek happened */
276
0
  }
277
0
}
278
279
/* return FALSE on error, TRUE on success, READER_MORE on occasion */
280
static int generic_head_read(mpg123_handle *fr,unsigned long *newhead)
281
0
{
282
0
  unsigned char hbuf[4];
283
0
  int ret = fr->rd->fullread(fr,hbuf,4);
284
0
  if(ret == READER_MORE) return ret;
285
0
  if(ret != 4) return FALSE;
286
287
0
  *newhead = ((unsigned long) hbuf[0] << 24) |
288
0
             ((unsigned long) hbuf[1] << 16) |
289
0
             ((unsigned long) hbuf[2] << 8)  |
290
0
              (unsigned long) hbuf[3];
291
292
0
  return TRUE;
293
0
}
294
295
/* return FALSE on error, TRUE on success, READER_MORE on occasion */
296
static int generic_head_shift(mpg123_handle *fr,unsigned long *head)
297
0
{
298
0
  unsigned char hbuf;
299
0
  int ret = fr->rd->fullread(fr,&hbuf,1);
300
0
  if(ret == READER_MORE) return ret;
301
0
  if(ret != 1) return FALSE;
302
303
0
  *head <<= 8;
304
0
  *head |= hbuf;
305
0
  *head &= 0xffffffff;
306
0
  return TRUE;
307
0
}
308
309
/* returns reached position... negative ones are bad... */
310
static int64_t stream_skip_bytes(mpg123_handle *fr, int64_t len)
311
0
{
312
0
  if(fr->rdat.flags & READER_SEEKABLE)
313
0
  {
314
0
    int64_t ret = stream_lseek(fr, len, SEEK_CUR);
315
0
    return (ret < 0) ? READER_ERROR : ret;
316
0
  }
317
0
  else if(len >= 0)
318
0
  {
319
0
    unsigned char buf[1024]; /* ThOr: Compaq cxx complained and it makes sense to me... or should one do a cast? What for? */
320
0
    ptrdiff_t ret;
321
0
    while (len > 0)
322
0
    {
323
0
      ptrdiff_t num = len < (ptrdiff_t)sizeof(buf) ? (ptrdiff_t)len : (ptrdiff_t)sizeof(buf);
324
0
      ret = fr->rd->fullread(fr, buf, num);
325
0
      if (ret < 0) return ret;
326
0
      else if(ret == 0) break; /* EOF... an error? interface defined to tell the actual position... */
327
0
      len -= ret;
328
0
    }
329
0
    return fr->rd->tell(fr);
330
0
  }
331
0
#ifndef NO_FEEDER
332
0
  else if(fr->rdat.flags & READER_BUFFERED)
333
0
  { /* Perhaps we _can_ go a bit back. */
334
0
    if(fr->rdat.buffer.pos >= -len)
335
0
    {
336
0
      fr->rdat.buffer.pos += len;
337
0
      return fr->rd->tell(fr);
338
0
    }
339
0
    else
340
0
    {
341
0
      fr->err = MPG123_NO_SEEK;
342
0
      return READER_ERROR;
343
0
    }
344
0
  }
345
0
#endif
346
0
  else
347
0
  {
348
0
    fr->err = MPG123_NO_SEEK;
349
0
    return READER_ERROR;
350
0
  }
351
0
}
352
353
/* Return 0 on success... */
354
static int stream_back_bytes(mpg123_handle *fr, int64_t bytes)
355
0
{
356
0
  int64_t want = fr->rd->tell(fr)-bytes;
357
0
  if(want < 0) return READER_ERROR;
358
0
  if(stream_skip_bytes(fr,-bytes) != want) return READER_ERROR;
359
360
0
  return 0;
361
0
}
362
363
364
/* returns size on success... otherwise an error code < 0 */
365
static int generic_read_frame_body(mpg123_handle *fr,unsigned char *buf, int size)
366
0
{
367
0
  ptrdiff_t l;
368
0
  l=fr->rd->fullread(fr,buf,size);
369
0
  return (l >= 0 && l<size) ? READER_ERROR : (int)l;
370
0
}
371
372
static int64_t generic_tell(mpg123_handle *fr)
373
0
{
374
0
#ifndef NO_FEEDER
375
0
  if(fr->rdat.flags & READER_BUFFERED)
376
0
  {
377
0
    fr->rdat.filepos = fr->rdat.buffer.fileoff;
378
0
    SATURATE_ADD(fr->rdat.filepos, fr->rdat.buffer.pos, INT64_MAX);
379
0
  }
380
0
#endif
381
382
0
  return fr->rdat.filepos;
383
0
}
384
385
/* This does not (fully) work for non-seekable streams... You have to check for that flag, pal! */
386
static void stream_rewind(mpg123_handle *fr)
387
0
{
388
0
  if(fr->rdat.flags & READER_SEEKABLE)
389
0
  {
390
0
    fr->rdat.filepos = stream_lseek(fr,0,SEEK_SET);
391
0
#ifndef NO_FEEDER
392
0
    fr->rdat.buffer.fileoff = fr->rdat.filepos;
393
0
#endif
394
0
  }
395
0
#ifndef NO_FEEDER
396
0
  if(fr->rdat.flags & READER_BUFFERED)
397
0
  {
398
0
    fr->rdat.buffer.pos      = 0;
399
0
    fr->rdat.buffer.firstpos = 0;
400
0
    fr->rdat.filepos = fr->rdat.buffer.fileoff;
401
0
  }
402
0
#endif
403
0
}
404
405
/*
406
 * returns length of a file (if filept points to a file)
407
 * reads the last 128 bytes information into buffer
408
 * ... that is not totally safe...
409
 */
410
static int64_t get_fileinfo(mpg123_handle *fr)
411
0
{
412
0
  int64_t len;
413
414
0
  if((len=fdseek(fr,0,SEEK_END)) < 0)
415
0
  {
416
0
    debug("cannot seek to end");
417
0
    return -1;
418
0
  } else if(len >= 128)
419
0
  {
420
0
    if(fdseek(fr,-128,SEEK_END) < 0)
421
0
    {
422
0
      debug("cannot seek to END-128");
423
0
      return -1;
424
0
    }
425
0
    if(fr->rd->fullread(fr,(unsigned char *)fr->id3buf,128) != 128)
426
0
    {
427
0
      debug("cannot read ID3v1?!");
428
0
      return -1;
429
0
    }
430
0
    if(!strncmp((char*)fr->id3buf,"TAG",3)) len -= 128;
431
0
  } else
432
0
  {
433
0
    debug("stream too short for ID3");
434
0
  }
435
436
0
  if(fdseek(fr,0,SEEK_SET) < 0)
437
0
  {
438
0
    debug("cannot seek back");
439
0
    return -1;
440
0
  }
441
0
  fr->rdat.filepos = 0; // un-do our seeking here
442
443
0
  debug1("returning length: %"PRIi64, len);
444
0
  return len;
445
0
}
446
447
#ifndef NO_FEEDER
448
/* Methods for the buffer chain, mainly used for feed reader, but not just that. */
449
450
451
static struct buffy* buffy_new(ptrdiff_t size, ptrdiff_t minsize)
452
0
{
453
0
  struct buffy *newbuf;
454
0
  if(size > PTRDIFF_MAX)
455
0
    return NULL;
456
0
  newbuf = malloc(sizeof(struct buffy));
457
0
  if(newbuf == NULL) return NULL;
458
459
0
  newbuf->realsize = size > minsize ? size : minsize;
460
0
  newbuf->data = malloc((size_t)newbuf->realsize);
461
0
  if(newbuf->data == NULL)
462
0
  {
463
0
    free(newbuf);
464
0
    return NULL;
465
0
  }
466
0
  newbuf->size = 0;
467
0
  newbuf->next = NULL;
468
0
  return newbuf;
469
0
}
470
471
static void buffy_del(struct buffy* buf)
472
0
{
473
0
  if(buf)
474
0
  {
475
0
    free(buf->data);
476
0
    free(buf);
477
0
  }
478
0
}
479
480
/* Delete this buffy and all following buffies. */
481
static void buffy_del_chain(struct buffy* buf)
482
0
{
483
0
  while(buf)
484
0
  {
485
0
    struct buffy* next = buf->next;
486
0
    buffy_del(buf);
487
0
    buf = next;
488
0
  }
489
0
}
490
491
void INT123_bc_prepare(struct bufferchain *bc, size_t pool_size, size_t bufblock)
492
0
{
493
0
  INT123_bc_poolsize(bc, pool_size, bufblock);
494
0
  bc->pool = NULL;
495
0
  bc->pool_fill = 0;
496
0
  bc_init(bc); /* Ensure that members are zeroed for read-only use. */
497
0
}
498
499
size_t INT123_bc_fill(struct bufferchain *bc)
500
0
{
501
0
  return (size_t)(bc->size - bc->pos);
502
0
}
503
504
void INT123_bc_poolsize(struct bufferchain *bc, size_t pool_size, size_t bufblock)
505
0
{
506
0
  bc->pool_size = pool_size;
507
0
  bc->bufblock = bufblock;
508
0
}
509
510
void INT123_bc_cleanup(struct bufferchain *bc)
511
0
{
512
0
  buffy_del_chain(bc->pool);
513
0
  bc->pool = NULL;
514
0
  bc->pool_fill = 0;
515
0
}
516
517
/* Fetch a buffer from the pool (if possible) or create one. */
518
static struct buffy* bc_alloc(struct bufferchain *bc, size_t size)
519
0
{
520
  /* Easy route: Just try the first available buffer.
521
     Size does not matter, it's only a hint for creation of new buffers. */
522
0
  if(bc->pool)
523
0
  {
524
0
    struct buffy *buf = bc->pool;
525
0
    bc->pool = buf->next;
526
0
    buf->next = NULL; /* That shall be set to a sensible value later. */
527
0
    buf->size = 0;
528
0
    --bc->pool_fill;
529
0
    debug2("bc_alloc: picked %p from pool (fill now %zu)", (void*)buf, bc->pool_fill);
530
0
    return buf;
531
0
  }
532
0
  else return buffy_new(size, bc->bufblock);
533
0
}
534
535
/* Either stuff the buffer back into the pool or free it for good. */
536
static void bc_free(struct bufferchain *bc, struct buffy* buf)
537
0
{
538
0
  if(!buf) return;
539
540
0
  if(bc->pool_fill < bc->pool_size)
541
0
  {
542
0
    buf->next = bc->pool;
543
0
    bc->pool = buf;
544
0
    ++bc->pool_fill;
545
0
  }
546
0
  else buffy_del(buf);
547
0
}
548
549
/* Make the buffer count in the pool match the pool size. */
550
static int bc_fill_pool(struct bufferchain *bc)
551
0
{
552
  /* Remove superfluous ones. */
553
0
  while(bc->pool_fill > bc->pool_size)
554
0
  {
555
    /* Lazyness: Just work on the front. */
556
0
    struct buffy* buf = bc->pool;
557
0
    bc->pool = buf->next;
558
0
    buffy_del(buf);
559
0
    --bc->pool_fill;
560
0
  }
561
562
  /* Add missing ones. */
563
0
  while(bc->pool_fill < bc->pool_size)
564
0
  {
565
    /* Again, just work on the front. */
566
0
    struct buffy* buf;
567
0
    buf = buffy_new(0, bc->bufblock); /* Use default block size. */
568
0
    if(!buf) return -1;
569
570
0
    buf->next = bc->pool;
571
0
    bc->pool = buf;
572
0
    ++bc->pool_fill;
573
0
  }
574
575
0
  return 0;
576
0
}
577
578
579
static void bc_init(struct bufferchain *bc)
580
0
{
581
0
  bc->first = NULL;
582
0
  bc->last  = bc->first;
583
0
  bc->size  = 0;
584
0
  bc->pos   = 0;
585
0
  bc->firstpos = 0;
586
0
  bc->fileoff  = 0;
587
0
}
588
589
static void bc_reset(struct bufferchain *bc)
590
0
{
591
  /* Free current chain, possibly stuffing back into the pool. */
592
0
  while(bc->first)
593
0
  {
594
0
    struct buffy* buf = bc->first;
595
0
    bc->first = buf->next;
596
0
    bc_free(bc, buf);
597
0
  }
598
0
  bc_fill_pool(bc); /* Ignoring an error here... */
599
0
  bc_init(bc);
600
0
}
601
602
/* Create a new buffy at the end to be filled. */
603
static int bc_append(struct bufferchain *bc, ptrdiff_t size)
604
0
{
605
0
  struct buffy *newbuf;
606
0
  if(size < 1) return -1;
607
608
0
  newbuf = bc_alloc(bc, size);
609
0
  if(newbuf == NULL) return -2;
610
611
0
  if(bc->last != NULL)  bc->last->next = newbuf;
612
0
  else if(bc->first == NULL) bc->first = newbuf;
613
614
0
  bc->last  = newbuf;
615
0
  debug3("bc_append: new last buffer %p with %td B (really %td)", (void*)bc->last, bc->last->size, bc->last->realsize);
616
0
  return 0;
617
0
}
618
619
/* Append a new buffer and copy content to it. */
620
static int bc_add(struct bufferchain *bc, const unsigned char *data, ptrdiff_t size)
621
0
{
622
0
  int ret = 0;
623
0
  ptrdiff_t part = 0;
624
0
  if((size_t)(PTRDIFF_MAX - bc->size) < size)
625
0
    return -1;
626
0
  debug2("bc_add: adding %zu bytes at %"PRIi64, size, (int64_t)(bc->fileoff+bc->size));
627
0
  if(size >=4) debug4("first bytes: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]);
628
629
0
  while(size > 0)
630
0
  {
631
    /* Try to fill up the last buffer block. */
632
0
    if(bc->last != NULL && bc->last->size < bc->last->realsize)
633
0
    {
634
0
      part = bc->last->realsize - bc->last->size;
635
0
      if(part > size) part = size;
636
637
0
      debug2("bc_add: adding %td B to existing block %p", part, (void*)bc->last);
638
0
      memcpy(bc->last->data+bc->last->size, data, part);
639
0
      bc->last->size += part;
640
0
      size -= part;
641
0
      bc->size += part;
642
0
      data += part;
643
0
    }
644
645
    /* If there is still data left, put it into a new buffer block. */
646
0
    if(size > 0 && (ret = bc_append(bc, size)) != 0)
647
0
    break;
648
0
  }
649
650
0
  return ret;
651
0
}
652
653
/* Common handler for "You want more than I can give." situation. */
654
static ptrdiff_t bc_need_more(struct bufferchain *bc, ptrdiff_t size)
655
0
{
656
0
  debug3("hit end, back to beginning (%td - %td < %td)", bc->size, bc->pos, size);
657
  /* go back to firstpos, undo the previous reads */
658
0
  bc->pos = bc->firstpos;
659
0
  return READER_MORE;
660
0
}
661
662
/* Give some data, advancing position but not forgetting yet. */
663
static ptrdiff_t bc_give(struct bufferchain *bc, unsigned char *out, ptrdiff_t size)
664
0
{
665
0
  struct buffy *b = bc->first;
666
0
  ptrdiff_t gotcount = 0;
667
0
  ptrdiff_t offset = 0;
668
0
  if(bc->size - bc->pos < size) return bc_need_more(bc, size);
669
670
  /* find the current buffer */
671
0
  while(b != NULL && (offset + b->size) <= bc->pos)
672
0
  {
673
0
    offset += b->size;
674
0
    b = b->next;
675
0
  }
676
  /* now start copying from there */
677
0
  while(gotcount < size && (b != NULL))
678
0
  {
679
0
    ptrdiff_t loff = bc->pos - offset;
680
0
    ptrdiff_t chunk = size - gotcount; /* amount of bytes to get from here... */
681
0
    if(chunk > b->size - loff) chunk = b->size - loff;
682
683
#ifdef EXTRA_DEBUG
684
    debug3("copying %liB from %p+%li",(long)chunk, b->data, (long)loff);
685
#endif
686
687
0
    memcpy(out+gotcount, b->data+loff, chunk);
688
0
    gotcount += chunk;
689
0
    bc->pos  += chunk;
690
0
    offset += b->size;
691
0
    b = b->next;
692
0
  }
693
#ifdef EXTRA_DEBUG
694
  debug2("got %li bytes, pos advanced to %li", (long)gotcount, (long)bc->pos);
695
#endif
696
697
0
  return gotcount;
698
0
}
699
700
/* Skip some bytes and return the new position.
701
   The buffers are still there, just the read pointer is moved! */
702
static ptrdiff_t bc_skip(struct bufferchain *bc, ptrdiff_t count)
703
0
{
704
0
  if(count >= 0)
705
0
  {
706
0
    if(bc->size - bc->pos < count) return bc_need_more(bc, count);
707
0
    else return bc->pos += count;
708
0
  }
709
0
  else return READER_ERROR;
710
0
}
711
712
static ptrdiff_t bc_seekback(struct bufferchain *bc, ptrdiff_t count)
713
0
{
714
0
  if(count >= 0 && count <= bc->pos) return bc->pos -= count;
715
0
  else return READER_ERROR;
716
0
}
717
718
/* Throw away buffies that we passed. */
719
static void bc_forget(struct bufferchain *bc)
720
0
{
721
0
  struct buffy *b = bc->first;
722
  /* free all buffers that are def'n'tly outdated */
723
  /* we have buffers until filepos... delete all buffers fully below it */
724
0
  if(b) debug2("bc_forget: block %td pos %td", b->size, bc->pos);
725
0
  else debug("forget with nothing there!");
726
727
0
  while(b != NULL && bc->pos >= b->size)
728
0
  {
729
0
    struct buffy *n = b->next; /* != NULL or this is indeed the end and the last cycle anyway */
730
0
    if(n == NULL) bc->last = NULL; /* Going to delete the last buffy... */
731
0
    bc->fileoff += b->size;
732
0
    bc->pos  -= b->size;
733
0
    bc->size -= b->size;
734
735
0
    debug5("bc_forget: forgot %p with %td, pos=%td, size=%td, fileoff=%td"
736
0
    , (void*)b->data, b->size, bc->pos,  bc->size, bc->fileoff);
737
738
0
    bc_free(bc, b);
739
0
    b = n;
740
0
  }
741
0
  bc->first = b;
742
0
  bc->firstpos = bc->pos;
743
0
}
744
745
/* reader for input via manually provided buffers */
746
747
static int feed_init(mpg123_handle *fr)
748
0
{
749
0
  bc_init(&fr->rdat.buffer);
750
0
  bc_fill_pool(&fr->rdat.buffer);
751
0
  fr->rdat.filelen = 0;
752
0
  fr->rdat.filepos = 0;
753
0
  fr->rdat.flags |= READER_BUFFERED;
754
0
  return 0;
755
0
}
756
757
/* externally called function, returns 0 on success, -1 on error */
758
// External API uses size_t, we use signed ptrdiff_t internally. Overflow
759
// is a theoretical possibility.
760
int INT123_feed_more(mpg123_handle *fr, const unsigned char *in, size_t count)
761
0
{
762
0
  int ret = 0;
763
0
  if(VERBOSE3) debug("INT123_feed_more");
764
0
  if(count > PTRDIFF_MAX)
765
0
    return READER_ERROR;
766
0
  if((ret = bc_add(&fr->rdat.buffer, in, (ptrdiff_t)count)) != 0)
767
0
  {
768
0
    ret = READER_ERROR;
769
0
    if(NOQUIET) error1("Failed to add buffer, return: %i", ret);
770
0
  }
771
0
  else /* Not talking about filelen... that stays at 0. */
772
773
0
  if(VERBOSE3) debug3("INT123_feed_more: %p %luB bufsize=%lu", fr->rdat.buffer.last->data,
774
0
    (unsigned long)fr->rdat.buffer.last->size, (unsigned long)fr->rdat.buffer.size);
775
0
  return ret;
776
0
}
777
778
static ptrdiff_t feed_read(mpg123_handle *fr, unsigned char *out, ptrdiff_t count)
779
0
{
780
0
  ptrdiff_t gotcount = bc_give(&fr->rdat.buffer, out, count);
781
0
  if(gotcount >= 0 && gotcount != count) return READER_ERROR;
782
0
  else return gotcount;
783
0
}
784
785
/* returns reached position... negative ones are bad... */
786
static int64_t feed_skip_bytes(mpg123_handle *fr, int64_t len)
787
0
{
788
  /* This is either the new buffer offset or some negative error value. */
789
0
  int64_t res = bc_skip(&fr->rdat.buffer, (ptrdiff_t)len);
790
0
  if(res < 0) return res;
791
792
0
  return fr->rdat.buffer.fileoff+res;
793
0
}
794
795
static int feed_back_bytes(mpg123_handle *fr, int64_t bytes)
796
0
{
797
0
  if(bytes >=0)
798
0
  return bc_seekback(&fr->rdat.buffer, (ptrdiff_t)bytes) >= 0 ? 0 : READER_ERROR;
799
0
  else
800
0
  return feed_skip_bytes(fr, -bytes) >= 0 ? 0 : READER_ERROR;
801
0
}
802
803
0
static int feed_seek_frame(mpg123_handle *fr, int64_t num){ return READER_ERROR; }
804
805
/* Not just for feed reader, also for self-feeding buffered reader. */
806
static void buffered_forget(mpg123_handle *fr)
807
0
{
808
0
  bc_forget(&fr->rdat.buffer);
809
0
  fr->rdat.filepos = fr->rdat.buffer.fileoff;
810
0
  SATURATE_ADD(fr->rdat.filepos, fr->rdat.buffer.pos, INT64_MAX);
811
0
}
812
813
int64_t INT123_feed_set_pos(mpg123_handle *fr, int64_t pos)
814
0
{
815
0
  struct bufferchain *bc = &fr->rdat.buffer;
816
0
  if(pos >= bc->fileoff && pos-bc->fileoff < bc->size)
817
0
  { /* We have the position! */
818
0
    bc->pos = (ptrdiff_t)(pos - bc->fileoff);
819
0
    debug1("INT123_feed_set_pos inside, next feed from %"PRIi64, (int64_t)(bc->fileoff+bc->size));
820
0
    return bc->fileoff+bc->size; /* Next input after end of buffer... */
821
0
  }
822
0
  else
823
0
  { /* I expect to get the specific position on next feed. Forget what I have now. */
824
0
    bc_reset(bc);
825
0
    bc->fileoff = pos;
826
0
    debug1("INT123_feed_set_pos outside, buffer reset, next feed from %"PRIi64, pos);
827
0
    return pos; /* Next input from exactly that position. */
828
0
  }
829
0
}
830
831
/* The specific stuff for buffered stream reader. */
832
833
static ptrdiff_t buffered_fullread(mpg123_handle *fr, unsigned char *out, ptrdiff_t count
834
, ptrdiff_t (*fullread)(mpg123_handle *, unsigned char *, ptrdiff_t))
835
0
{
836
0
  struct bufferchain *bc = &fr->rdat.buffer;
837
0
  ptrdiff_t gotcount;
838
0
  if(VERBOSE3)
839
0
    mdebug("buffered_fullread: want %zd", count);
840
0
  if(bc->size - bc->pos < count)
841
0
  { /* Add more stuff to buffer. If hitting end of file, adjust count. */
842
0
    unsigned char readbuf[4096];
843
0
    ptrdiff_t need = count - (bc->size-bc->pos);
844
0
    while(need>0)
845
0
    {
846
0
      int ret;
847
0
      ptrdiff_t got = fullread(fr, readbuf, sizeof(readbuf));
848
0
      if(got < 0)
849
0
      {
850
0
        if(NOQUIET) error("buffer reading");
851
0
        return READER_ERROR;
852
0
      }
853
854
0
      if(VERBOSE3)
855
0
        debug1("buffered_fullread: buffering %td bytes from stream (if > 0)", got);
856
0
      if(got > 0 && (ret=bc_add(bc, readbuf, got)) != 0)
857
0
      {
858
0
        if(NOQUIET) error1("unable to add to chain, return: %i", ret);
859
0
        return READER_ERROR;
860
0
      }
861
862
0
      need -= got; /* May underflow here... */
863
0
      if(got < sizeof(readbuf)) /* That naturally catches got == 0, too. */
864
0
      {
865
0
        if(VERBOSE3) fprintf(stderr, "Note: Input data end.\n");
866
0
        break; /* End. */
867
0
      }
868
0
    }
869
0
    if(bc->size - bc->pos < count)
870
0
    count = bc->size - bc->pos; /* We want only what we got. */
871
0
  }
872
0
  gotcount = bc_give(bc, out, count);
873
0
  if(VERBOSE3)
874
0
    mdebug("buffered_fullread: got %td", gotcount);
875
0
  if(gotcount != count){ if(NOQUIET) error("gotcount != count"); return READER_ERROR; }
876
0
  else return gotcount;
877
0
}
878
879
static ptrdiff_t buffered_plain_fullread(mpg123_handle *fr, unsigned char *out, ptrdiff_t count)
880
0
{
881
0
  return buffered_fullread(fr, out, count, plain_fullread);
882
0
}
883
884
static ptrdiff_t buffered_icy_fullread(mpg123_handle *fr, unsigned char *out, ptrdiff_t count)
885
0
{
886
0
  return buffered_fullread(fr, out, count, icy_fullread);
887
0
}
888
889
#else
890
int INT123_feed_more(mpg123_handle *fr, const unsigned char *in, size_t count)
891
{
892
  fr->err = MPG123_MISSING_FEATURE;
893
  return -1;
894
}
895
int64_t INT123_feed_set_pos(mpg123_handle *fr, int64_t pos)
896
{
897
  fr->err = MPG123_MISSING_FEATURE;
898
  return -1;
899
}
900
#endif /* NO_FEEDER */
901
902
/*****************************************************************
903
 * read frame helper
904
 */
905
906
0
#define bugger_off { mh->err = MPG123_NO_READER; return MPG123_ERR; }
Unexecuted instantiation: readers.c:bad_init
Unexecuted instantiation: readers.c:bad_fullread
Unexecuted instantiation: readers.c:bad_head_read
Unexecuted instantiation: readers.c:bad_head_shift
Unexecuted instantiation: readers.c:bad_skip_bytes
Unexecuted instantiation: readers.c:bad_read_frame_body
Unexecuted instantiation: readers.c:bad_back_bytes
Unexecuted instantiation: readers.c:bad_seek_frame
Unexecuted instantiation: readers.c:bad_tell
907
static int bad_init(mpg123_handle *mh) bugger_off
908
0
static void bad_close(mpg123_handle *mh){}
909
static ptrdiff_t bad_fullread(mpg123_handle *mh, unsigned char *data, ptrdiff_t count) bugger_off
910
static int bad_head_read(mpg123_handle *mh, unsigned long *newhead) bugger_off
911
static int bad_head_shift(mpg123_handle *mh, unsigned long *head) bugger_off
912
static int64_t bad_skip_bytes(mpg123_handle *mh, int64_t len) bugger_off
913
static int bad_read_frame_body(mpg123_handle *mh, unsigned char *data, int size) bugger_off
914
static int bad_back_bytes(mpg123_handle *mh, int64_t bytes) bugger_off
915
static int bad_seek_frame(mpg123_handle *mh, int64_t num) bugger_off
916
static int64_t bad_tell(mpg123_handle *mh) bugger_off
917
0
static void bad_rewind(mpg123_handle *mh){}
918
#undef bugger_off
919
920
0
#define READER_STREAM 0
921
0
#define READER_ICY_STREAM 1
922
0
#define READER_FEED       2
923
0
#define READER_BUF_STREAM 3
924
0
#define READER_BUF_ICY_STREAM 4
925
static struct reader readers[] =
926
{
927
  { /* READER_STREAM */
928
    stream_init,
929
    stream_close,
930
    plain_fullread,
931
    generic_head_read,
932
    generic_head_shift,
933
    stream_skip_bytes,
934
    generic_read_frame_body,
935
    stream_back_bytes,
936
    stream_seek_frame,
937
    generic_tell,
938
    stream_rewind,
939
    NULL
940
  } ,
941
  { /* READER_ICY_STREAM */
942
    stream_init,
943
    stream_close,
944
    icy_fullread,
945
    generic_head_read,
946
    generic_head_shift,
947
    stream_skip_bytes,
948
    generic_read_frame_body,
949
    stream_back_bytes,
950
    stream_seek_frame,
951
    generic_tell,
952
    stream_rewind,
953
    NULL
954
  },
955
#ifdef NO_FEEDER
956
#define feed_init NULL
957
#define feed_read NULL
958
#define buffered_fullread NULL
959
#define buffered_plain_fullread NULL
960
#define buffered_icy_fullread NULL
961
#define feed_seek_frame NULL
962
#define feed_back_bytes NULL
963
#define feed_skip_bytes NULL
964
#define buffered_forget NULL
965
#endif
966
  { /* READER_FEED */
967
    feed_init,
968
    stream_close,
969
    feed_read,
970
    generic_head_read,
971
    generic_head_shift,
972
    feed_skip_bytes,
973
    generic_read_frame_body,
974
    feed_back_bytes,
975
    feed_seek_frame,
976
    generic_tell,
977
    stream_rewind,
978
    buffered_forget
979
  },
980
  { /* READER_BUF_STREAM */
981
    stream_init,
982
    stream_close,
983
    buffered_plain_fullread,
984
    generic_head_read,
985
    generic_head_shift,
986
    stream_skip_bytes,
987
    generic_read_frame_body,
988
    stream_back_bytes,
989
    stream_seek_frame,
990
    generic_tell,
991
    stream_rewind,
992
    buffered_forget
993
  } ,
994
  { /* READER_BUF_ICY_STREAM */
995
    stream_init,
996
    stream_close,
997
    buffered_icy_fullread,
998
    generic_head_read,
999
    generic_head_shift,
1000
    stream_skip_bytes,
1001
    generic_read_frame_body,
1002
    stream_back_bytes,
1003
    stream_seek_frame,
1004
    generic_tell,
1005
    stream_rewind,
1006
    buffered_forget
1007
  },
1008
};
1009
1010
static struct reader bad_reader =
1011
{
1012
  bad_init,
1013
  bad_close,
1014
  bad_fullread,
1015
  bad_head_read,
1016
  bad_head_shift,
1017
  bad_skip_bytes,
1018
  bad_read_frame_body,
1019
  bad_back_bytes,
1020
  bad_seek_frame,
1021
  bad_tell,
1022
  bad_rewind,
1023
  NULL
1024
};
1025
1026
static int stream_init(mpg123_handle *fr)
1027
0
{
1028
0
#ifndef NO_ICY
1029
  /* ICY streams of any sort shall not be seekable. */
1030
0
  if(fr->p.icy_interval > 0) fr->rdat.flags |= READER_NOSEEK;
1031
0
#endif
1032
1033
0
  fr->rdat.filepos = 0;
1034
0
  fr->rdat.filelen = fr->p.flags & MPG123_NO_PEEK_END ? -1 : get_fileinfo(fr);
1035
0
  if(fr->p.flags & MPG123_FORCE_SEEKABLE)
1036
0
  {
1037
0
    fr->rdat.flags |= READER_SEEKABLE;
1038
0
    fr->rdat.flags &= ~READER_NOSEEK;
1039
0
  }
1040
  /*
1041
    Don't enable seeking on ICY streams, just plain normal files.
1042
    This check is necessary since the client can enforce ICY parsing on files that would otherwise be seekable.
1043
    It is a task for the future to make the ICY parsing safe with seeks ... or not.
1044
  */
1045
0
  if(fr->rdat.filelen >= 0)
1046
0
  {
1047
0
    debug("seekable stream");
1048
0
    fr->rdat.flags |= READER_SEEKABLE;
1049
0
    if(!strncmp((char*)fr->id3buf,"TAG",3))
1050
0
    {
1051
0
      fr->rdat.flags |= READER_ID3TAG;
1052
0
      fr->metaflags  |= MPG123_NEW_ID3;
1053
0
    }
1054
0
  }
1055
  /* Switch reader to a buffered one, if allowed. */
1056
0
  else if(fr->p.flags & MPG123_SEEKBUFFER)
1057
0
  {
1058
#ifdef NO_FEEDER
1059
    if(NOQUIET)
1060
      error("Buffered readers not supported in this build.");
1061
    fr->err = MPG123_MISSING_FEATURE;
1062
    return -1;
1063
#else
1064
0
    if     (fr->rd == &readers[READER_STREAM])
1065
0
    {
1066
0
      debug("switching to buffered stream reader");
1067
0
      fr->rd = &readers[READER_BUF_STREAM];
1068
0
    }
1069
0
#ifndef NO_ICY
1070
0
    else if(fr->rd == &readers[READER_ICY_STREAM])
1071
0
    {
1072
0
      debug("switching to buffered ICY stream reader");
1073
0
      fr->rd = &readers[READER_BUF_ICY_STREAM];
1074
0
    }
1075
0
#endif
1076
0
    else
1077
0
    {
1078
0
      if(NOQUIET) error("mpg123 Programmer's fault: invalid reader");
1079
0
      return -1;
1080
0
    }
1081
0
    bc_init(&fr->rdat.buffer);
1082
0
    fr->rdat.filelen = 0; /* We carry the offset, but never know how big the stream is. */
1083
0
    fr->rdat.flags |= READER_BUFFERED;
1084
0
#endif /* NO_ICY */
1085
0
  }
1086
0
  return 0;
1087
0
}
1088
1089
1090
void INT123_open_bad(mpg123_handle *mh)
1091
0
{
1092
0
  debug("INT123_open_bad");
1093
0
#ifndef NO_ICY
1094
0
  INT123_clear_icy(&mh->icy);
1095
0
#endif
1096
0
  mh->rd = &bad_reader;
1097
0
  mh->rdat.flags = 0;
1098
0
#ifndef NO_FEEDER
1099
0
  bc_init(&mh->rdat.buffer);
1100
0
#endif
1101
0
  mh->rdat.filelen = -1;
1102
0
}
1103
1104
int INT123_open_feed(mpg123_handle *fr)
1105
0
{
1106
0
  debug("feed reader");
1107
#ifdef NO_FEEDER
1108
  if(NOQUIET)
1109
    error("Buffered readers not supported in this build.");
1110
  fr->err = MPG123_MISSING_FEATURE;
1111
  return -1;
1112
#else
1113
0
#ifndef NO_ICY
1114
0
  if(fr->p.icy_interval > 0)
1115
0
  {
1116
0
    if(NOQUIET) error("Feed reader cannot do ICY parsing!");
1117
1118
0
    return -1;
1119
0
  }
1120
0
  INT123_clear_icy(&fr->icy);
1121
0
#endif
1122
0
  fr->rd = &readers[READER_FEED];
1123
0
  fr->rdat.flags = 0;
1124
0
  if(fr->rd->init(fr) < 0) return -1;
1125
1126
0
  debug("feed reader init successful");
1127
0
  return 0;
1128
0
#endif /* NO_FEEDER */
1129
0
}
1130
1131
/* Final code common to open_stream and INT123_open_stream_handle. */
1132
int INT123_open_stream_handle(mpg123_handle *fr, void *iohandle)
1133
0
{
1134
0
  INT123_clear_icy(&fr->icy); /* can be done inside frame_clear ...? */
1135
0
  fr->rdat.filelen = -1;
1136
0
  fr->rdat.iohandle = iohandle;
1137
0
  fr->rdat.flags = 0;
1138
0
  fr->rdat.flags |= READER_HANDLEIO;
1139
1140
0
#ifndef NO_ICY
1141
0
  if(fr->p.icy_interval > 0)
1142
0
  {
1143
0
    debug("ICY reader");
1144
0
    fr->icy.interval = fr->p.icy_interval;
1145
0
    fr->icy.next = fr->icy.interval;
1146
0
    fr->rd = &readers[READER_ICY_STREAM];
1147
0
  }
1148
0
  else
1149
0
#endif
1150
0
  {
1151
0
    fr->rd = &readers[READER_STREAM];
1152
0
    debug("stream reader");
1153
0
  }
1154
1155
0
  if(fr->rd->init(fr) < 0) return -1;
1156
1157
0
  return MPG123_OK;
1158
0
}