ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

lfs_wrap.c
Go to the documentation of this file.
00001 /*
00002     lfs_wrap: Crappy wrapper code for supporting crappy ambiguous large file support.
00003 
00004     copyright 2010 by the mpg123 project - free software under the terms of the LGPL 2.1
00005     see COPYING and AUTHORS files in distribution or http://mpg123.org
00006 
00007     initially written by Thomas Orgis, thanks to Guido Draheim for consulting
00008 
00009     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).
00010     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.
00011 
00012     Prototypical idea: There is
00013         off_t mpg123_seek_64(mpg123_handle*, off_t, int)
00014     This code provides
00015         long mpg123_seek(mpg123_handle*, long, int)
00016 
00017     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.
00018 
00019     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).
00020 */
00021 
00022 /* It mainly needs the official API ... */
00023 /* ... but also some inside access (frame struct, readers). */
00024 #include "mpg123lib_intern.h"
00025 /* Include the system headers _after_ the implied config.h!
00026    Otherwise _FILE_OFFSET_BITS is not in effect! */
00027 #include <errno.h>
00028 #include <sys/stat.h>
00029 #include <fcntl.h>
00030 #include "compat.h"
00031 #include "debug.h"
00032 
00033 #include "aligncheck.h"
00034 
00035 #include "mpg123.h"
00036 
00037 /*
00038     Now, start off easy... translate simple API calls.
00039     I need to deal with these here:
00040 perl -ne '
00041 if(/^\s*EXPORT\s+(\S+)\s+(mpg123_\S+)\((.*)\);\s*$/)
00042 {
00043     $type = $1;
00044     $name = $2;
00045     $args = $3;
00046     next unless ($type =~ /off_t/ or $args =~ /off_t/);
00047     print "$name\n" unless grep {$_ eq $name} 
00048         ("mpg123_open", "mpg123_open_fd", "mpg123_open_handle", "mpg123_replace_reader", "mpg123_replace_reader_handle");
00049 }' < mpg123.h.in
00050 
00051 mpg123_decode_frame
00052 mpg123_framebyframe_decode
00053 mpg123_tell
00054 mpg123_tellframe
00055 mpg123_tell_stream
00056 mpg123_seek
00057 mpg123_feedseek
00058 mpg123_seek_frame
00059 mpg123_timeframe
00060 mpg123_index
00061 mpg123_set_index
00062 mpg123_position
00063 mpg123_length
00064 mpg123_set_filesize
00065 
00066 Let's work on them in that order.
00067 */
00068 
00069 /* 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. */
00070 
00071 /* The wrapper handle for descriptor and handle I/O. */
00072 
00073 /* The handle is used for nothing (0), or one of these two modes of operation: */
00074 #define IO_FD 1 /* Wrapping over callbacks operation on integer file descriptor. */
00075 #define IO_HANDLE 2 /* Wrapping over custom handle callbacks. */
00076 
00077 struct wrap_data
00078 {
00079     /* Storage for small offset index table. */
00080     long *indextable;
00081     /* I/O handle stuff */
00082     int iotype; /* IO_FD or IO_HANDLE */
00083     /* Data for IO_FD. */
00084     int fd;
00085     int my_fd; /* A descriptor that the wrapper code opened itself. */
00086     /* The actual callbacks from the outside. */
00087     long (*r_read) (int, void *, size_t);
00088     long (*r_lseek)(int, long, int);
00089     /* Data for IO_HANDLE. */
00090     void* handle;
00091     long (*r_h_read)(void *, void *, size_t);
00092     long (*r_h_lseek)(void*, long, int);
00093     void (*h_cleanup)(void*);
00094 };
00095 
00096 
00097 /* Cleanup I/O part of the handle handle... but not deleting the wrapper handle itself.
00098    That is stored in the frame and only deleted on mpg123_delete(). */
00099 static void wrap_io_cleanup(void *handle)
00100 {
00101     struct wrap_data *ioh = handle;
00102     if(ioh->iotype == IO_HANDLE)
00103     {
00104         if(ioh->h_cleanup != NULL && ioh->handle != NULL)
00105         ioh->h_cleanup(ioh->handle);
00106 
00107         ioh->handle = NULL;
00108     }
00109     if(ioh->my_fd >= 0)
00110     {
00111         close(ioh->my_fd);
00112         ioh->my_fd = -1;
00113     }
00114 }
00115 
00116 /* Really finish off the handle... freeing all memory. */
00117 static void wrap_destroy(void *handle)
00118 {
00119     struct wrap_data *wh = handle;
00120     wrap_io_cleanup(handle);
00121     if(wh->indextable != NULL)
00122     free(wh->indextable);
00123 
00124     free(wh);
00125 }
00126 
00127 /* More helper code... extract the special wrapper handle, possible allocate and initialize it. */
00128 static struct wrap_data* wrap_get(mpg123_handle *mh)
00129 {
00130     struct wrap_data* whd;
00131     if(mh == NULL) return NULL;
00132 
00133     /* Access the private storage inside the mpg123 handle.
00134        The real callback functions and handles are stored there. */
00135     if(mh->wrapperdata == NULL)
00136     {
00137         /* Create a new one. */
00138         mh->wrapperdata = malloc(sizeof(struct wrap_data));
00139         if(mh->wrapperdata == NULL)
00140         {
00141             mh->err = MPG123_OUT_OF_MEM;
00142             return NULL;
00143         }
00144     /* When we have wrapper data present, the callback for its proper cleanup is needed. */
00145         mh->wrapperclean = wrap_destroy;
00146 
00147         whd = mh->wrapperdata;
00148         whd->indextable = NULL;
00149         whd->iotype = 0;
00150         whd->fd = -1;
00151         whd->my_fd = -1;
00152         whd->r_read = NULL;
00153         whd->r_lseek = NULL;
00154         whd->handle = NULL;
00155         whd->r_h_read = NULL;
00156         whd->r_h_lseek = NULL;
00157         whd->h_cleanup = NULL;
00158     }
00159     else whd = mh->wrapperdata;
00160 
00161     return whd;
00162 }
00163 
00164 /* After settling the data... start with some simple wrappers. */
00165 
00166 #undef mpg123_decode_frame
00167 /* int mpg123_decode_frame(mpg123_handle *mh, off_t *num, unsigned char **audio, size_t *bytes) */
00168 int attribute_align_arg mpg123_decode_frame(mpg123_handle *mh, long *num, unsigned char **audio, size_t *bytes)
00169 {
00170     off_t largenum;
00171     int err;
00172     ALIGNCHECK(mh);
00173     err = MPG123_LARGENAME(mpg123_decode_frame)(mh, &largenum, audio, bytes);
00174     if(err == MPG123_OK && num != NULL)
00175     {
00176         *num = largenum;
00177         if(*num != largenum)
00178         {
00179             mh->err = MPG123_LFS_OVERFLOW;
00180             err = MPG123_ERR;
00181         }
00182     }
00183     return err;
00184 }
00185 
00186 #undef mpg123_framebyframe_decode
00187 /* int mpg123_framebyframe_decode(mpg123_handle *mh, off_t *num, unsigned char **audio, size_t *bytes); */
00188 int attribute_align_arg mpg123_framebyframe_decode(mpg123_handle *mh, long *num, unsigned char **audio, size_t *bytes)
00189 {
00190     off_t largenum;
00191     int err;
00192     ALIGNCHECK(mh);
00193     err = MPG123_LARGENAME(mpg123_framebyframe_decode)(mh, &largenum, audio, bytes);
00194     if(err == MPG123_OK && num != NULL)
00195     {
00196         *num = largenum;
00197         if(*num != largenum)
00198         {
00199             mh->err = MPG123_LFS_OVERFLOW;
00200             err = MPG123_ERR;
00201         }
00202     }
00203     return err;
00204 }
00205 
00206 #undef mpg123_tell
00207 /* off_t mpg123_tell(mpg123_handle *mh); */
00208 long attribute_align_arg mpg123_tell(mpg123_handle *mh)
00209 {
00210     long val;
00211     off_t largeval;
00212     ALIGNCHECK(mh);
00213     largeval = MPG123_LARGENAME(mpg123_tell)(mh);
00214     val = largeval;
00215     if(val != largeval)
00216     {
00217         mh->err = MPG123_LFS_OVERFLOW;
00218         return MPG123_ERR;
00219     }
00220     return val;
00221 }
00222 
00223 #undef mpg123_tellframe
00224 /* off_t mpg123_tellframe(mpg123_handle *mh); */
00225 long attribute_align_arg mpg123_tellframe(mpg123_handle *mh)
00226 {
00227     long val;
00228     off_t largeval;
00229     ALIGNCHECK(mh);
00230     largeval = MPG123_LARGENAME(mpg123_tellframe)(mh);
00231     val = largeval;
00232     if(val != largeval)
00233     {
00234         mh->err = MPG123_LFS_OVERFLOW;
00235         return MPG123_ERR;
00236     }
00237     return val;
00238 }
00239 
00240 #undef mpg123_tell_stream
00241 /* off_t mpg123_tell_stream(mpg123_handle *mh); */
00242 long attribute_align_arg mpg123_tell_stream(mpg123_handle *mh)
00243 {
00244     long val;
00245     off_t largeval;
00246     ALIGNCHECK(mh);
00247     largeval = MPG123_LARGENAME(mpg123_tell_stream)(mh);
00248     val = largeval;
00249     if(val != largeval)
00250     {
00251         mh->err = MPG123_LFS_OVERFLOW;
00252         return MPG123_ERR;
00253     }
00254     return val;
00255 }
00256 
00257 #undef mpg123_seek
00258 /* off_t mpg123_seek(mpg123_handle *mh, off_t sampleoff, int whence); */
00259 long attribute_align_arg mpg123_seek(mpg123_handle *mh, long sampleoff, int whence)
00260 {
00261     long val;
00262     off_t largeval;
00263     ALIGNCHECK(mh);
00264     largeval = MPG123_LARGENAME(mpg123_seek)(mh, sampleoff, whence);
00265     val = largeval;
00266     if(val != largeval)
00267     {
00268         mh->err = MPG123_LFS_OVERFLOW;
00269         return MPG123_ERR;
00270     }
00271     return val;
00272 }
00273 
00274 #undef mpg123_feedseek
00275 /* off_t mpg123_feedseek(mpg123_handle *mh, off_t sampleoff, int whence, off_t *input_offset); */
00276 long attribute_align_arg mpg123_feedseek(mpg123_handle *mh, long sampleoff, int whence, long *input_offset)
00277 {
00278     long val;
00279     off_t largeioff;
00280     off_t largeval;
00281     ALIGNCHECK(mh);
00282     largeval = MPG123_LARGENAME(mpg123_feedseek)(mh, sampleoff, whence, &largeioff);
00283     /* Error/message codes are small... */
00284     if(largeval < 0) return (long)largeval;
00285 
00286     val = largeval;
00287     *input_offset = largeioff;
00288     if(val != largeval || *input_offset != largeioff)
00289     {
00290         mh->err = MPG123_LFS_OVERFLOW;
00291         return MPG123_ERR;
00292     }
00293     return val;
00294 }
00295 
00296 #undef mpg123_seek_frame
00297 /* off_t mpg123_seek_frame(mpg123_handle *mh, off_t frameoff, int whence); */
00298 long attribute_align_arg mpg123_seek_frame(mpg123_handle *mh, long frameoff, int whence)
00299 {
00300     long val;
00301     off_t largeval;
00302     ALIGNCHECK(mh);
00303     largeval = MPG123_LARGENAME(mpg123_seek_frame)(mh, frameoff, whence);
00304     val = largeval;
00305     if(val != largeval)
00306     {
00307         mh->err = MPG123_LFS_OVERFLOW;
00308         return MPG123_ERR;
00309     }
00310     return val;
00311 }
00312 
00313 #undef mpg123_timeframe
00314 /* off_t mpg123_timeframe(mpg123_handle *mh, double sec); */
00315 long attribute_align_arg mpg123_timeframe(mpg123_handle *mh, double sec)
00316 {
00317     long val;
00318     off_t largeval;
00319     ALIGNCHECK(mh);
00320     largeval = MPG123_LARGENAME(mpg123_timeframe)(mh, sec);
00321     val = largeval;
00322     if(val != largeval)
00323     {
00324         mh->err = MPG123_LFS_OVERFLOW;
00325         return MPG123_ERR;
00326     }
00327     return val;
00328 }
00329 
00330 /* Now something less simple: Index retrieval and manipulation.
00331    The index is an _array_ of off_t, which means that I need to construct a copy with translated long values. */
00332 #undef mpg123_index
00333 /* int mpg123_index(mpg123_handle *mh, off_t **offsets, off_t *step, size_t *fill) */
00334 int attribute_align_arg mpg123_index(mpg123_handle *mh, long **offsets, long *step, size_t *fill)
00335 {
00336     int err;
00337     size_t i;
00338     long smallstep;
00339     size_t thefill;
00340     off_t largestep;
00341     off_t *largeoffsets;
00342     struct wrap_data *whd;
00343     ALIGNCHECK(mh);
00344     whd = wrap_get(mh);
00345     if(whd == NULL) return MPG123_ERR;
00346 
00347     err = MPG123_LARGENAME(mpg123_index)(mh, &largeoffsets, &largestep, &thefill);
00348     if(err != MPG123_OK) return err;
00349 
00350     /* For a _very_ large file, even the step could overflow. */
00351     smallstep = largestep;
00352     if(smallstep != largestep)
00353     {
00354         mh->err = MPG123_LFS_OVERFLOW;
00355         return MPG123_ERR;
00356     }
00357     if(step != NULL) *step = smallstep;
00358 
00359     /* When there are no values stored, there is no table content to take care of.
00360        Table pointer does not matter. Mission completed. */
00361     if(thefill == 0) return MPG123_OK;
00362 
00363     if(fill != NULL) *fill = thefill;
00364 
00365     /* Construct a copy of the index to hand over to the small-minded client. */
00366     *offsets = safe_realloc(whd->indextable, (*fill)*sizeof(long));
00367     if(*offsets == NULL)
00368     {
00369         mh->err = MPG123_OUT_OF_MEM;
00370         return MPG123_ERR;
00371     }
00372     whd->indextable = *offsets;
00373     /* Elaborate conversion of each index value, with overflow check. */
00374     for(i=0; i<*fill; ++i)
00375     {
00376         whd->indextable[i] = largeoffsets[i];
00377         if(whd->indextable[i] != largeoffsets[i])
00378         {
00379             mh->err = MPG123_LFS_OVERFLOW;
00380             return MPG123_ERR;
00381         }
00382     }
00383     /* If we came that far... there should be a valid copy of the table now. */
00384     return MPG123_OK;
00385 }
00386 
00387 /* The writing does basically the same than the above, just the opposite.
00388    Oh, and the overflow checks are not needed -- off_t is bigger than long. */
00389 #undef mpg123_set_index
00390 /* int mpg123_set_index(mpg123_handle *mh, off_t *offsets, off_t step, size_t fill); */
00391 int attribute_align_arg mpg123_set_index(mpg123_handle *mh, long *offsets, long step, size_t fill)
00392 {
00393     int err;
00394     size_t i;
00395     struct wrap_data *whd;
00396     off_t *indextmp;
00397     ALIGNCHECK(mh);
00398     whd = wrap_get(mh);
00399     if(whd == NULL) return MPG123_ERR;
00400 
00401     /* Expensive temporary storage... for staying outside at the API layer. */
00402     indextmp = malloc(fill*sizeof(off_t));
00403     if(indextmp == NULL)
00404     {
00405         mh->err = MPG123_OUT_OF_MEM;
00406         return MPG123_ERR;
00407     }
00408 
00409     if(fill > 0 && offsets == NULL)
00410     {
00411         mh->err = MPG123_BAD_INDEX_PAR;
00412         err = MPG123_ERR;
00413     }
00414     else
00415     {
00416         /* Fill the large-file copy of the provided index, then feed it to mpg123. */
00417         for(i=0; i<fill; ++i)
00418         indextmp[i] = offsets[i];
00419 
00420         err = MPG123_LARGENAME(mpg123_set_index)(mh, indextmp, step, fill);
00421     }
00422     free(indextmp);
00423 
00424     return err;
00425 }
00426 
00427 /* So... breathe... a couple of simple wrappers before the big mess. */
00428 #undef mpg123_position
00429 /* 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); */
00430 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)
00431 {
00432     off_t curframe, frameleft;
00433     long small_curframe, small_frameleft;
00434     int err;
00435     ALIGNCHECK(mh);
00436     err = MPG123_LARGENAME(mpg123_position)(mh, frame_offset, buffered_bytes, &curframe, &frameleft, current_seconds, seconds_left);
00437     if(err != MPG123_OK) return err;
00438 
00439     small_curframe = curframe;
00440     small_frameleft = frameleft;
00441     if(small_curframe != curframe || small_frameleft != frameleft)
00442     {
00443         mh->err = MPG123_LFS_OVERFLOW;
00444         return MPG123_ERR;
00445     }
00446 
00447     if(current_frame != NULL) *current_frame = small_curframe;
00448 
00449     if(frames_left != NULL) *frames_left = small_frameleft;
00450 
00451 
00452     return MPG123_OK;
00453 }
00454 
00455 #undef mpg123_length
00456 /* off_t mpg123_length(mpg123_handle *mh); */
00457 long attribute_align_arg mpg123_length(mpg123_handle *mh)
00458 {
00459     long val;
00460     off_t largeval;
00461     ALIGNCHECK(mh);
00462     largeval = MPG123_LARGENAME(mpg123_length)(mh);
00463     val = largeval;
00464     if(val != largeval)
00465     {
00466         mh->err = MPG123_LFS_OVERFLOW;
00467         return MPG123_ERR;
00468     }
00469     return val;
00470 }
00471 
00472 /* The simplest wrapper of all... */
00473 #undef mpg123_set_filesize
00474 /* int mpg123_set_filesize(mpg123_handle *mh, off_t size); */
00475 int attribute_align_arg mpg123_set_filesize(mpg123_handle *mh, long size)
00476 {
00477     ALIGNCHECK(mh);
00478     return MPG123_LARGENAME(mpg123_set_filesize)(mh, size);
00479 }
00480 
00481 
00482 /* =========================================
00483              THE BOUNDARY OF SANITY
00484                Behold, stranger!
00485    ========================================= */
00486 
00487 
00488 /*
00489     The messy part: Replacement of I/O core (actally, this is only due to lseek()).
00490     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.
00491     You got multiple levels of handles and callbacks to think about. Have fun reading and comprehending.
00492 */
00493 
00494 /* Could go into compat.h ... Windows needs that flag. */
00495 #ifndef O_BINARY
00496 #define O_BINARY 0
00497 #endif
00498 
00499 /* Read callback needs nothing special. */
00500 long wrap_read(void* handle, void *buf, size_t count)
00501 {
00502     struct wrap_data *ioh = handle;
00503     switch(ioh->iotype)
00504     {
00505         case IO_FD: return ioh->r_read(ioh->fd, buf, count);
00506         case IO_HANDLE: return ioh->r_h_read(ioh->handle, buf, count);
00507     }
00508     error("Serious breakage - bad IO type in LFS wrapper!");
00509     return -1;
00510 }
00511 
00512 /* Seek callback needs protection from too big offsets. */
00513 off_t wrap_lseek(void *handle, off_t offset, int whence)
00514 {
00515     struct wrap_data *ioh = handle;
00516     long smalloff = offset;
00517     if(smalloff == offset)
00518     {
00519         switch(ioh->iotype)
00520         {
00521             case IO_FD: return ioh->r_lseek(ioh->fd, smalloff, whence);
00522             case IO_HANDLE: return ioh->r_h_lseek(ioh->handle, smalloff, whence);
00523         }
00524         error("Serious breakage - bad IO type in LFS wrapper!");
00525         return -1;
00526     }
00527     else
00528     {
00529         errno = EOVERFLOW;
00530         return -1;
00531     }
00532 }
00533 
00534 
00535 /*
00536     Now, let's replace the API dealing with replacement I/O.
00537     Start with undefining the renames...
00538 */
00539 
00540 #undef mpg123_replace_reader
00541 #undef mpg123_replace_reader_handle
00542 #undef mpg123_open
00543 #undef mpg123_open_fd
00544 #undef mpg123_open_handle
00545 
00546 
00547 /* Normal reader replacement needs fallback implementations. */
00548 static long fallback_read(int fd, void *buf, size_t count)
00549 {
00550     return read(fd, buf, count);
00551 }
00552 
00553 static long fallback_lseek(int fd, long offset, int whence)
00554 {
00555     /* Since the offset is long int already, the returned value really should fit into a long... but whatever. */
00556     long newpos_long;
00557     off_t newpos;
00558     newpos = lseek(fd, offset, whence);
00559     newpos_long = newpos;
00560     if(newpos_long == newpos)
00561     return newpos_long;
00562     else
00563     {
00564         errno = EOVERFLOW;
00565         return -1;
00566     }
00567 }
00568 
00569 /* Reader replacement prepares the hidden handle storage for next mpg123_open_fd() or plain mpg123_open(). */
00570 int attribute_align_arg mpg123_replace_reader(mpg123_handle *mh, long (*r_read) (int, void *, size_t), long (*r_lseek)(int, long, int) )
00571 {
00572     struct wrap_data* ioh;
00573     ALIGNCHECK(mh);
00574     if(mh == NULL) return MPG123_ERR;
00575 
00576     mpg123_close(mh);
00577     ioh = wrap_get(mh);
00578     if(ioh == NULL) return MPG123_ERR;
00579 
00580     /* If both callbacks are NULL, switch totally to internal I/O, else just use fallback for at most half of them. */
00581     if(r_read == NULL && r_lseek == NULL)
00582     {
00583         /* Only the type is actually important to disable the code. */
00584         ioh->iotype = 0;
00585         ioh->fd = -1;
00586         ioh->r_read = NULL;
00587         ioh->r_lseek = NULL;
00588     }
00589     else
00590     {
00591         ioh->iotype = IO_FD;
00592         ioh->fd = -1; /* On next mpg123_open_fd(), this gets a value. */
00593         ioh->r_read = r_read != NULL ? r_read : fallback_read;
00594         ioh->r_lseek = r_lseek != NULL ? r_lseek : fallback_lseek;
00595     }
00596 
00597     /* The real reader replacement will happen while opening. */
00598     return MPG123_OK;
00599 }
00600 
00601 int attribute_align_arg mpg123_replace_reader_handle(mpg123_handle *mh, long (*r_read) (void*, void *, size_t), long (*r_lseek)(void*, long, int), void (*cleanup)(void*))
00602 {
00603     struct wrap_data* ioh;
00604     ALIGNCHECK(mh);
00605     if(mh == NULL) return MPG123_ERR;
00606 
00607     mpg123_close(mh);
00608     ioh = wrap_get(mh);
00609     if(ioh == NULL) return MPG123_ERR;
00610 
00611     ioh->iotype = IO_HANDLE;
00612     ioh->handle = NULL;
00613     ioh->r_h_read = r_read;
00614     ioh->r_h_lseek = r_lseek;
00615     ioh->h_cleanup = cleanup;
00616 
00617     /* The real reader replacement will happen while opening. */
00618     return MPG123_OK;
00619 }
00620 
00621 /*
00622     The open routines always need to watch out for a prepared wrapper handle to use replaced normal I/O.
00623     Two cases to consider:
00624     1. Plain normal open using internal I/O.
00625     2. Client called mpg123_replace_reader() before.
00626     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.
00627 */
00628 int attribute_align_arg mpg123_open(mpg123_handle *mh, const char *path)
00629 {
00630     struct wrap_data* ioh;
00631     ALIGNCHECK(mh);
00632 
00633     if(mh == NULL) return MPG123_ERR;
00634 
00635     ioh = mh->wrapperdata;
00636     /* Mimic the use of mpg123_replace_reader() functions by lower levels...
00637        IO_HANDLE is not valid here, though. Only IO_FD. */
00638     if(ioh != NULL && ioh->iotype == IO_FD)
00639     {
00640         int err;
00641         err = MPG123_LARGENAME(mpg123_replace_reader_handle)(mh, wrap_read, wrap_lseek, wrap_io_cleanup);
00642         if(err != MPG123_OK) return MPG123_ERR;
00643 
00644         /* The above call implied mpg123_close() already */
00645         /*
00646             I really need to open the file here... to be able to use the replacer handle I/O ...
00647             my_fd is used to indicate closing of the descriptor on cleanup.
00648         */
00649         ioh->my_fd = compat_open(path, O_RDONLY|O_BINARY);
00650         if(ioh->my_fd < 0)
00651         {
00652             if(!(mh->p.flags & MPG123_QUIET)) error2("Cannot open file %s: %s", path, strerror(errno));
00653 
00654             mh->err = MPG123_BAD_FILE;
00655             return MPG123_ERR;
00656         }
00657         /* Store a copy of the descriptor where it is actually used. */
00658         ioh->fd = ioh->my_fd;
00659         /* Initiate I/O operating on my handle now. */
00660         err = open_stream_handle(mh, ioh);
00661         if(err != MPG123_OK)
00662         {
00663             wrap_io_cleanup(ioh);
00664             return MPG123_ERR;
00665         }
00666         /* All fine... */
00667         return MPG123_OK;
00668     }
00669     else return MPG123_LARGENAME(mpg123_open)(mh, path);
00670 }
00671 
00672 /*
00673     This is in fact very similar to the above:
00674     The open routines always need to watch out for a prepared wrapper handle to use replaced normal I/O.
00675     Two cases to consider:
00676     1. Plain normal open_fd using internal I/O.
00677     2. Client called mpg123_replace_reader() before.
00678     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.
00679 */
00680 
00681 int attribute_align_arg mpg123_open_fd(mpg123_handle *mh, int fd)
00682 {
00683     struct wrap_data* ioh;
00684     ALIGNCHECK(mh);
00685 
00686     if(mh == NULL) return MPG123_ERR;
00687 
00688     mpg123_close(mh);
00689     ioh = mh->wrapperdata;
00690     if(ioh != NULL && ioh->iotype == IO_FD)
00691     {
00692         int err;
00693         err = MPG123_LARGENAME(mpg123_replace_reader_handle)(mh, wrap_read, wrap_lseek, wrap_io_cleanup);
00694         if(err != MPG123_OK) return MPG123_ERR;
00695 
00696         /* The above call implied mpg123_close() already */
00697 
00698         /* Store the real file descriptor inside the handle. */
00699         ioh->fd = fd;
00700         /* Initiate I/O operating on my handle now. */
00701         err = open_stream_handle(mh, ioh);
00702         if(err != MPG123_OK)
00703         {
00704             wrap_io_cleanup(ioh);
00705             return MPG123_ERR;
00706         }
00707         /* All fine... */
00708         return MPG123_OK;
00709     }
00710     else return MPG123_LARGENAME(mpg123_open_fd)(mh, fd);
00711 }
00712 
00713 int attribute_align_arg mpg123_open_handle(mpg123_handle *mh, void *handle)
00714 {
00715     struct wrap_data* ioh;
00716     ALIGNCHECK(mh);
00717 
00718     if(mh == NULL) return MPG123_ERR;
00719 
00720     mpg123_close(mh);
00721     ioh = mh->wrapperdata;
00722     if(ioh != NULL && ioh->iotype == IO_HANDLE && ioh->r_h_read != NULL)
00723     {
00724         /* Wrap the custom handle into my handle. */
00725         int err;
00726         err = MPG123_LARGENAME(mpg123_replace_reader_handle)(mh, wrap_read, wrap_lseek, wrap_io_cleanup);
00727         if(err != MPG123_OK) return MPG123_ERR;
00728 
00729         ioh->handle = handle;
00730         /* No extra error handling, keep behaviour of the original open_handle. */
00731         return open_stream_handle(mh, ioh);
00732     }
00733     else
00734     {
00735         /* This is an error ... you need to prepare the I/O before using it. */
00736         mh->err = MPG123_BAD_CUSTOM_IO;
00737         return MPG123_ERR;
00738     }
00739 }
00740 

Generated on Fri May 25 2012 04:32:37 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.