ReactOS  0.4.14-dev-342-gdc047f9
lfs_wrap.c
Go to the documentation of this file.
1 /*
2  lfs_wrap: Crappy wrapper code for supporting crappy ambiguous large file support.
3 
4  copyright 2010 by the mpg123 project - free software under the terms of the LGPL 2.1
5  see COPYING and AUTHORS files in distribution or http://mpg123.org
6 
7  initially written by Thomas Orgis, thanks to Guido Draheim for consulting
8 
9  This file contains wrappers for the case that _FILE_OFFSET_BITS (or equivalent, theoretically, depends on mpg123.h) is defined and thus certain mpg123 API calls get renamed with a suffix (p.ex. _64).
10  The renamed calls expect large off_t arguments, and possibly return large off_t values... these wrappers here provide the same functionality with long integer arguments/values.
11 
12  Prototypical idea: There is
13  off_t mpg123_seek_64(mpg123_handle*, off_t, int)
14  This code provides
15  long mpg123_seek(mpg123_handle*, long, int)
16 
17  This is rather simple business... wouldn't mpg123 offer replacing the I/O core with callbacks. Translating the callbacks between long and off_t world is the main reason why this file contains non-trivial code.
18 
19  Note about file descriptors: We just assume that they are generally interchangeable between large and small file code... and that a large file descriptor will trigger errors when accessed with small file code where it may cause trouble (a really large file).
20 */
21 
22 /* It mainly needs the official API ... */
23 /* ... but also some inside access (frame struct, readers). */
24 #include "mpg123lib_intern.h"
25 /* Include the system headers _after_ the implied config.h!
26  Otherwise _FILE_OFFSET_BITS is not in effect! */
27 #include <errno.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include "compat.h"
31 #include "debug.h"
32 
33 /*
34  Now, start off easy... translate simple API calls.
35  I need to deal with these here:
36 perl -ne '
37 if(/^\s*MPG123_EXPORT\s+(\S+)\s+(mpg123_\S+)\((.*)\);\s*$/)
38 {
39  $type = $1;
40  $name = $2;
41  $args = $3;
42  next unless ($type =~ /off_t/ or $args =~ /off_t/);
43  print "$name\n" unless grep {$_ eq $name}
44  ("mpg123_open", "mpg123_open_fd", "mpg123_open_handle", "mpg123_replace_reader", "mpg123_replace_reader_handle");
45 }' < mpg123.h.in
46 
47 mpg123_decode_frame
48 mpg123_framebyframe_decode
49 mpg123_framepos
50 mpg123_tell
51 mpg123_tellframe
52 mpg123_tell_stream
53 mpg123_seek
54 mpg123_feedseek
55 mpg123_seek_frame
56 mpg123_timeframe
57 mpg123_index
58 mpg123_set_index
59 mpg123_position
60 mpg123_length
61 mpg123_set_filesize
62 mpg123_decode_raw ... that's experimental.
63 
64 Let's work on them in that order.
65 */
66 
67 /* I see that I will need custom data storage. Main use is for the replaced I/O later, but the seek table for small file offsets needs extra storage, too. */
68 
69 /* The wrapper handle for descriptor and handle I/O. */
70 
71 /* The handle is used for nothing (0), or one of these two modes of operation: */
72 #define IO_FD 1 /* Wrapping over callbacks operation on integer file descriptor. */
73 #define IO_HANDLE 2 /* Wrapping over custom handle callbacks. */
74 
75 struct wrap_data
76 {
77  /* Storage for small offset index table. */
78  long *indextable;
79  /* I/O handle stuff */
80  int iotype; /* IO_FD or IO_HANDLE */
81  /* Data for IO_FD. */
82  int fd;
83  int my_fd; /* A descriptor that the wrapper code opened itself. */
84  /* The actual callbacks from the outside. */
85  ssize_t (*r_read) (int, void *, size_t);
87  /* Data for IO_HANDLE. */
88  void* handle;
89  ssize_t (*r_h_read)(void *, void *, size_t);
90  long (*r_h_lseek)(void*, long, int);
91  void (*h_cleanup)(void*);
92 };
93 
94 
95 /* Cleanup I/O part of the handle handle... but not deleting the wrapper handle itself.
96  That is stored in the frame and only deleted on mpg123_delete(). */
97 static void wrap_io_cleanup(void *handle)
98 {
99  struct wrap_data *ioh = handle;
100  if(ioh->iotype == IO_HANDLE)
101  {
102  if(ioh->h_cleanup != NULL && ioh->handle != NULL)
103  ioh->h_cleanup(ioh->handle);
104 
105  ioh->handle = NULL;
106  }
107  if(ioh->my_fd >= 0)
108  {
109  close(ioh->my_fd);
110  ioh->my_fd = -1;
111  }
112 }
113 
114 /* Really finish off the handle... freeing all memory. */
115 static void wrap_destroy(void *handle)
116 {
117  struct wrap_data *wh = handle;
119  if(wh->indextable != NULL)
120  free(wh->indextable);
121 
122  free(wh);
123 }
124 
125 /* More helper code... extract the special wrapper handle, possible allocate and initialize it. */
126 static struct wrap_data* wrap_get(mpg123_handle *mh)
127 {
128  struct wrap_data* whd;
129  if(mh == NULL) return NULL;
130 
131  /* Access the private storage inside the mpg123 handle.
132  The real callback functions and handles are stored there. */
133  if(mh->wrapperdata == NULL)
134  {
135  /* Create a new one. */
136  mh->wrapperdata = malloc(sizeof(struct wrap_data));
137  if(mh->wrapperdata == NULL)
138  {
139  mh->err = MPG123_OUT_OF_MEM;
140  return NULL;
141  }
142  /* When we have wrapper data present, the callback for its proper cleanup is needed. */
144 
145  whd = mh->wrapperdata;
146  whd->indextable = NULL;
147  whd->iotype = 0;
148  whd->fd = -1;
149  whd->my_fd = -1;
150  whd->r_read = NULL;
151  whd->r_lseek = NULL;
152  whd->handle = NULL;
153  whd->r_h_read = NULL;
154  whd->r_h_lseek = NULL;
155  whd->h_cleanup = NULL;
156  }
157  else whd = mh->wrapperdata;
158 
159  return whd;
160 }
161 
162 /* After settling the data... start with some simple wrappers. */
163 
164 #undef mpg123_decode_frame
165 /* int mpg123_decode_frame(mpg123_handle *mh, off_t *num, unsigned char **audio, size_t *bytes) */
166 int attribute_align_arg mpg123_decode_frame(mpg123_handle *mh, long *num, unsigned char **audio, size_t *bytes)
167 {
168  off_t largenum;
169  int err;
170 
171  err = MPG123_LARGENAME(mpg123_decode_frame)(mh, &largenum, audio, bytes);
172  if(err == MPG123_OK && num != NULL)
173  {
174  *num = largenum;
175  if(*num != largenum)
176  {
177  mh->err = MPG123_LFS_OVERFLOW;
178  err = MPG123_ERR;
179  }
180  }
181  return err;
182 }
183 
184 #undef mpg123_framebyframe_decode
185 /* int mpg123_framebyframe_decode(mpg123_handle *mh, off_t *num, unsigned char **audio, size_t *bytes); */
186 int attribute_align_arg mpg123_framebyframe_decode(mpg123_handle *mh, long *num, unsigned char **audio, size_t *bytes)
187 {
188  off_t largenum;
189  int err;
190 
191  err = MPG123_LARGENAME(mpg123_framebyframe_decode)(mh, &largenum, audio, bytes);
192  if(err == MPG123_OK && num != NULL)
193  {
194  *num = largenum;
195  if(*num != largenum)
196  {
197  mh->err = MPG123_LFS_OVERFLOW;
198  err = MPG123_ERR;
199  }
200  }
201  return err;
202 }
203 
204 #undef mpg123_framepos
205 /* off_t mpg123_framepos(mpg123_handle *mh); */
207 {
208  long val;
209  off_t largeval;
210 
211  largeval = MPG123_LARGENAME(mpg123_framepos)(mh);
212  val = largeval;
213  if(val != largeval)
214  {
215  mh->err = MPG123_LFS_OVERFLOW;
216  return MPG123_ERR;
217  }
218  return val;
219 }
220 
221 #undef mpg123_tell
222 /* off_t mpg123_tell(mpg123_handle *mh); */
224 {
225  long val;
226  off_t largeval;
227 
228  largeval = MPG123_LARGENAME(mpg123_tell)(mh);
229  val = largeval;
230  if(val != largeval)
231  {
232  mh->err = MPG123_LFS_OVERFLOW;
233  return MPG123_ERR;
234  }
235  return val;
236 }
237 
238 #undef mpg123_tellframe
239 /* off_t mpg123_tellframe(mpg123_handle *mh); */
241 {
242  long val;
243  off_t largeval;
244 
245  largeval = MPG123_LARGENAME(mpg123_tellframe)(mh);
246  val = largeval;
247  if(val != largeval)
248  {
249  mh->err = MPG123_LFS_OVERFLOW;
250  return MPG123_ERR;
251  }
252  return val;
253 }
254 
255 #undef mpg123_tell_stream
256 /* off_t mpg123_tell_stream(mpg123_handle *mh); */
258 {
259  long val;
260  off_t largeval;
261 
262  largeval = MPG123_LARGENAME(mpg123_tell_stream)(mh);
263  val = largeval;
264  if(val != largeval)
265  {
266  mh->err = MPG123_LFS_OVERFLOW;
267  return MPG123_ERR;
268  }
269  return val;
270 }
271 
272 #undef mpg123_seek
273 /* off_t mpg123_seek(mpg123_handle *mh, off_t sampleoff, int whence); */
274 long attribute_align_arg mpg123_seek(mpg123_handle *mh, long sampleoff, int whence)
275 {
276  long val;
277  off_t largeval;
278 
279  largeval = MPG123_LARGENAME(mpg123_seek)(mh, sampleoff, whence);
280  val = largeval;
281  if(val != largeval)
282  {
283  mh->err = MPG123_LFS_OVERFLOW;
284  return MPG123_ERR;
285  }
286  return val;
287 }
288 
289 #undef mpg123_feedseek
290 /* off_t mpg123_feedseek(mpg123_handle *mh, off_t sampleoff, int whence, off_t *input_offset); */
291 long attribute_align_arg mpg123_feedseek(mpg123_handle *mh, long sampleoff, int whence, long *input_offset)
292 {
293  long val;
294  off_t largeioff;
295  off_t largeval;
296 
297  largeval = MPG123_LARGENAME(mpg123_feedseek)(mh, sampleoff, whence, &largeioff);
298  /* Error/message codes are small... */
299  if(largeval < 0) return (long)largeval;
300 
301  val = largeval;
302  *input_offset = largeioff;
303  if(val != largeval || *input_offset != largeioff)
304  {
305  mh->err = MPG123_LFS_OVERFLOW;
306  return MPG123_ERR;
307  }
308  return val;
309 }
310 
311 #undef mpg123_seek_frame
312 /* off_t mpg123_seek_frame(mpg123_handle *mh, off_t frameoff, int whence); */
313 long attribute_align_arg mpg123_seek_frame(mpg123_handle *mh, long frameoff, int whence)
314 {
315  long val;
316  off_t largeval;
317 
318  largeval = MPG123_LARGENAME(mpg123_seek_frame)(mh, frameoff, whence);
319  val = largeval;
320  if(val != largeval)
321  {
322  mh->err = MPG123_LFS_OVERFLOW;
323  return MPG123_ERR;
324  }
325  return val;
326 }
327 
328 #undef mpg123_timeframe
329 /* off_t mpg123_timeframe(mpg123_handle *mh, double sec); */
331 {
332  long val;
333  off_t largeval;
334 
335  largeval = MPG123_LARGENAME(mpg123_timeframe)(mh, sec);
336  val = largeval;
337  if(val != largeval)
338  {
339  mh->err = MPG123_LFS_OVERFLOW;
340  return MPG123_ERR;
341  }
342  return val;
343 }
344 
345 /* Now something less simple: Index retrieval and manipulation.
346  The index is an _array_ of off_t, which means that I need to construct a copy with translated long values. */
347 #undef mpg123_index
348 /* int mpg123_index(mpg123_handle *mh, off_t **offsets, off_t *step, size_t *fill) */
349 int attribute_align_arg mpg123_index(mpg123_handle *mh, long **offsets, long *step, size_t *fill)
350 {
351  int err;
352  size_t i;
353  long smallstep;
354  size_t thefill;
355  off_t largestep;
356  off_t *largeoffsets;
357  struct wrap_data *whd;
358 
359  whd = wrap_get(mh);
360  if(whd == NULL) return MPG123_ERR;
361 
362  err = MPG123_LARGENAME(mpg123_index)(mh, &largeoffsets, &largestep, &thefill);
363  if(err != MPG123_OK) return err;
364 
365  /* For a _very_ large file, even the step could overflow. */
366  smallstep = largestep;
367  if(smallstep != largestep)
368  {
369  mh->err = MPG123_LFS_OVERFLOW;
370  return MPG123_ERR;
371  }
372  if(step != NULL) *step = smallstep;
373 
374  /* When there are no values stored, there is no table content to take care of.
375  Table pointer does not matter. Mission completed. */
376  if(thefill == 0) return MPG123_OK;
377 
378  if(fill != NULL) *fill = thefill;
379 
380  /* Construct a copy of the index to hand over to the small-minded client. */
381  *offsets = safe_realloc(whd->indextable, (*fill)*sizeof(long));
382  if(*offsets == NULL)
383  {
384  mh->err = MPG123_OUT_OF_MEM;
385  return MPG123_ERR;
386  }
387  whd->indextable = *offsets;
388  /* Elaborate conversion of each index value, with overflow check. */
389  for(i=0; i<*fill; ++i)
390  {
391  whd->indextable[i] = largeoffsets[i];
392  if(whd->indextable[i] != largeoffsets[i])
393  {
394  mh->err = MPG123_LFS_OVERFLOW;
395  return MPG123_ERR;
396  }
397  }
398  /* If we came that far... there should be a valid copy of the table now. */
399  return MPG123_OK;
400 }
401 
402 /* The writing does basically the same than the above, just the opposite.
403  Oh, and the overflow checks are not needed -- off_t is bigger than long. */
404 #undef mpg123_set_index
405 /* int mpg123_set_index(mpg123_handle *mh, off_t *offsets, off_t step, size_t fill); */
406 int attribute_align_arg mpg123_set_index(mpg123_handle *mh, long *offsets, long step, size_t fill)
407 {
408  int err;
409  size_t i;
410  struct wrap_data *whd;
411  off_t *indextmp;
412 
413  whd = wrap_get(mh);
414  if(whd == NULL) return MPG123_ERR;
415 
416  /* Expensive temporary storage... for staying outside at the API layer. */
417  indextmp = malloc(fill*sizeof(off_t));
418  if(indextmp == NULL)
419  {
420  mh->err = MPG123_OUT_OF_MEM;
421  return MPG123_ERR;
422  }
423 
424  if(fill > 0 && offsets == NULL)
425  {
427  err = MPG123_ERR;
428  }
429  else
430  {
431  /* Fill the large-file copy of the provided index, then feed it to mpg123. */
432  for(i=0; i<fill; ++i)
433  indextmp[i] = offsets[i];
434 
435  err = MPG123_LARGENAME(mpg123_set_index)(mh, indextmp, step, fill);
436  }
437  free(indextmp);
438 
439  return err;
440 }
441 
442 /* So... breathe... a couple of simple wrappers before the big mess. */
443 #undef mpg123_position
444 /* int mpg123_position( mpg123_handle *mh, off_t frame_offset, off_t buffered_bytes, off_t *current_frame, off_t *frames_left, double *current_seconds, double *seconds_left); */
445 int attribute_align_arg mpg123_position(mpg123_handle *mh, long frame_offset, long buffered_bytes, long *current_frame, long *frames_left, double *current_seconds, double *seconds_left)
446 {
447  off_t curframe, frameleft;
448  long small_curframe, small_frameleft;
449  int err;
450 
451  err = MPG123_LARGENAME(mpg123_position)(mh, frame_offset, buffered_bytes, &curframe, &frameleft, current_seconds, seconds_left);
452  if(err != MPG123_OK) return err;
453 
454  small_curframe = curframe;
455  small_frameleft = frameleft;
456  if(small_curframe != curframe || small_frameleft != frameleft)
457  {
458  mh->err = MPG123_LFS_OVERFLOW;
459  return MPG123_ERR;
460  }
461 
462  if(current_frame != NULL) *current_frame = small_curframe;
463 
464  if(frames_left != NULL) *frames_left = small_frameleft;
465 
466 
467  return MPG123_OK;
468 }
469 
470 #undef mpg123_framelength
471 /* off_t mpg123_framelength(mpg123_handle *mh); */
473 {
474  long val;
475  off_t largeval;
476 
477  largeval = MPG123_LARGENAME(mpg123_framelength)(mh);
478  val = largeval;
479  if(val != largeval)
480  {
481  mh->err = MPG123_LFS_OVERFLOW;
482  return MPG123_ERR;
483  }
484  return val;
485 }
486 
487 #undef mpg123_length
488 /* off_t mpg123_length(mpg123_handle *mh); */
490 {
491  long val;
492  off_t largeval;
493 
494  largeval = MPG123_LARGENAME(mpg123_length)(mh);
495  val = largeval;
496  if(val != largeval)
497  {
498  mh->err = MPG123_LFS_OVERFLOW;
499  return MPG123_ERR;
500  }
501  return val;
502 }
503 
504 /* The simplest wrapper of all... */
505 #undef mpg123_set_filesize
506 /* int mpg123_set_filesize(mpg123_handle *mh, off_t size); */
508 {
509  return MPG123_LARGENAME(mpg123_set_filesize)(mh, size);
510 }
511 
512 
513 /* =========================================
514  THE BOUNDARY OF SANITY
515  Behold, stranger!
516  ========================================= */
517 
518 
519 /*
520  The messy part: Replacement of I/O core (actally, this is only due to lseek()).
521  Both descriptor and handle replaced I/O are mapped to replaced handle I/O, the handle wrapping over the actual callbacks and the actual handle/descriptor.
522  You got multiple levels of handles and callbacks to think about. Have fun reading and comprehending.
523 */
524 
525 /* Could go into compat.h ... Windows needs that flag. */
526 #ifndef O_BINARY
527 #define O_BINARY 0
528 #endif
529 
530 /* Read callback needs nothing special. */
531 ssize_t wrap_read(void* handle, void *buf, size_t count)
532 {
533  struct wrap_data *ioh = handle;
534  switch(ioh->iotype)
535  {
536  case IO_FD: return ioh->r_read(ioh->fd, buf, count);
537  case IO_HANDLE: return ioh->r_h_read(ioh->handle, buf, count);
538  }
539  error("Serious breakage - bad IO type in LFS wrapper!");
540  return -1;
541 }
542 
543 /* Seek callback needs protection from too big offsets. */
544 off_t wrap_lseek(void *handle, off_t offset, int whence)
545 {
546  struct wrap_data *ioh = handle;
547  long smalloff = offset;
548  if(smalloff == offset)
549  {
550  switch(ioh->iotype)
551  {
552  case IO_FD: return ioh->r_lseek(ioh->fd, smalloff, whence);
553  case IO_HANDLE: return ioh->r_h_lseek(ioh->handle, smalloff, whence);
554  }
555  error("Serious breakage - bad IO type in LFS wrapper!");
556  return -1;
557  }
558  else
559  {
560  errno = EOVERFLOW;
561  return -1;
562  }
563 }
564 
565 
566 /*
567  Now, let's replace the API dealing with replacement I/O.
568  Start with undefining the renames...
569 */
570 
571 #undef mpg123_replace_reader
572 #undef mpg123_replace_reader_handle
573 #undef mpg123_open
574 #undef mpg123_open_fd
575 #undef mpg123_open_handle
576 
577 
578 /* Normal reader replacement needs fallback implementations. */
579 static ssize_t fallback_read(int fd, void *buf, size_t count)
580 {
581  return read(fd, buf, count);
582 }
583 
584 static long fallback_lseek(int fd, long offset, int whence)
585 {
586  /* Since the offset is long int already, the returned value really should fit into a long... but whatever. */
587  long newpos_long;
588  off_t newpos;
589  newpos = lseek(fd, offset, whence);
590  newpos_long = newpos;
591  if(newpos_long == newpos)
592  return newpos_long;
593  else
594  {
595  errno = EOVERFLOW;
596  return -1;
597  }
598 }
599 
600 /* Reader replacement prepares the hidden handle storage for next mpg123_open_fd() or plain mpg123_open(). */
601 int attribute_align_arg mpg123_replace_reader(mpg123_handle *mh, ssize_t (*r_read) (int, void *, size_t), long (*r_lseek)(int, long, int) )
602 {
603  struct wrap_data* ioh;
604 
605  if(mh == NULL) return MPG123_ERR;
606 
607  mpg123_close(mh);
608  ioh = wrap_get(mh);
609  if(ioh == NULL) return MPG123_ERR;
610 
611  /* If both callbacks are NULL, switch totally to internal I/O, else just use fallback for at most half of them. */
612  if(r_read == NULL && r_lseek == NULL)
613  {
614  /* Only the type is actually important to disable the code. */
615  ioh->iotype = 0;
616  ioh->fd = -1;
617  ioh->r_read = NULL;
618  ioh->r_lseek = NULL;
619  }
620  else
621  {
622  ioh->iotype = IO_FD;
623  ioh->fd = -1; /* On next mpg123_open_fd(), this gets a value. */
624  ioh->r_read = r_read != NULL ? r_read : fallback_read;
625  ioh->r_lseek = r_lseek != NULL ? r_lseek : fallback_lseek;
626  }
627 
628  /* The real reader replacement will happen while opening. */
629  return MPG123_OK;
630 }
631 
632 int attribute_align_arg mpg123_replace_reader_handle(mpg123_handle *mh, ssize_t (*r_read) (void*, void *, size_t), long (*r_lseek)(void*, long, int), void (*cleanup)(void*))
633 {
634  struct wrap_data* ioh;
635 
636  if(mh == NULL) return MPG123_ERR;
637 
638  mpg123_close(mh);
639  ioh = wrap_get(mh);
640  if(ioh == NULL) return MPG123_ERR;
641 
642  ioh->iotype = IO_HANDLE;
643  ioh->handle = NULL;
644  ioh->r_h_read = r_read;
645  ioh->r_h_lseek = r_lseek;
646  ioh->h_cleanup = cleanup;
647 
648  /* The real reader replacement will happen while opening. */
649  return MPG123_OK;
650 }
651 
652 /*
653  The open routines always need to watch out for a prepared wrapper handle to use replaced normal I/O.
654  Two cases to consider:
655  1. Plain normal open using internal I/O.
656  2. Client called mpg123_replace_reader() before.
657  The second case needs hackery to activate the client I/O callbacks. For that, we create a custom I/O handle and use the guts of mpg123_open_fd() on it.
658 */
660 {
661  struct wrap_data* ioh;
662 
663  if(mh == NULL) return MPG123_ERR;
664 
665  ioh = mh->wrapperdata;
666  /* Mimic the use of mpg123_replace_reader() functions by lower levels...
667  IO_HANDLE is not valid here, though. Only IO_FD. */
668  if(ioh != NULL && ioh->iotype == IO_FD)
669  {
670  int err;
672  if(err != MPG123_OK) return MPG123_ERR;
673 
674  /* The above call implied mpg123_close() already */
675  /*
676  I really need to open the file here... to be able to use the replacer handle I/O ...
677  my_fd is used to indicate closing of the descriptor on cleanup.
678  */
680  if(ioh->my_fd < 0)
681  {
682  if(!(mh->p.flags & MPG123_QUIET)) error2("Cannot open file %s: %s", path, strerror(errno));
683 
684  mh->err = MPG123_BAD_FILE;
685  return MPG123_ERR;
686  }
687  /* Store a copy of the descriptor where it is actually used. */
688  ioh->fd = ioh->my_fd;
689  /* Initiate I/O operating on my handle now. */
690  err = open_stream_handle(mh, ioh);
691  if(err != MPG123_OK)
692  {
693  wrap_io_cleanup(ioh);
694  return MPG123_ERR;
695  }
696  /* All fine... */
697  return MPG123_OK;
698  }
699  else return MPG123_LARGENAME(mpg123_open)(mh, path);
700 }
701 
702 /*
703  This is in fact very similar to the above:
704  The open routines always need to watch out for a prepared wrapper handle to use replaced normal I/O.
705  Two cases to consider:
706  1. Plain normal open_fd using internal I/O.
707  2. Client called mpg123_replace_reader() before.
708  The second case needs hackery to activate the client I/O callbacks. For that, we create a custom I/O handle and use the guts of mpg123_open_fd() on it.
709 */
710 
712 {
713  struct wrap_data* ioh;
714 
715  if(mh == NULL) return MPG123_ERR;
716 
717  mpg123_close(mh);
718  ioh = mh->wrapperdata;
719  if(ioh != NULL && ioh->iotype == IO_FD)
720  {
721  int err;
723  if(err != MPG123_OK) return MPG123_ERR;
724 
725  /* The above call implied mpg123_close() already */
726 
727  /* Store the real file descriptor inside the handle. */
728  ioh->fd = fd;
729  /* Initiate I/O operating on my handle now. */
730  err = open_stream_handle(mh, ioh);
731  if(err != MPG123_OK)
732  {
733  wrap_io_cleanup(ioh);
734  return MPG123_ERR;
735  }
736  /* All fine... */
737  return MPG123_OK;
738  }
739  else return MPG123_LARGENAME(mpg123_open_fd)(mh, fd);
740 }
741 
743 {
744  struct wrap_data* ioh;
745 
746  if(mh == NULL) return MPG123_ERR;
747 
748  mpg123_close(mh);
749  ioh = mh->wrapperdata;
750  if(ioh != NULL && ioh->iotype == IO_HANDLE && ioh->r_h_read != NULL)
751  {
752  /* Wrap the custom handle into my handle. */
753  int err;
755  if(err != MPG123_OK) return MPG123_ERR;
756 
757  ioh->handle = handle;
758  /* No extra error handling, keep behaviour of the original open_handle. */
759  return open_stream_handle(mh, ioh);
760  }
761  else
762  {
763  /* This is an error ... you need to prepare the I/O before using it. */
765  return MPG123_ERR;
766  }
767 }
768 
long(* r_h_lseek)(void *, long, int)
Definition: lfs_wrap.c:90
long attribute_align_arg mpg123_timeframe(mpg123_handle *mh, double sec)
Definition: lfs_wrap.c:330
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define frame_offset
Definition: intsym.h:190
long attribute_align_arg mpg123_feedseek(mpg123_handle *mh, long sampleoff, int whence, long *input_offset)
Definition: lfs_wrap.c:291
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
struct mpg123_pars_struct p
Definition: frame.h:287
#define compat_open
Definition: intsym.h:12
#define error(str)
Definition: mkdosfs.c:1605
#define EOVERFLOW
Definition: errno.h:82
#define IO_HANDLE
Definition: lfs_wrap.c:73
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static void wrap_destroy(void *handle)
Definition: lfs_wrap.c:115
GLsizei const GLchar ** path
Definition: glext.h:7234
GLuint GLuint GLsizei count
Definition: gl.h:1545
void * wrapperdata
Definition: frame.h:333
long attribute_align_arg mpg123_tell_stream(mpg123_handle *mh)
Definition: lfs_wrap.c:257
#define free
Definition: debug_ros.c:5
__kernel_off_t off_t
Definition: linux.h:201
GLintptr offset
Definition: glext.h:5920
long attribute_align_arg mpg123_tell(mpg123_handle *mh)
Definition: lfs_wrap.c:223
int attribute_align_arg mpg123_position(mpg123_handle *mh, long frame_offset, long buffered_bytes, long *current_frame, long *frames_left, double *current_seconds, double *seconds_left)
Definition: lfs_wrap.c:445
static int fd
Definition: io.c:51
_Check_return_opt_ _CRTIMP long __cdecl lseek(_In_ int _FileHandle, _In_ long _Offset, _In_ int _Origin)
#define ssize_t
Definition: config.h:469
#define safe_realloc
Definition: intsym.h:10
#define open_stream_handle
Definition: intsym.h:242
int errno
off_t wrap_lseek(void *handle, off_t offset, int whence)
Definition: lfs_wrap.c:544
const char * strerror(int err)
Definition: compat_str.c:23
ssize_t(* r_h_read)(void *, void *, size_t)
Definition: lfs_wrap.c:89
void(* wrapperclean)(void *)
Definition: frame.h:335
long attribute_align_arg mpg123_framepos(mpg123_handle *mh)
Definition: lfs_wrap.c:206
int attribute_align_arg mpg123_framebyframe_decode(mpg123_handle *mh, long *num, unsigned char **audio, size_t *bytes)
Definition: lfs_wrap.c:186
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
#define O_BINARY
Definition: lfs_wrap.c:527
MPG123_EXPORT int mpg123_close(mpg123_handle *mh)
Definition: libmpg123.c:1602
static ssize_t fallback_read(int fd, void *buf, size_t count)
Definition: lfs_wrap.c:579
smooth NULL
Definition: ftsmooth.c:416
ssize_t(* r_read)(int, void *, size_t)
Definition: lfs_wrap.c:85
#define error2(s, a, b)
Definition: debug.h:110
GLuint GLfloat * val
Definition: glext.h:7180
__kernel_size_t size_t
Definition: linux.h:237
long attribute_align_arg mpg123_tellframe(mpg123_handle *mh)
Definition: lfs_wrap.c:240
GLsizeiptr size
Definition: glext.h:5919
int attribute_align_arg mpg123_replace_reader_handle(mpg123_handle *mh, ssize_t(*r_read)(void *, void *, size_t), long(*r_lseek)(void *, long, int), void(*cleanup)(void *))
Definition: lfs_wrap.c:632
_STLP_MOVE_TO_STD_NAMESPACE void fill(_ForwardIter __first, _ForwardIter __last, const _Tp &__val)
Definition: _algobase.h:449
long attribute_align_arg mpg123_framelength(mpg123_handle *mh)
Definition: lfs_wrap.c:472
long attribute_align_arg mpg123_seek(mpg123_handle *mh, long sampleoff, int whence)
Definition: lfs_wrap.c:274
GLuint GLuint num
Definition: glext.h:9618
int attribute_align_arg mpg123_open(mpg123_handle *mh, const char *path)
Definition: lfs_wrap.c:659
long(* r_lseek)(int, long, int)
Definition: lfs_wrap.c:86
int attribute_align_arg mpg123_set_index(mpg123_handle *mh, long *offsets, long step, size_t fill)
Definition: lfs_wrap.c:406
void * handle
Definition: lfs_wrap.c:88
ssize_t wrap_read(void *handle, void *buf, size_t count)
Definition: lfs_wrap.c:531
int ssize_t
Definition: rosdhcp.h:48
#define close
Definition: acwin.h:98
#define err(...)
int attribute_align_arg mpg123_open_handle(mpg123_handle *mh, void *handle)
Definition: lfs_wrap.c:742
int attribute_align_arg mpg123_replace_reader(mpg123_handle *mh, ssize_t(*r_read)(int, void *, size_t), long(*r_lseek)(int, long, int))
Definition: lfs_wrap.c:601
#define long
Definition: qsort.c:33
Definition: services.c:325
long attribute_align_arg mpg123_length(mpg123_handle *mh)
Definition: lfs_wrap.c:489
int attribute_align_arg mpg123_index(mpg123_handle *mh, long **offsets, long *step, size_t *fill)
Definition: lfs_wrap.c:349
int fd
Definition: lfs_wrap.c:82
long attribute_align_arg mpg123_seek_frame(mpg123_handle *mh, long frameoff, int whence)
Definition: lfs_wrap.c:313
int iotype
Definition: lfs_wrap.c:80
char * cleanup(char *str)
Definition: wpickclick.c:99
static void wrap_io_cleanup(void *handle)
Definition: lfs_wrap.c:97
int attribute_align_arg mpg123_set_filesize(mpg123_handle *mh, long size)
Definition: lfs_wrap.c:507
#define malloc
Definition: debug_ros.c:4
int attribute_align_arg mpg123_open_fd(mpg123_handle *mh, int fd)
Definition: lfs_wrap.c:711
#define attribute_align_arg
Definition: abi_align.h:30
void(* h_cleanup)(void *)
Definition: lfs_wrap.c:91
int attribute_align_arg mpg123_decode_frame(mpg123_handle *mh, long *num, unsigned char **audio, size_t *bytes)
Definition: lfs_wrap.c:166
#define IO_FD
Definition: lfs_wrap.c:72
_CRTIMP int __cdecl read(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void *_DstBuf, _In_ unsigned int _MaxCharCount)
long * indextable
Definition: lfs_wrap.c:78
static struct wrap_data * wrap_get(mpg123_handle *mh)
Definition: lfs_wrap.c:126
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define O_RDONLY
Definition: acwin.h:108
static long fallback_lseek(int fd, long offset, int whence)
Definition: lfs_wrap.c:584
int my_fd
Definition: lfs_wrap.c:83