00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <sys/time.h>
00026 #include <fcntl.h>
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <errno.h>
00030 #include <string.h>
00031 #include <ctype.h>
00032 #include <unistd.h>
00033 #include <limits.h>
00034 #include <dirent.h>
00035
00036
00037 #ifdef WIN32
00038 #ifndef HAVE_GETTIMEOFDAY
00039
00040 #include <sys/timeb.h>
00041 static inline int _private_gettimeofday( struct timeval *tv, void *tz )
00042 {
00043 struct timeb t;
00044 ftime( &t );
00045 tv->tv_sec = t.time;
00046 tv->tv_usec = t.millitm * 1000;
00047 return 0;
00048 }
00049 #define gettimeofday(TV, TZ) _private_gettimeofday((TV), (TZ))
00050 #endif
00051 #include <io.h>
00052 #define lseek64 _lseeki64
00053 #endif
00054
00055 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__) || defined(__APPLE__)
00056 #define SYS_BSD 1
00057 #endif
00058
00059 #if defined(__sun)
00060 #include <sys/mnttab.h>
00061 #elif defined(SYS_BSD)
00062 #include <fstab.h>
00063 #elif defined(__linux__)
00064 #include <mntent.h>
00065 #include <paths.h>
00066 #endif
00067
00068 #include "dvdread/dvd_udf.h"
00069 #include "dvd_input.h"
00070 #include "dvdread/dvd_reader.h"
00071 #include "md5.h"
00072 #include "mythiowrapper.h"
00073
00074 #define DEFAULT_UDF_CACHE_LEVEL 1
00075
00076 struct dvd_reader_s {
00077
00078 int isImageFile;
00079
00080
00081
00082 int css_state;
00083 int css_title;
00084
00085
00086 dvd_input_t dev;
00087
00088
00089 char *path_root;
00090
00091
00092 int udfcache_level;
00093 void *udfcache;
00094 };
00095
00096 #define TITLES_MAX 9
00097
00098 struct dvd_file_s {
00099
00100 dvd_reader_t *dvd;
00101
00102
00103 int css_title;
00104
00105
00106 uint32_t lb_start;
00107 uint32_t seek_pos;
00108
00109
00110 size_t title_sizes[ TITLES_MAX ];
00111 dvd_input_t title_devs[ TITLES_MAX ];
00112
00113
00114 ssize_t filesize;
00115 };
00116
00117 int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number,
00118 size_t block_count, unsigned char *data,
00119 int encrypted );
00120
00126 int DVDUDFCacheLevel(dvd_reader_t *device, int level)
00127 {
00128 struct dvd_reader_s *dev = (struct dvd_reader_s *)device;
00129
00130 if(level > 0) {
00131 level = 1;
00132 } else if(level < 0) {
00133 return dev->udfcache_level;
00134 }
00135
00136 dev->udfcache_level = level;
00137
00138 return level;
00139 }
00140
00141 void *GetUDFCacheHandle(dvd_reader_t *device)
00142 {
00143 struct dvd_reader_s *dev = (struct dvd_reader_s *)device;
00144
00145 return dev->udfcache;
00146 }
00147
00148 void SetUDFCacheHandle(dvd_reader_t *device, void *cache)
00149 {
00150 struct dvd_reader_s *dev = (struct dvd_reader_s *)device;
00151
00152 dev->udfcache = cache;
00153 }
00154
00155
00156
00157
00158 static int initAllCSSKeys( dvd_reader_t *dvd )
00159 {
00160 struct timeval all_s, all_e;
00161 struct timeval t_s, t_e;
00162 char filename[ MAX_UDF_FILE_NAME_LEN ];
00163 uint32_t start, len;
00164 int title;
00165
00166 char *nokeys_str = getenv("DVDREAD_NOKEYS");
00167 if(nokeys_str != NULL)
00168 return 0;
00169
00170 fprintf( stderr, "\n" );
00171 fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" );
00172 fprintf( stderr, "libdvdread: This can take a _long_ time, "
00173 "please be patient\n\n" );
00174 gettimeofday(&all_s, NULL);
00175
00176 for( title = 0; title < 100; title++ ) {
00177 gettimeofday( &t_s, NULL );
00178 if( title == 0 ) {
00179 sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
00180 } else {
00181 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 );
00182 }
00183 start = UDFFindFile( dvd, filename, &len );
00184 if( start != 0 && len != 0 ) {
00185
00186 fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
00187 filename, start );
00188 if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
00189 fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)\n", filename, start);
00190 }
00191 gettimeofday( &t_e, NULL );
00192 fprintf( stderr, "libdvdread: Elapsed time %ld\n",
00193 (long int) t_e.tv_sec - t_s.tv_sec );
00194 }
00195
00196 if( title == 0 ) continue;
00197
00198 gettimeofday( &t_s, NULL );
00199 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 );
00200 start = UDFFindFile( dvd, filename, &len );
00201 if( start == 0 || len == 0 ) break;
00202
00203
00204 fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
00205 filename, start );
00206 if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
00207 fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)!!\n", filename, start);
00208 }
00209 gettimeofday( &t_e, NULL );
00210 fprintf( stderr, "libdvdread: Elapsed time %ld\n",
00211 (long int) t_e.tv_sec - t_s.tv_sec );
00212 }
00213 title--;
00214
00215 fprintf( stderr, "libdvdread: Found %d VTS's\n", title );
00216 gettimeofday(&all_e, NULL);
00217 fprintf( stderr, "libdvdread: Elapsed time %ld\n",
00218 (long int) all_e.tv_sec - all_s.tv_sec );
00219
00220 return 0;
00221 }
00222
00223
00224
00228 static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css )
00229 {
00230 dvd_reader_t *dvd;
00231 dvd_input_t dev;
00232
00233 dev = dvdinput_open( location );
00234 if( !dev ) {
00235 fprintf( stderr, "libdvdread: Can't open %s for reading\n", location );
00236 return NULL;
00237 }
00238
00239 dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
00240 if( !dvd ) {
00241 dvdinput_close(dev);
00242 return NULL;
00243 }
00244 memset( dvd, 0, sizeof( dvd_reader_t ) );
00245 dvd->isImageFile = 1;
00246 dvd->dev = dev;
00247 dvd->path_root = NULL;
00248
00249 dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL;
00250 dvd->udfcache = NULL;
00251
00252 if( have_css ) {
00253
00254
00255
00256
00257 dvd->css_state = 1;
00258 }
00259 dvd->css_title = 0;
00260
00261 return dvd;
00262 }
00263
00264 static dvd_reader_t *DVDOpenPath( const char *path_root )
00265 {
00266 dvd_reader_t *dvd;
00267
00268 dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
00269 if( !dvd ) return NULL;
00270 dvd->isImageFile = 0;
00271 dvd->dev = 0;
00272 dvd->path_root = strdup( path_root );
00273 if(!dvd->path_root) {
00274 free(dvd);
00275 return 0;
00276 }
00277 dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL;
00278 dvd->udfcache = NULL;
00279
00280 dvd->css_state = 0;
00281 dvd->css_title = 0;
00282
00283 return dvd;
00284 }
00285
00286 #if defined(__sun)
00287
00288
00289
00290 static char *sun_block2char( const char *path )
00291 {
00292 char *new_path;
00293
00294
00295 if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path );
00296
00297
00298 new_path = malloc( strlen(path) + 2 );
00299 strcpy( new_path, path );
00300 strcpy( strstr( new_path, "/dsk/" ), "" );
00301 strcat( new_path, "/rdsk/" );
00302 strcat( new_path, strstr( path, "/dsk/" ) + strlen( "/dsk/" ) );
00303
00304 return new_path;
00305 }
00306 #endif
00307
00308 #if defined(SYS_BSD)
00309
00310
00311
00312
00313
00314
00315
00316
00317 static char *bsd_block2char( const char *path )
00318 {
00319 #if defined(__FreeBSD__) || defined(__DragonFly__)
00320 return (char *) strdup( path );
00321 #else
00322 char *new_path;
00323
00324
00325 if( strncmp( path, "/dev/", 5 ) || !strncmp( path, "/dev/r", 6 ) )
00326 return (char *) strdup( path );
00327
00328
00329 new_path = malloc( strlen(path) + 2 );
00330 strcpy( new_path, "/dev/r" );
00331 strcat( new_path, path + strlen( "/dev/" ) );
00332
00333 return new_path;
00334 #endif
00335 }
00336 #endif
00337
00338
00339 dvd_reader_t *DVDOpen( const char *ppath )
00340 {
00341 struct stat fileinfo;
00342 int ret, have_css, retval, cdir = -1;
00343 dvd_reader_t *ret_val = NULL;
00344 char *dev_name = NULL;
00345 char *path = NULL, *new_path = NULL, *path_copy = NULL;
00346
00347 #if defined(_WIN32) || defined(__OS2__)
00348 int len;
00349 #endif
00350
00351 if( ppath == NULL )
00352 goto DVDOpen_error;
00353
00354 path = strdup(ppath);
00355 if( path == NULL )
00356 goto DVDOpen_error;
00357
00358
00359 have_css = dvdinput_setup(path);
00360
00361 #if defined(_WIN32) || defined(__OS2__)
00362
00363 len = strlen(path);
00364 if ((len > 1) &&
00365 (path[len - 1] == '\\') &&
00366 (path[len - 2] != ':'))
00367 {
00368 path[len-1] = '\0';
00369 }
00370 #endif
00371
00372 ret = mythfile_stat( path, &fileinfo );
00373
00374 if( ret < 0 ) {
00375
00376
00377 if( strchr(path,':') ) {
00378 ret_val = DVDOpenImageFile( path, have_css );
00379 free(path);
00380 return ret_val;
00381 }
00382
00383
00384 fprintf( stderr, "libdvdread: Can't stat %s\n", path );
00385 perror("");
00386 goto DVDOpen_error;
00387 }
00388
00389
00390 if( S_ISBLK( fileinfo.st_mode ) ||
00391 S_ISCHR( fileinfo.st_mode ) ||
00392 S_ISREG( fileinfo.st_mode ) ) {
00393
00397 dvd_reader_t *dvd = NULL;
00398 #if defined(__sun)
00399 dev_name = sun_block2char( path );
00400 #elif defined(SYS_BSD)
00401 dev_name = bsd_block2char( path );
00402 #else
00403 dev_name = strdup( path );
00404 #endif
00405 dvd = DVDOpenImageFile( dev_name, have_css );
00406 free( dev_name );
00407 free(path);
00408 return dvd;
00409 } else if( S_ISDIR( fileinfo.st_mode ) ) {
00410 dvd_reader_t *auth_drive = 0;
00411 #if defined(SYS_BSD)
00412 struct fstab* fe;
00413 #elif defined(__sun) || defined(__linux__)
00414 FILE *mntfile;
00415 #endif
00416
00417
00418 if( !(path_copy = strdup( path ) ) )
00419 goto DVDOpen_error;
00420
00421 #ifndef WIN32
00422
00423
00424
00425 if (!strncmp(path, "myth://", 7))
00426 dev_name = strdup( path );
00427 else
00428 {
00429 if( ( cdir = open( ".", O_RDONLY ) ) >= 0 ) {
00430 if( chdir( path_copy ) == -1 ) {
00431 goto DVDOpen_error;
00432 }
00433 new_path = malloc(PATH_MAX+1);
00434 if(!new_path) {
00435 goto DVDOpen_error;
00436 }
00437 if( getcwd( new_path, PATH_MAX ) == NULL ) {
00438 goto DVDOpen_error;
00439 }
00440 retval = fchdir( cdir );
00441 close( cdir );
00442 cdir = -1;
00443 if( retval == -1 ) {
00444 goto DVDOpen_error;
00445 }
00446 path_copy = new_path;
00447 new_path = NULL;
00448 }
00449 }
00450 #endif
00451
00457 if( strlen( path_copy ) > 1 ) {
00458 if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) {
00459 path_copy[ strlen( path_copy ) - 1 ] = '\0';
00460 }
00461 }
00462
00463 #if defined(_WIN32) || defined(__OS2__)
00464 if(strlen(path_copy) > TITLES_MAX) {
00465 if(!strcasecmp(&(path_copy[strlen( path_copy ) - TITLES_MAX]),
00466 "\\video_ts"))
00467 path_copy[strlen(path_copy) - (TITLES_MAX-1)] = '\0';
00468 }
00469 #endif
00470 if( strlen( path_copy ) > TITLES_MAX ) {
00471 if( !strcasecmp( &(path_copy[ strlen( path_copy ) - TITLES_MAX ]),
00472 "/video_ts" ) ) {
00473 path_copy[ strlen( path_copy ) - TITLES_MAX ] = '\0';
00474 }
00475 }
00476
00477 if(path_copy[0] == '\0') {
00478 path_copy[0] = '/';
00479 path_copy[1] = '\0';
00480 }
00481
00482 #if defined(SYS_BSD)
00483 if( ( fe = getfsfile( path_copy ) ) ) {
00484 dev_name = bsd_block2char( fe->fs_spec );
00485 fprintf( stderr,
00486 "libdvdread: Attempting to use device %s"
00487 " mounted on %s for CSS authentication\n",
00488 dev_name,
00489 fe->fs_file );
00490 auth_drive = DVDOpenImageFile( dev_name, have_css );
00491 }
00492 #elif defined(__sun)
00493 mntfile = fopen( MNTTAB, "r" );
00494 if( mntfile ) {
00495 struct mnttab mp;
00496 int res;
00497
00498 while( ( res = getmntent( mntfile, &mp ) ) != -1 ) {
00499 if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
00500 dev_name = sun_block2char( mp.mnt_special );
00501 fprintf( stderr,
00502 "libdvdread: Attempting to use device %s"
00503 " mounted on %s for CSS authentication\n",
00504 dev_name,
00505 mp.mnt_mountp );
00506 auth_drive = DVDOpenImageFile( dev_name, have_css );
00507 break;
00508 }
00509 }
00510 fclose( mntfile );
00511 }
00512 #elif defined(__linux__)
00513 mntfile = fopen( _PATH_MOUNTED, "r" );
00514 if( mntfile ) {
00515 struct mntent *me;
00516
00517 while( ( me = getmntent( mntfile ) ) ) {
00518 if( !strcmp( me->mnt_dir, path_copy ) ) {
00519 fprintf( stderr,
00520 "libdvdread: Attempting to use device %s"
00521 " mounted on %s for CSS authentication\n",
00522 me->mnt_fsname,
00523 me->mnt_dir );
00524 auth_drive = DVDOpenImageFile( me->mnt_fsname, have_css );
00525 dev_name = strdup(me->mnt_fsname);
00526 break;
00527 }
00528 }
00529 fclose( mntfile );
00530 }
00531 #elif defined(_WIN32) || defined(__OS2__)
00532 #ifdef __OS2__
00533
00534 if(isalpha(path[0]) && path[1] == ':' &&
00535 ( !path[2] ||
00536 ((path[2] == '\\' || path[2] == '/') && !path[3])))
00537 #endif
00538 auth_drive = DVDOpenImageFile( path, have_css );
00539 #endif
00540
00541 #if !defined(_WIN32) && !defined(__OS2__)
00542 if( !dev_name ) {
00543 fprintf( stderr, "libdvdread: Couldn't find device name.\n" );
00544 } else if( !auth_drive ) {
00545 fprintf( stderr, "libdvdread: Device %s inaccessible, "
00546 "CSS authentication not available.\n", dev_name );
00547 }
00548 #else
00549 if( !auth_drive ) {
00550 fprintf( stderr, "libdvdread: Device %s inaccessible, "
00551 "CSS authentication not available.\n", path );
00552 }
00553 #endif
00554
00555 free( dev_name );
00556 dev_name = NULL;
00557 free( path_copy );
00558 path_copy = NULL;
00559
00563 if( auth_drive ) {
00564 free(path);
00565 return auth_drive;
00566 }
00570 ret_val = DVDOpenPath( path );
00571 free( path );
00572 return ret_val;
00573 }
00574
00575 DVDOpen_error:
00576
00577 fprintf( stderr, "libdvdread: Could not open %s\n", path );
00578 if( path != NULL )
00579 free( path );
00580 if ( path_copy != NULL )
00581 free( path_copy );
00582 if ( cdir >= 0 )
00583 close( cdir );
00584 if ( new_path != NULL )
00585 free( new_path );
00586 return NULL;
00587 }
00588
00589 void DVDClose( dvd_reader_t *dvd )
00590 {
00591 if( dvd ) {
00592 if( dvd->dev ) dvdinput_close( dvd->dev );
00593 if( dvd->path_root ) free( dvd->path_root );
00594 if( dvd->udfcache ) FreeUDFCache( dvd->udfcache );
00595 free( dvd );
00596 }
00597 }
00598
00602 static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename )
00603 {
00604 uint32_t start, len;
00605 dvd_file_t *dvd_file;
00606
00607 start = UDFFindFile( dvd, filename, &len );
00608 if( !start ) {
00609 fprintf( stderr, "libdvdnav:DVDOpenFileUDF:UDFFindFile %s failed\n", filename );
00610 return NULL;
00611 }
00612
00613 dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
00614 if( !dvd_file ) {
00615 fprintf( stderr, "libdvdnav:DVDOpenFileUDF:malloc failed\n" );
00616 return NULL;
00617 }
00618 dvd_file->dvd = dvd;
00619 dvd_file->lb_start = start;
00620 dvd_file->seek_pos = 0;
00621 memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
00622 memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
00623 dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
00624
00625 return dvd_file;
00626 }
00627
00634 static int findDirFile( const char *path, const char *file, char *filename )
00635 {
00636 DIR *dir;
00637 struct dirent *ent;
00638
00639 if (!strncmp(path, "myth://", 7) && mythfile_exists(path, file))
00640 {
00641 sprintf( filename, "%s%s%s", path,
00642 ( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ),
00643 file );
00644 return 0;
00645 }
00646
00647 dir = opendir( path );
00648 if( !dir ) return -2;
00649
00650 while( ( ent = readdir( dir ) ) != NULL ) {
00651 if( !strcasecmp( ent->d_name, file ) ) {
00652 sprintf( filename, "%s%s%s", path,
00653 ( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ),
00654 ent->d_name );
00655 closedir(dir);
00656 return 0;
00657 }
00658 }
00659 closedir(dir);
00660 return -1;
00661 }
00662
00663 static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename )
00664 {
00665 char video_path[ PATH_MAX + 1 ];
00666 const char *nodirfile;
00667 int ret;
00668
00669
00670 if( !strncasecmp( "/VIDEO_TS/", file, 10 ) ) {
00671 nodirfile = &(file[ 10 ]);
00672 } else {
00673 nodirfile = file;
00674 }
00675
00676 ret = findDirFile( dvd->path_root, nodirfile, filename );
00677 if( ret < 0 ) {
00678
00679 sprintf( video_path, "%s/VIDEO_TS/", dvd->path_root );
00680 ret = findDirFile( video_path, nodirfile, filename );
00681 if( ret < 0 ) {
00682
00683 sprintf( video_path, "%s/video_ts/", dvd->path_root );
00684 ret = findDirFile( video_path, nodirfile, filename );
00685 if( ret < 0 ) {
00686 return 0;
00687 }
00688 }
00689 }
00690
00691 return 1;
00692 }
00693
00697 static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
00698 {
00699 char full_path[ PATH_MAX + 1 ];
00700 dvd_file_t *dvd_file;
00701 struct stat fileinfo;
00702 dvd_input_t dev;
00703
00704
00705 if( !findDVDFile( dvd, filename, full_path ) ) {
00706 fprintf( stderr, "libdvdnav:DVDOpenFilePath:findDVDFile %s failed\n", filename );
00707 return NULL;
00708 }
00709
00710 dev = dvdinput_open( full_path );
00711 if( !dev ) {
00712 fprintf( stderr, "libdvdnav:DVDOpenFilePath:dvdinput_open %s failed\n", full_path );
00713 return NULL;
00714 }
00715
00716 dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
00717 if( !dvd_file ) {
00718 fprintf( stderr, "libdvdnav:DVDOpenFilePath:dvd_file malloc failed\n" );
00719 dvdinput_close(dev);
00720 return NULL;
00721 }
00722 dvd_file->dvd = dvd;
00723 dvd_file->lb_start = 0;
00724 dvd_file->seek_pos = 0;
00725 memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
00726 memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
00727 dvd_file->filesize = 0;
00728
00729 if( mythfile_stat( full_path, &fileinfo ) < 0 ) {
00730 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
00731 free( dvd_file );
00732 dvdinput_close(dev);
00733 return NULL;
00734 }
00735 dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
00736 dvd_file->title_devs[ 0 ] = dev;
00737 dvd_file->filesize = dvd_file->title_sizes[ 0 ];
00738
00739 return dvd_file;
00740 }
00741
00742 static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu )
00743 {
00744 char filename[ MAX_UDF_FILE_NAME_LEN ];
00745 uint32_t start, len;
00746 dvd_file_t *dvd_file;
00747
00748 if( title == 0 ) {
00749 sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
00750 } else {
00751 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
00752 }
00753 start = UDFFindFile( dvd, filename, &len );
00754 if( start == 0 ) return NULL;
00755
00756 dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
00757 if( !dvd_file ) return NULL;
00758 dvd_file->dvd = dvd;
00759 dvd_file->css_title = title << 1 | menu;
00760 dvd_file->lb_start = start;
00761 dvd_file->seek_pos = 0;
00762 memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
00763 memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
00764 dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
00765
00766
00767 if( !menu ) {
00768 int cur;
00769
00770 for( cur = 2; cur < 10; cur++ ) {
00771 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
00772 if( !UDFFindFile( dvd, filename, &len ) ) break;
00773 dvd_file->filesize += len / DVD_VIDEO_LB_LEN;
00774 }
00775 }
00776
00777 if( dvd->css_state == 1 ) {
00778 initAllCSSKeys( dvd );
00779 dvd->css_state = 2;
00780 }
00781
00782
00783
00784
00785
00786
00787
00788 return dvd_file;
00789 }
00790
00791 static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu )
00792 {
00793 char filename[ MAX_UDF_FILE_NAME_LEN ];
00794 char full_path[ PATH_MAX + 1 ];
00795 struct stat fileinfo;
00796 dvd_file_t *dvd_file;
00797 int i;
00798
00799 dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
00800 if( !dvd_file ) return NULL;
00801 dvd_file->dvd = dvd;
00802 dvd_file->css_title = title << 1 | menu;
00803 dvd_file->lb_start = 0;
00804 dvd_file->seek_pos = 0;
00805 memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
00806 memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
00807 dvd_file->filesize = 0;
00808
00809 if( menu ) {
00810 dvd_input_t dev;
00811
00812 if( title == 0 ) {
00813 sprintf( filename, "VIDEO_TS.VOB" );
00814 } else {
00815 sprintf( filename, "VTS_%02i_0.VOB", title );
00816 }
00817 if( !findDVDFile( dvd, filename, full_path ) ) {
00818 free( dvd_file );
00819 return NULL;
00820 }
00821
00822 dev = dvdinput_open( full_path );
00823 if( dev == NULL ) {
00824 free( dvd_file );
00825 return NULL;
00826 }
00827
00828 if( mythfile_stat( full_path, &fileinfo ) < 0 ) {
00829 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
00830 dvdinput_close(dev);
00831 free( dvd_file );
00832 return NULL;
00833 }
00834 dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
00835 dvd_file->title_devs[ 0 ] = dev;
00836 dvdinput_title( dvd_file->title_devs[0], 0);
00837 dvd_file->filesize = dvd_file->title_sizes[ 0 ];
00838
00839 } else {
00840 for( i = 0; i < TITLES_MAX; ++i ) {
00841
00842 sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 );
00843 if( !findDVDFile( dvd, filename, full_path ) ) {
00844 break;
00845 }
00846
00847 if( mythfile_stat( full_path, &fileinfo ) < 0 ) {
00848 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
00849 break;
00850 }
00851
00852 dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
00853 dvd_file->title_devs[ i ] = dvdinput_open( full_path );
00854 dvdinput_title( dvd_file->title_devs[ i ], 0 );
00855 dvd_file->filesize += dvd_file->title_sizes[ i ];
00856 }
00857 if( !dvd_file->title_devs[ 0 ] ) {
00858 free( dvd_file );
00859 return NULL;
00860 }
00861 }
00862
00863 return dvd_file;
00864 }
00865
00866 dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
00867 dvd_read_domain_t domain )
00868 {
00869 char filename[ MAX_UDF_FILE_NAME_LEN ];
00870
00871
00872 if( dvd == NULL || titlenum < 0 )
00873 return NULL;
00874
00875 switch( domain ) {
00876 case DVD_READ_INFO_FILE:
00877 if( titlenum == 0 ) {
00878 sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" );
00879 } else {
00880 sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum );
00881 }
00882 break;
00883 case DVD_READ_INFO_BACKUP_FILE:
00884 if( titlenum == 0 ) {
00885 sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" );
00886 } else {
00887 sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum );
00888 }
00889 break;
00890 case DVD_READ_MENU_VOBS:
00891 if( dvd->isImageFile ) {
00892 return DVDOpenVOBUDF( dvd, titlenum, 1 );
00893 } else {
00894 return DVDOpenVOBPath( dvd, titlenum, 1 );
00895 }
00896 break;
00897 case DVD_READ_TITLE_VOBS:
00898 if( titlenum == 0 ) return 0;
00899 if( dvd->isImageFile ) {
00900 return DVDOpenVOBUDF( dvd, titlenum, 0 );
00901 } else {
00902 return DVDOpenVOBPath( dvd, titlenum, 0 );
00903 }
00904 break;
00905 default:
00906 fprintf( stderr, "libdvdread: Invalid domain for file open.\n" );
00907 return NULL;
00908 }
00909
00910 if( dvd->isImageFile ) {
00911 return DVDOpenFileUDF( dvd, filename );
00912 } else {
00913 return DVDOpenFilePath( dvd, filename );
00914 }
00915 }
00916
00917 void DVDCloseFile( dvd_file_t *dvd_file )
00918 {
00919 int i;
00920
00921 if( dvd_file ) {
00922 if( !dvd_file->dvd->isImageFile ) {
00923 for( i = 0; i < TITLES_MAX; ++i ) {
00924 if( dvd_file->title_devs[ i ] ) {
00925 dvdinput_close( dvd_file->title_devs[i] );
00926 }
00927 }
00928 }
00929
00930 free( dvd_file );
00931 dvd_file = 0;
00932 }
00933 }
00934
00935 static int DVDFileStatVOBUDF( dvd_reader_t *dvd, int title,
00936 int menu, dvd_stat_t *statbuf )
00937 {
00938 char filename[ MAX_UDF_FILE_NAME_LEN ];
00939 uint32_t size;
00940 off_t tot_size;
00941 off_t parts_size[ 9 ];
00942 int nr_parts = 0;
00943 int n;
00944
00945 if( title == 0 )
00946 sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
00947 else
00948 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
00949
00950 if( !UDFFindFile( dvd, filename, &size ) )
00951 return -1;
00952
00953 tot_size = size;
00954 nr_parts = 1;
00955 parts_size[ 0 ] = size;
00956
00957 if( !menu ) {
00958 int cur;
00959
00960 for( cur = 2; cur < 10; cur++ ) {
00961 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
00962 if( !UDFFindFile( dvd, filename, &size ) )
00963 break;
00964
00965 parts_size[ nr_parts ] = size;
00966 tot_size += size;
00967 nr_parts++;
00968 }
00969 }
00970
00971 statbuf->size = tot_size;
00972 statbuf->nr_parts = nr_parts;
00973 for( n = 0; n < nr_parts; n++ )
00974 statbuf->parts_size[ n ] = parts_size[ n ];
00975
00976 return 0;
00977 }
00978
00979
00980 static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title,
00981 int menu, dvd_stat_t *statbuf )
00982 {
00983 char filename[ MAX_UDF_FILE_NAME_LEN ];
00984 char full_path[ PATH_MAX + 1 ];
00985 struct stat fileinfo;
00986 off_t tot_size;
00987 off_t parts_size[ 9 ];
00988 int nr_parts = 0;
00989 int n;
00990
00991 if( title == 0 )
00992 sprintf( filename, "VIDEO_TS.VOB" );
00993 else
00994 sprintf( filename, "VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
00995
00996 if( !findDVDFile( dvd, filename, full_path ) )
00997 return -1;
00998
00999 if( mythfile_stat( full_path, &fileinfo ) < 0 ) {
01000 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
01001 return -1;
01002 }
01003
01004 tot_size = fileinfo.st_size;
01005 nr_parts = 1;
01006 parts_size[ 0 ] = fileinfo.st_size;
01007
01008 if( !menu ) {
01009 int cur;
01010 for( cur = 2; cur < 10; cur++ ) {
01011 sprintf( filename, "VTS_%02d_%d.VOB", title, cur );
01012 if( !findDVDFile( dvd, filename, full_path ) )
01013 break;
01014
01015 if( mythfile_stat( full_path, &fileinfo ) < 0 ) {
01016 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
01017 break;
01018 }
01019
01020 parts_size[ nr_parts ] = fileinfo.st_size;
01021 tot_size += parts_size[ nr_parts ];
01022 nr_parts++;
01023 }
01024 }
01025
01026 statbuf->size = tot_size;
01027 statbuf->nr_parts = nr_parts;
01028 for( n = 0; n < nr_parts; n++ )
01029 statbuf->parts_size[ n ] = parts_size[ n ];
01030
01031 return 0;
01032 }
01033
01034
01035 int DVDFileStat( dvd_reader_t *dvd, int titlenum,
01036 dvd_read_domain_t domain, dvd_stat_t *statbuf )
01037 {
01038 char filename[ MAX_UDF_FILE_NAME_LEN ];
01039 char full_path[ PATH_MAX + 1 ];
01040 struct stat fileinfo;
01041 uint32_t size;
01042
01043
01044 if( dvd == NULL || titlenum < 0 ) {
01045 errno = EINVAL;
01046 return -1;
01047 }
01048
01049 switch( domain ) {
01050 case DVD_READ_INFO_FILE:
01051 if( titlenum == 0 )
01052 sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" );
01053 else
01054 sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum );
01055
01056 break;
01057 case DVD_READ_INFO_BACKUP_FILE:
01058 if( titlenum == 0 )
01059 sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" );
01060 else
01061 sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum );
01062
01063 break;
01064 case DVD_READ_MENU_VOBS:
01065 if( dvd->isImageFile )
01066 return DVDFileStatVOBUDF( dvd, titlenum, 1, statbuf );
01067 else
01068 return DVDFileStatVOBPath( dvd, titlenum, 1, statbuf );
01069
01070 break;
01071 case DVD_READ_TITLE_VOBS:
01072 if( titlenum == 0 )
01073 return -1;
01074
01075 if( dvd->isImageFile )
01076 return DVDFileStatVOBUDF( dvd, titlenum, 0, statbuf );
01077 else
01078 return DVDFileStatVOBPath( dvd, titlenum, 0, statbuf );
01079
01080 break;
01081 default:
01082 fprintf( stderr, "libdvdread: Invalid domain for file stat.\n" );
01083 errno = EINVAL;
01084 return -1;
01085 }
01086
01087 if( dvd->isImageFile ) {
01088 if( UDFFindFile( dvd, filename, &size ) ) {
01089 statbuf->size = size;
01090 statbuf->nr_parts = 1;
01091 statbuf->parts_size[ 0 ] = size;
01092 return 0;
01093 }
01094 } else {
01095 if( findDVDFile( dvd, filename, full_path ) ) {
01096 if( mythfile_stat( full_path, &fileinfo ) < 0 )
01097 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
01098 else {
01099 statbuf->size = fileinfo.st_size;
01100 statbuf->nr_parts = 1;
01101 statbuf->parts_size[ 0 ] = statbuf->size;
01102 return 0;
01103 }
01104 }
01105 }
01106 return -1;
01107 }
01108
01109
01110 int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number,
01111 size_t block_count, unsigned char *data,
01112 int encrypted )
01113 {
01114 int ret;
01115
01116 if( !device->dev ) {
01117 fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
01118 return 0;
01119 }
01120
01121 ret = dvdinput_seek( device->dev, (int) lb_number );
01122 if( ret != (int) lb_number ) {
01123 fprintf( stderr, "libdvdread: Can't seek to block %u\n", lb_number );
01124 return 0;
01125 }
01126
01127 ret = dvdinput_read( device->dev, (char *) data,
01128 (int) block_count, encrypted );
01129 return ret;
01130 }
01131
01132
01133
01134
01135
01136
01137
01138 static int DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
01139 size_t block_count, unsigned char *data,
01140 int encrypted )
01141 {
01142 return UDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset,
01143 block_count, data, encrypted );
01144 }
01145
01146
01147
01148
01149
01150
01151
01152 static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset,
01153 size_t block_count, unsigned char *data,
01154 int encrypted )
01155 {
01156 int i;
01157 int ret, ret2, off;
01158
01159 ret = 0;
01160 ret2 = 0;
01161 for( i = 0; i < TITLES_MAX; ++i ) {
01162 if( !dvd_file->title_sizes[ i ] ) return 0;
01163
01164 if( offset < dvd_file->title_sizes[ i ] ) {
01165 if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
01166 off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset );
01167 if( off < 0 || off != (int)offset ) {
01168 fprintf( stderr, "libdvdread: Can't seek to block %d\n",
01169 offset );
01170 return off < 0 ? off : 0;
01171 }
01172 ret = dvdinput_read( dvd_file->title_devs[ i ], data,
01173 (int)block_count, encrypted );
01174 break;
01175 } else {
01176 size_t part1_size = dvd_file->title_sizes[ i ] - offset;
01177
01178
01179
01180
01181 off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset );
01182 if( off < 0 || off != (int)offset ) {
01183 fprintf( stderr, "libdvdread: Can't seek to block %d\n",
01184 offset );
01185 return off < 0 ? off : 0;
01186 }
01187 ret = dvdinput_read( dvd_file->title_devs[ i ], data,
01188 (int)part1_size, encrypted );
01189 if( ret < 0 ) return ret;
01190
01191
01192
01193
01194 if( i + 1 >= TITLES_MAX || !dvd_file->title_devs[ i + 1 ] )
01195 return ret;
01196
01197
01198 off = dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0 );
01199 if( off < 0 || off != 0 ) {
01200 fprintf( stderr, "libdvdread: Can't seek to block %d\n",
01201 0 );
01202 return off < 0 ? off : 0;
01203 }
01204 ret2 = dvdinput_read( dvd_file->title_devs[ i + 1 ],
01205 data + ( part1_size
01206 * (int64_t)DVD_VIDEO_LB_LEN ),
01207 (int)(block_count - part1_size),
01208 encrypted );
01209 if( ret2 < 0 ) return ret2;
01210 break;
01211 }
01212 } else {
01213 offset -= dvd_file->title_sizes[ i ];
01214 }
01215 }
01216
01217 return ret + ret2;
01218 }
01219
01220
01221 ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
01222 size_t block_count, unsigned char *data )
01223 {
01224 int ret;
01225
01226
01227 if( dvd_file == NULL || offset < 0 || data == NULL )
01228 return -1;
01229
01230
01231 if( dvd_file->dvd->css_title != dvd_file->css_title ) {
01232 dvd_file->dvd->css_title = dvd_file->css_title;
01233 if( dvd_file->dvd->isImageFile ) {
01234 dvdinput_title( dvd_file->dvd->dev, (int)dvd_file->lb_start );
01235 }
01236
01237
01238
01239
01240 }
01241
01242 if( dvd_file->dvd->isImageFile ) {
01243 ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset,
01244 block_count, data, DVDINPUT_READ_DECRYPT );
01245 } else {
01246 ret = DVDReadBlocksPath( dvd_file, (unsigned int)offset,
01247 block_count, data, DVDINPUT_READ_DECRYPT );
01248 }
01249
01250 return (ssize_t)ret;
01251 }
01252
01253 int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset )
01254 {
01255
01256 if( dvd_file == NULL || offset < 0 )
01257 return -1;
01258
01259 if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN ) {
01260 return -1;
01261 }
01262 dvd_file->seek_pos = (uint32_t) offset;
01263 return offset;
01264 }
01265
01266 int DVDFileSeekForce(dvd_file_t *dvd_file, int offset, int force_size)
01267 {
01268
01269 if( dvd_file == NULL || offset <= 0 )
01270 return -1;
01271
01272 if( dvd_file->dvd->isImageFile ) {
01273 if( force_size < 0 )
01274 force_size = (offset - 1) / DVD_VIDEO_LB_LEN + 1;
01275 if( dvd_file->filesize < force_size ) {
01276 dvd_file->filesize = force_size;
01277 fprintf(stderr, "libdvdread: Ignored size of file indicated in UDF.\n");
01278 }
01279 }
01280
01281 if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN )
01282 return -1;
01283
01284 dvd_file->seek_pos = (uint32_t) offset;
01285 return offset;
01286 }
01287
01288 ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
01289 {
01290 unsigned char *secbuf_base, *secbuf;
01291 unsigned int numsec, seek_sector, seek_byte;
01292 int ret;
01293
01294
01295 if( dvd_file == NULL || data == NULL )
01296 return -1;
01297
01298 seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN;
01299 seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN;
01300
01301 numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) +
01302 ( ( ( seek_byte + byte_size ) % DVD_VIDEO_LB_LEN ) ? 1 : 0 );
01303
01304 secbuf_base = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN + 2048 );
01305 secbuf = (unsigned char *)(((uintptr_t)secbuf_base & ~((uintptr_t)2047)) + 2048);
01306 if( !secbuf_base ) {
01307 fprintf( stderr, "libdvdread: Can't allocate memory "
01308 "for file read!\n" );
01309 return 0;
01310 }
01311
01312 if( dvd_file->dvd->isImageFile ) {
01313 ret = DVDReadBlocksUDF( dvd_file, (uint32_t) seek_sector,
01314 (size_t) numsec, secbuf, DVDINPUT_NOFLAGS );
01315 } else {
01316 ret = DVDReadBlocksPath( dvd_file, seek_sector,
01317 (size_t) numsec, secbuf, DVDINPUT_NOFLAGS );
01318 }
01319
01320 if( ret != (int) numsec ) {
01321 free( secbuf_base );
01322 return ret < 0 ? ret : 0;
01323 }
01324
01325 memcpy( data, &(secbuf[ seek_byte ]), byte_size );
01326 free( secbuf_base );
01327
01328 DVDFileSeekForce(dvd_file, dvd_file->seek_pos + byte_size, -1);
01329 return byte_size;
01330 }
01331
01332 ssize_t DVDFileSize( dvd_file_t *dvd_file )
01333 {
01334
01335 if( dvd_file == NULL )
01336 return -1;
01337
01338 return dvd_file->filesize;
01339 }
01340
01341 int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid )
01342 {
01343 struct md5_ctx ctx;
01344 int title;
01345 int nr_of_files = 0;
01346
01347
01348 if( dvd == NULL || discid == NULL )
01349 return 0;
01350
01351
01352
01353 md5_init_ctx( &ctx );
01354 for( title = 0; title < 10; title++ ) {
01355 dvd_file_t *dvd_file = DVDOpenFile( dvd, title, DVD_READ_INFO_FILE );
01356 if( dvd_file != NULL ) {
01357 ssize_t bytes_read;
01358 size_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN;
01359 char *buffer_base = malloc( file_size + 2048 );
01360 char *buffer = (char *)(((uintptr_t)buffer_base & ~((uintptr_t)2047)) + 2048);
01361
01362 if( buffer_base == NULL ) {
01363 DVDCloseFile( dvd_file );
01364 fprintf( stderr, "libdvdread: DVDDiscId, failed to "
01365 "allocate memory for file read!\n" );
01366 return -1;
01367 }
01368
01369 bytes_read = DVDReadBytes( dvd_file, buffer, file_size );
01370 if( bytes_read != file_size ) {
01371 fprintf( stderr, "libdvdread: DVDDiscId read returned %zd bytes"
01372 ", wanted %zd\n", bytes_read, file_size );
01373 DVDCloseFile( dvd_file );
01374 free( buffer_base );
01375 return -1;
01376 }
01377
01378 md5_process_bytes( buffer, file_size, &ctx );
01379
01380 DVDCloseFile( dvd_file );
01381 free( buffer_base );
01382 nr_of_files++;
01383 }
01384 }
01385 md5_finish_ctx( &ctx, discid );
01386 if(!nr_of_files)
01387 return -1;
01388
01389 return 0;
01390 }
01391
01392
01393 int DVDISOVolumeInfo( dvd_reader_t *dvd,
01394 char *volid, unsigned int volid_size,
01395 unsigned char *volsetid, unsigned int volsetid_size )
01396 {
01397 unsigned char *buffer, *buffer_base;
01398 int ret;
01399
01400
01401 if( dvd == NULL )
01402 return 0;
01403
01404 if( dvd->dev == NULL ) {
01405
01406 return -1;
01407 }
01408
01409 buffer_base = malloc( DVD_VIDEO_LB_LEN + 2048 );
01410 buffer = (unsigned char *)(((uintptr_t)buffer_base & ~((uintptr_t)2047)) + 2048);
01411
01412 if( buffer_base == NULL ) {
01413 fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to "
01414 "allocate memory for file read!\n" );
01415 return -1;
01416 }
01417
01418 ret = UDFReadBlocksRaw( dvd, 16, 1, buffer, 0 );
01419 if( ret != 1 ) {
01420 fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to "
01421 "read ISO9660 Primary Volume Descriptor!\n" );
01422 free( buffer_base );
01423 return -1;
01424 }
01425
01426 if( (volid != NULL) && (volid_size > 0) ) {
01427 unsigned int n;
01428 for(n = 0; n < 32; n++) {
01429 if(buffer[40+n] == 0x20) {
01430 break;
01431 }
01432 }
01433
01434 if(volid_size > n+1) {
01435 volid_size = n+1;
01436 }
01437
01438 memcpy(volid, &buffer[40], volid_size-1);
01439 volid[volid_size-1] = '\0';
01440 }
01441
01442 if( (volsetid != NULL) && (volsetid_size > 0) ) {
01443 if(volsetid_size > 128) {
01444 volsetid_size = 128;
01445 }
01446 memcpy(volsetid, &buffer[190], volsetid_size);
01447 }
01448 free( buffer_base );
01449 return 0;
01450 }
01451
01452
01453 int DVDUDFVolumeInfo( dvd_reader_t *dvd,
01454 char *volid, unsigned int volid_size,
01455 unsigned char *volsetid, unsigned int volsetid_size )
01456 {
01457 int ret;
01458
01459 if( dvd == NULL )
01460 return -1;
01461
01462 if( dvd->dev == NULL ) {
01463
01464 return -1;
01465 }
01466
01467 if( (volid != NULL) && (volid_size > 0) ) {
01468 ret = UDFGetVolumeIdentifier(dvd, volid, volid_size);
01469 if(!ret) {
01470 return -1;
01471 }
01472 }
01473 if( (volsetid != NULL) && (volsetid_size > 0) ) {
01474 ret = UDFGetVolumeSetIdentifier(dvd, volsetid, volsetid_size);
01475 if(!ret) {
01476 return -1;
01477 }
01478 }
01479
01480 return 0;
01481 }