Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenlfs_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
1.7.6.1
|