I finally got my act together on the whoe dvdnav/dvdread svn write access. So I am asking for a last review before I commit these patches to the repo.
0001 The already sent (and already approved) DVDFileStat addition to the API 0002 Close a dvd file struct in an error path (another finger in the proverbial dike) 0003 Use parens to make mask off of 'is present' bit explicit 0004 Add the *BSD bits from libdvdread 0.9.7 Thanks E -- Erik Hovland [email protected] http://hovland.org/
From caf2b3d7853b82246ef07959f0a55a21b08d46a3 Mon Sep 17 00:00:00 2001 From: Erik Hovland <[email protected]> Date: Sun, 30 Aug 2009 15:26:20 -0700 Subject: [PATCH] Add DVD file stat from version 0.9.7 to libdvdread A new function to do an informational read of the dvd file handle was introduced to libdvdread 0.9.7 (or was it .6). Since libdvdread at mplayerhq imported an older version of dvdread/dvdnav this part of the API was not available. This commit places that function into the library making this library complete in reference to 0.9.7. diff --git a/src/dvd_reader.c b/src/dvd_reader.c index eb0ad8b..05ace3b 100644 --- a/src/dvd_reader.c +++ b/src/dvd_reader.c @@ -111,6 +111,12 @@ struct dvd_file_s { ssize_t filesize; }; +struct dvd_stat_s { + off_t size; /**< Total size of file in bytes */ + int nr_parts; /**< Number of file parts */ + off_t parts_size[9]; /**< Size of each part in bytes */ +}; + int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ); @@ -897,6 +903,187 @@ void DVDCloseFile( dvd_file_t *dvd_file ) } } +static int DVDFileStatVOBUDF(dvd_reader_t *dvd, int title, + int menu, dvd_stat_t *statbuf) +{ + char filename[ MAX_UDF_FILE_NAME_LEN ]; + uint32_t size; + off_t tot_size; + off_t parts_size[9]; + int nr_parts = 0; + int n; + + if( title == 0 ) { + sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); + } else { + sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 ); + } + if(!UDFFindFile( dvd, filename, &size )) { + return -1; + } + tot_size = size; + nr_parts = 1; + parts_size[0] = size; + + if( !menu ) { + int cur; + + for( cur = 2; cur < 10; cur++ ) { + sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur ); + if( !UDFFindFile( dvd, filename, &size ) ) { + break; + } + parts_size[nr_parts] = size; + tot_size += size; + nr_parts++; + } + } + + statbuf->size = tot_size; + statbuf->nr_parts = nr_parts; + for(n = 0; n < nr_parts; n++) { + statbuf->parts_size[n] = parts_size[n]; + } + return 0; +} + + +static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title, + int menu, dvd_stat_t *statbuf ) +{ + char filename[ MAX_UDF_FILE_NAME_LEN ]; + char full_path[ PATH_MAX + 1 ]; + struct stat fileinfo; + off_t tot_size; + off_t parts_size[9]; + int nr_parts = 0; + int n; + + + + if( title == 0 ) { + sprintf( filename, "VIDEO_TS.VOB" ); + } else { + sprintf( filename, "VTS_%02d_%d.VOB", title, menu ? 0 : 1 ); + } + if( !findDVDFile( dvd, filename, full_path ) ) { + return -1; + } + + if( stat( full_path, &fileinfo ) < 0 ) { + fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); + return -1; + } + + + tot_size = fileinfo.st_size; + nr_parts = 1; + parts_size[0] = fileinfo.st_size; + + if( !menu ) { + int cur; + + for( cur = 2; cur < 10; cur++ ) { + + sprintf( filename, "VTS_%02d_%d.VOB", title, cur ); + if( !findDVDFile( dvd, filename, full_path ) ) { + break; + } + + if( stat( full_path, &fileinfo ) < 0 ) { + fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); + break; + } + + parts_size[nr_parts] = fileinfo.st_size; + tot_size += parts_size[nr_parts]; + nr_parts++; + } + } + + statbuf->size = tot_size; + statbuf->nr_parts = nr_parts; + for(n = 0; n < nr_parts; n++) { + statbuf->parts_size[n] = parts_size[n]; + } + return 0; +} + + +int DVDFileStat(dvd_reader_t *dvd, int titlenum, + dvd_read_domain_t domain, dvd_stat_t *statbuf) +{ + char filename[ MAX_UDF_FILE_NAME_LEN ]; + char full_path[ PATH_MAX + 1 ]; + struct stat fileinfo; + uint32_t size; + + /* Check arguments. */ + if( dvd == NULL || titlenum < 0 ) { + errno = EINVAL; + return -1; + } + + switch( domain ) { + case DVD_READ_INFO_FILE: + if( titlenum == 0 ) { + sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" ); + } else { + sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum ); + } + break; + case DVD_READ_INFO_BACKUP_FILE: + if( titlenum == 0 ) { + sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" ); + } else { + sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum ); + } + break; + case DVD_READ_MENU_VOBS: + if( dvd->isImageFile ) { + return DVDFileStatVOBUDF( dvd, titlenum, 1, statbuf ); + } else { + return DVDFileStatVOBPath( dvd, titlenum, 1, statbuf ); + } + break; + case DVD_READ_TITLE_VOBS: + if( titlenum == 0 ) { + return -1; + } + if( dvd->isImageFile ) { + return DVDFileStatVOBUDF( dvd, titlenum, 0, statbuf ); + } else { + return DVDFileStatVOBPath( dvd, titlenum, 0, statbuf ); + } + break; + default: + fprintf( stderr, "libdvdread: Invalid domain for file stat.\n" ); + errno = EINVAL; + return -1; + } + + if( dvd->isImageFile ) { + if( UDFFindFile( dvd, filename, &size ) ) { + statbuf->size = size; + statbuf->nr_parts = 1; + statbuf->parts_size[0] = size; + return 0; + } + } else { + if( findDVDFile( dvd, filename, full_path ) ) { + if( stat( full_path, &fileinfo ) < 0 ) { + fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); + } else { + statbuf->size = fileinfo.st_size; + statbuf->nr_parts = 1; + statbuf->parts_size[0] = statbuf->size; + return 0; + } + } + } + return -1; +} + /* Internal, but used from dvd_udf.c */ int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, diff --git a/src/dvdread/dvd_reader.h b/src/dvdread/dvd_reader.h index 8a2a58d..f3e599f 100644 --- a/src/dvdread/dvd_reader.h +++ b/src/dvdread/dvd_reader.h @@ -70,6 +70,11 @@ typedef struct dvd_reader_s dvd_reader_t; typedef struct dvd_file_s dvd_file_t; /** + * Opaque type that is used to provide statistics on a handle. + */ +typedef struct dvd_stat_s dvd_stat_t; + +/** * Opens a block device of a DVD-ROM file, or an image file, or a directory * name for a mounted DVD or HD copy of a DVD. * @@ -117,6 +122,33 @@ typedef enum { } dvd_read_domain_t; /** + * Stats a file on the DVD given the title number and domain. + * The information about the file is stored in a dvd_stat_t + * which contains information about the size of the file and + * the number of parts in case of a multipart file and the respective + * sizes of the parts. + * A multipart file is for instance VTS_02_1.VOB, VTS_02_2.VOB, VTS_02_3.VOB + * The size of VTS_02_1.VOB will be stored in stat->parts_size[0], + * VTS_02_2.VOB in stat->parts_size[1], ... + * The total size (sum of all parts) is stored in stat->size and + * stat->nr_parts will hold the number of parts. + * Only DVD_READ_TITLE_VOBS (VTS_??_[1-9].VOB) can be multipart files. + * + * This function is only of use if you want to get the size of each file + * in the filesystem. These sizes are not needed to use any other + * functions in libdvdread. + * + * @param dvd A dvd read handle. + * @param titlenum Which Video Title Set should be used, VIDEO_TS is 0. + * @param domain Which domain. + * @param stat Pointer to where the result is stored. + * @return If successful 0, otherwise -1. + * + * int DVDFileStat(dvd, titlenum, domain, stat); + */ +int DVDFileStat(dvd_reader_t *, int, dvd_read_domain_t, dvd_stat_t *); + +/** * Opens a file on the DVD given the title number and domain. * * If the title number is 0, the video manager information is opened -- 1.6.0.4
From b210c217f3d2e5b1ddcef1a7b62efd2f96bf51de Mon Sep 17 00:00:00 2001 From: Erik Hovland <[email protected]> Date: Sun, 30 Aug 2009 16:52:52 -0700 Subject: [PATCH] Close a dev struct leak in the error path When things go bad the dev struct is not always deallocated. This commit makes sure that is always deallocated. diff --git a/src/dvd_reader.c b/src/dvd_reader.c index 05ace3b..ece611e 100644 --- a/src/dvd_reader.c +++ b/src/dvd_reader.c @@ -699,6 +699,7 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename ) if( stat( full_path, &fileinfo ) < 0 ) { fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); free( dvd_file ); + dvdinput_close( dev ); return NULL; } dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; -- 1.6.0.4
From 0d06d35eff9f9784504eb701303b14dd3159e6d7 Mon Sep 17 00:00:00 2001 From: Erik Hovland <[email protected]> Date: Sun, 30 Aug 2009 16:53:54 -0700 Subject: [PATCH] Use parens to make the 'is present' mask explicit W/o parens the check for the 'is present' mask will not work right because the ! operator will evaluate first. But by wrapping the & operation in parens, we make it explicit that this goes first. And so the is present flag will be properly evaluated in the conditional diff --git a/src/ifo_read.c b/src/ifo_read.c index 82e915d..682589a 100644 --- a/src/ifo_read.c +++ b/src/ifo_read.c @@ -844,10 +844,10 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { /* verify time (look at print_time) */ for(i = 0; i < 8; i++) - if(!pgc->audio_control[i] & 0x8000) /* The 'is present' bit */ + if(!(pgc->audio_control[i] & 0x8000)) /* The 'is present' bit */ CHECK_ZERO(pgc->audio_control[i]); for(i = 0; i < 32; i++) - if(!pgc->subp_control[i] & 0x80000000) /* The 'is present' bit */ + if(!(pgc->subp_control[i] & 0x80000000)) /* The 'is present' bit */ CHECK_ZERO(pgc->subp_control[i]); /* Check that time is 0:0:0:0 also if nr_of_programs == 0 */ -- 1.6.0.4
From 9eb83ae3dc5f1cd58a7dd4408815fe8d6e662e04 Mon Sep 17 00:00:00 2001 From: Erik Hovland <[email protected]> Date: Sun, 30 Aug 2009 17:03:54 -0700 Subject: [PATCH] Add *BSD porting bits from 0.9.7 Both version 0.9.6 and 0.9.7 had some porting code put in for the *BSDs. This code is untested by me, but I bet the OpenSolaris and *BSD folk would love to have it. diff --git a/src/dvd_reader.c b/src/dvd_reader.c index ece611e..ba5a165 100644 --- a/src/dvd_reader.c +++ b/src/dvd_reader.c @@ -309,12 +309,18 @@ static char *sun_block2char( const char *path ) #if defined(SYS_BSD) /* FreeBSD /dev/(r)(a)cd0c (a is for atapi), recommended to _not_ use r + update: FreeBSD and DragonFly no longer uses the prefix so don't add it. OpenBSD /dev/rcd0c, it needs to be the raw device NetBSD /dev/rcd0[d|c|..] d for x86, c (for non x86), perhaps others Darwin /dev/rdisk0, it needs to be the raw device - BSD/OS /dev/sr0c (if not mounted) or /dev/rsr0c ('c' any letter will do) */ + BSD/OS /dev/sr0c (if not mounted) or /dev/rsr0c ('c' any letter will do) + returns a string allocated with strdup. It should be freed when no longer + used. */ static char *bsd_block2char( const char *path ) { +#if defined(__FreeBSD__) || defined(__DragonFly__) + return (char *) strdup( path ); +#else char *new_path; /* If it doesn't start with "/dev/" or does start with "/dev/r" exit */ @@ -327,6 +333,7 @@ static char *bsd_block2char( const char *path ) strcat( new_path, path + strlen( "/dev/" ) ); return new_path; +#endif /* __FreeBSD__ || __DragonFly__ */ } #endif @@ -389,17 +396,18 @@ dvd_reader_t *DVDOpen( const char *ppath ) /** * Block devices and regular files are assumed to be DVD-Video images. */ + dvd_reader_t *dvd = NULL; #if defined(__sun) - ret_val = DVDOpenImageFile( sun_block2char( path ), have_css ); + dev_name = sun_block2char( path ); #elif defined(SYS_BSD) - ret_val = DVDOpenImageFile( bsd_block2char( path ), have_css ); + dev_name = bsd_block2char( path ); #else - ret_val = DVDOpenImageFile( path, have_css ); + dev_name = strdup( path ); #endif - + dvd = DVDOpenImageFile( dev_name, have_css ); + free( dev_name ); free(path); - return ret_val; - + return dvd; } else if( S_ISDIR( fileinfo.st_mode ) ) { dvd_reader_t *auth_drive = 0; #if defined(SYS_BSD) -- 1.6.0.4
_______________________________________________ DVDnav-discuss mailing list [email protected] https://lists.mplayerhq.hu/mailman/listinfo/dvdnav-discuss
