diff options
Diffstat (limited to 'dvdread')
-rw-r--r-- | dvdread/Makefile | 1 | ||||
-rw-r--r-- | dvdread/bswap.h | 14 | ||||
-rw-r--r-- | dvdread/dvd_input.c | 104 | ||||
-rw-r--r-- | dvdread/dvd_input.h | 7 | ||||
-rw-r--r-- | dvdread/dvd_reader.c | 436 | ||||
-rw-r--r-- | dvdread/dvd_reader.h | 44 | ||||
-rw-r--r-- | dvdread/dvd_udf.c | 282 | ||||
-rw-r--r-- | dvdread/dvd_udf.h | 6 | ||||
-rw-r--r-- | dvdread/dvdread_internal.h | 4 | ||||
-rw-r--r-- | dvdread/ifo_print.c | 91 | ||||
-rw-r--r-- | dvdread/ifo_read.c | 246 | ||||
-rw-r--r-- | dvdread/ifo_types.h | 62 | ||||
-rw-r--r-- | dvdread/nav_print.c | 8 | ||||
-rw-r--r-- | dvdread/nav_read.c | 4 | ||||
-rw-r--r-- | dvdread/nav_types.h | 3 |
15 files changed, 1080 insertions, 232 deletions
diff --git a/dvdread/Makefile b/dvdread/Makefile index 77f2e1c2ee..c79375e755 100644 --- a/dvdread/Makefile +++ b/dvdread/Makefile @@ -10,6 +10,7 @@ SRCS_COMMON = dvd_input.c \ nav_print.c \ nav_read.c \ md5.c \ + cmd_print.c \ CFLAGS = -D__USE_UNIX98 -D_GNU_SOURCE diff --git a/dvdread/bswap.h b/dvdread/bswap.h index c612025b31..a5296b82cd 100644 --- a/dvdread/bswap.h +++ b/dvdread/bswap.h @@ -61,7 +61,19 @@ #include <sys/endian.h> #define B2N_16(x) x = be16toh(x) #define B2N_32(x) x = be32toh(x) +#if __FreeBSD_version >= 500000 #define B2N_64(x) x = be64toh(x) +#else +#define B2N_64(x) \ + x = ((((x) & 0xff00000000000000) >> 56) | \ + (((x) & 0x00ff000000000000) >> 40) | \ + (((x) & 0x0000ff0000000000) >> 24) | \ + (((x) & 0x000000ff00000000) >> 8) | \ + (((x) & 0x00000000ff000000) << 8) | \ + (((x) & 0x0000000000ff0000) << 24) | \ + (((x) & 0x000000000000ff00) << 40) | \ + (((x) & 0x00000000000000ff) << 56)) +#endif /* _FreeBSD_version >= 500000 */ #elif defined(__DragonFly__) #include <sys/endian.h> @@ -113,7 +125,7 @@ inline static unsigned long long int bswap_64(unsigned long long int x) * functionality! */ -#elif defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__) || defined(__CYGWIN__) +#elif defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__) || defined(WIN32) || defined(__BEOS__) || defined(__INTERIX) || defined(__CYGWIN__) #define B2N_16(x) \ x = ((((x) & 0xff00) >> 8) | \ (((x) & 0x00ff) << 8)) diff --git a/dvdread/dvd_input.c b/dvdread/dvd_input.c index 341c9882d4..dcd5307862 100644 --- a/dvdread/dvd_input.c +++ b/dvdread/dvd_input.c @@ -25,18 +25,26 @@ #include <stdio.h> #include <stdlib.h> +#define __USE_GNU /* to get O_DIRECT in linux */ #include <fcntl.h> #include <unistd.h> #include "dvd_reader.h" #include "dvd_input.h" +#include "dvdread_internal.h" + /* The function pointers that is the exported interface of this file. */ dvd_input_t (*dvdinput_open) (const char *); int (*dvdinput_close) (dvd_input_t); int (*dvdinput_seek) (dvd_input_t, int); int (*dvdinput_title) (dvd_input_t, int); +/** + * pointer must be aligned to 2048 bytes + * if reading from a raw/O_DIRECT file + */ int (*dvdinput_read) (dvd_input_t, void *, int, int); + char * (*dvdinput_error) (dvd_input_t); #ifdef HAVE_DVDCSS_DVDCSS_H @@ -80,16 +88,15 @@ static dvd_input_t css_open(const char *target) /* Allocate the handle structure */ dev = (dvd_input_t) malloc(sizeof(struct dvd_input_s)); if(dev == NULL) { - fprintf(stderr, "libdvdread: Could not allocate memory.\n"); + /* malloc has set errno to ENOMEM */ return NULL; } /* Really open it with libdvdcss */ dev->dvdcss = DVDcss_open(target); if(dev->dvdcss == 0) { - fprintf(stderr, "libdvdread: Could not open %s with libdvdcss.\n", target); free(dev); - return NULL; + dev = NULL; } return dev; @@ -145,10 +152,14 @@ static int css_close(dvd_input_t dev) return 0; } - - - - +/* Need to use O_BINARY for WIN32 */ +#ifndef O_BINARY +#ifdef _O_BINARY +#define O_BINARY _O_BINARY +#else +#define O_BINARY 0 +#endif +#endif /** * initialize and open a DVD device or file. @@ -156,18 +167,26 @@ static int css_close(dvd_input_t dev) static dvd_input_t file_open(const char *target) { dvd_input_t dev; + char *use_odirect; + int oflags; + oflags = O_RDONLY | O_BINARY; + use_odirect = getenv("DVDREAD_USE_DIRECT"); + if(use_odirect) { +#ifndef O_DIRECT +#define O_DIRECT 0 +#endif + oflags |= O_DIRECT; + } /* Allocate the library structure */ dev = (dvd_input_t) malloc(sizeof(struct dvd_input_s)); if(dev == NULL) { - fprintf(stderr, "libdvdread: Could not allocate memory.\n"); return NULL; } /* Open the device */ - dev->fd = open(target, O_RDONLY); + dev->fd = open(target, oflags); if(dev->fd < 0) { - perror("libdvdread: Could not open input"); free(dev); return NULL; } @@ -189,9 +208,9 @@ static char *file_error(dvd_input_t dev) */ static int file_seek(dvd_input_t dev, int blocks) { - off_t pos; + off_t pos = (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN; - pos = lseek(dev->fd, (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN, SEEK_SET); + pos = lseek(dev->fd, pos, SEEK_SET); if(pos < 0) { return pos; } @@ -214,12 +233,13 @@ static int file_read(dvd_input_t dev, void *buffer, int blocks, int flags) { size_t len; ssize_t ret; + unsigned char *buf = buffer; len = (size_t)blocks * DVD_VIDEO_LB_LEN; while(len > 0) { - ret = read(dev->fd, buffer, len); + ret = read(dev->fd, buf, len); if(ret < 0) { /* One of the reads failed, too bad. We won't even bother @@ -238,6 +258,7 @@ static int file_read(dvd_input_t dev, void *buffer, int blocks, int flags) return (int) (bytes / DVD_VIDEO_LB_LEN); } + buf+=ret; len -= ret; } @@ -262,13 +283,49 @@ static int file_close(dvd_input_t dev) } +static void *dvdcss_library = NULL; +static int dvdcss_library_init = 0; + +/** + * Free any objects allocated by dvdinput_setup. + * Should only be called when libdvdread is not to be used any more. + * Closes dlopened libraries. + */ +void dvdinput_free(void) +{ +#ifdef HAVE_DVDCSS_DVDCSS_H + /* linked statically, nothing to free */ + return; +#else + if(dvdcss_library) { + dlclose(dvdcss_library); + dvdcss_library = NULL; + } + dvdcss_library_init = 0; + return; +#endif +} + + /** * Setup read functions with either libdvdcss or minimal DVD access. */ int dvdinput_setup(void) { - void *dvdcss_library = NULL; char **dvdcss_version = NULL; + int verbose; + + /* dlopening libdvdcss */ + if(dvdcss_library_init) { + /* libdvdcss is already dlopened, function ptrs set */ + if(dvdcss_library) { + return 1; /* css available */ + } else { + return 0; /* css not available */ + } + } + + verbose = get_verbose(); #ifdef HAVE_DVDCSS_DVDCSS_H /* linking to libdvdcss */ @@ -277,7 +334,7 @@ int dvdinput_setup(void) dvdcss_version = &dvdcss_interface_2; #else - /* dlopening libdvdcss */ + dvdcss_library = dlopen("libdvdcss.so.2", RTLD_LAZY); if(dvdcss_library != NULL) { @@ -302,33 +359,39 @@ int dvdinput_setup(void) dvdcss_version = (char **)dlsym(dvdcss_library, U_S "dvdcss_interface_2"); if(dlsym(dvdcss_library, U_S "dvdcss_crack")) { + if(verbose >= 0) { fprintf(stderr, "libdvdread: Old (pre-0.0.2) version of libdvdcss found.\n" "libdvdread: You should get the latest version from " "http://www.videolan.org/\n" ); + } dlclose(dvdcss_library); dvdcss_library = NULL; } else if(!DVDcss_open || !DVDcss_close || !DVDcss_title || !DVDcss_seek || !DVDcss_read || !DVDcss_error || !dvdcss_version) { + if(verbose >= 0) { fprintf(stderr, "libdvdread: Missing symbols in libdvdcss.so.2, " "this shouldn't happen !\n"); + } dlclose(dvdcss_library); + dvdcss_library = NULL; } } #endif /* HAVE_DVDCSS_DVDCSS_H */ - if(dvdcss_library != NULL) { + dvdcss_library_init = 1; + + if(dvdcss_library) { /* char *psz_method = getenv( "DVDCSS_METHOD" ); char *psz_verbose = getenv( "DVDCSS_VERBOSE" ); fprintf(stderr, "DVDCSS_METHOD %s\n", psz_method); fprintf(stderr, "DVDCSS_VERBOSE %s\n", psz_verbose); */ - /* + if(verbose >= 1) { fprintf(stderr, "libdvdread: Using libdvdcss version %s for DVD access\n", *dvdcss_version); - */ - + } /* libdvdcss wrapper functions */ dvdinput_open = css_open; dvdinput_close = css_close; @@ -339,8 +402,9 @@ int dvdinput_setup(void) return 1; } else { + if(verbose >= 1) { fprintf(stderr, "libdvdread: Encrypted DVD support unavailable.\n"); - + } /* libdvdcss replacement functions */ dvdinput_open = file_open; dvdinput_close = file_close; diff --git a/dvdread/dvd_input.h b/dvdread/dvd_input.h index e9e84917ea..0f05c97952 100644 --- a/dvdread/dvd_input.h +++ b/dvdread/dvd_input.h @@ -40,6 +40,13 @@ extern int (*dvdinput_read) (dvd_input_t, void *, int, int); extern char * (*dvdinput_error) (dvd_input_t); /** + * Free any objects allocated by dvdinput_setup. + * Should only be called when libdvdread is not to be used any more. + * Closes dlopened libraries. + */ +void dvdinput_free(void); + +/** * Setup function accessed by dvd_reader.c. Returns 1 if there is CSS support. */ int dvdinput_setup(void); diff --git a/dvdread/dvd_reader.c b/dvdread/dvd_reader.c index d944696c15..92d202b8d9 100644 --- a/dvdread/dvd_reader.c +++ b/dvdread/dvd_reader.c @@ -60,11 +60,13 @@ static void gettimeofday(struct timeval* t,void* timezone){ } #endif -#include "dvd_udf.h" -#include "dvd_input.h" #include "dvd_reader.h" +#include "dvd_input.h" +#include "dvd_udf.h" #include "md5.h" +#include "dvdread_internal.h" + #define DEFAULT_UDF_CACHE_LEVEL 0 struct dvd_reader_s { @@ -85,6 +87,12 @@ struct dvd_reader_s { /* Filesystem cache */ int udfcache_level; /* 0 - turned off, 1 - on */ void *udfcache; + + /* block aligned malloc */ + void *align; + + /* error message verbosity level */ + int verbose; }; struct dvd_file_s { @@ -106,6 +114,42 @@ struct dvd_file_s { ssize_t filesize; }; + +#define DVDREAD_VERBOSE_DEFAULT 0 + +int get_verbose(void) +{ + char *dvdread_verbose; + int verbose; + + dvdread_verbose = getenv("DVDREAD_VERBOSE"); + if(dvdread_verbose) { + verbose = (int)strtol(dvdread_verbose, NULL, 0); + } else { + verbose = DVDREAD_VERBOSE_DEFAULT; + } + return verbose; +} + +int dvdread_verbose(dvd_reader_t *dvd) +{ + return dvd->verbose; +} + +dvd_reader_t *device_of_file(dvd_file_t *file) +{ + return file->dvd; +} + +/** + * Returns the compiled version. (DVDREAD_VERSION as an int) + */ +int DVDVersion(void) +{ + return DVDREAD_VERSION; +} + + /** * Set the level of caching on udf * level = 0 (no caching) @@ -140,6 +184,31 @@ void SetUDFCacheHandle(dvd_reader_t *device, void *cache) dev->udfcache = cache; } +void *GetAlignHandle(dvd_reader_t *device) +{ + struct dvd_reader_s *dev = (struct dvd_reader_s *)device; + + return dev->align; +} + +void SetAlignHandle(dvd_reader_t *device, void *align) +{ + struct dvd_reader_s *dev = (struct dvd_reader_s *)device; + + dev->align = align; +} + +#ifdef WIN32 /* replacement gettimeofday implementation */ +#include <sys/timeb.h> +static int gettimeofday( struct timeval *tv, void *tz ) +{ + struct timeb t; + ftime( &t ); + tv->tv_sec = t.time; + tv->tv_usec = t.millitm * 1000; + return 0; +} +#endif /* Loop over all titles and call dvdcss_title to crack the keys. */ @@ -155,11 +224,12 @@ static int initAllCSSKeys( dvd_reader_t *dvd ) if(nokeys_str != NULL) return 0; + if(dvd->verbose >= 1) { fprintf( stderr, "\n" ); fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" ); fprintf( stderr, "libdvdread: This can take a _long_ time, " "please be patient\n\n" ); - + } gettimeofday(&all_s, NULL); for( title = 0; title < 100; title++ ) { @@ -172,15 +242,21 @@ static int initAllCSSKeys( dvd_reader_t *dvd ) start = UDFFindFile( dvd, filename, &len ); if( start != 0 && len != 0 ) { /* Perform CSS key cracking for this title. */ + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", filename, start ); + } if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { + if(dvd->verbose >= 0) { fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)\n", filename, start); } + } gettimeofday( &t_e, NULL ); + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Elapsed time %ld\n", (long int) t_e.tv_sec - t_s.tv_sec ); } + } if( title == 0 ) continue; @@ -190,22 +266,31 @@ static int initAllCSSKeys( dvd_reader_t *dvd ) if( start == 0 || len == 0 ) break; /* Perform CSS key cracking for this title. */ + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", filename, start ); + } if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { + if(dvd->verbose >= 0) { fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)!!\n", filename, start); } + } gettimeofday( &t_e, NULL ); + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Elapsed time %ld\n", (long int) t_e.tv_sec - t_s.tv_sec ); } + } title--; + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Found %d VTS's\n", title ); + } gettimeofday(&all_e, NULL); + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Elapsed time %ld\n", (long int) all_e.tv_sec - all_s.tv_sec ); - + } return 0; } @@ -213,27 +298,43 @@ static int initAllCSSKeys( dvd_reader_t *dvd ) /** * Open a DVD image or block device file. + * Checks if the root directory in the udf image file can be found. + * If not it assumes this isn't a valid udf image and returns NULL */ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ) { dvd_reader_t *dvd; dvd_input_t dev; + int verbose; + + verbose = get_verbose(); dev = dvdinput_open( location ); if( !dev ) { - fprintf( stderr, "libdvdread: Can't open %s for reading\n", location ); - return 0; + if(verbose >= 1) { + fprintf( stderr, "libdvdread: Can't open '%s' for reading: %s\n", + location, strerror(errno)); + } + return NULL; } dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); - if( !dvd ) return 0; + if( !dvd ) { + int tmp_errno = errno; + dvdinput_close(dev); + errno = tmp_errno; + return NULL; + } + dvd->verbose = verbose; dvd->isImageFile = 1; dvd->dev = dev; - dvd->path_root = 0; + dvd->path_root = NULL; dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; dvd->udfcache = NULL; + dvd->align = NULL; + if( have_css ) { /* Only if DVDCSS_METHOD = title, a bit if it's disc or if * DVDCSS_METHOD = key but region missmatch. Unfortunaly we @@ -243,6 +344,20 @@ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ) } dvd->css_title = 0; + /* sanity check, is it a valid UDF image, can we find the root dir */ + if(!UDFFindFile(dvd, "/", NULL)) { + dvdinput_close(dvd->dev); + if(dvd->udfcache) { + FreeUDFCache(dvd, dvd->udfcache); + } + if(dvd->align) { + if(dvd->verbose >= 0) { + fprintf(stderr, "libdvdread: DVDOpenImageFile(): Memory leak in align functions 1\n"); + } + } + free(dvd); + return NULL; + } return dvd; } @@ -251,14 +366,22 @@ static dvd_reader_t *DVDOpenPath( const char *path_root ) dvd_reader_t *dvd; dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); - if( !dvd ) return 0; + if( !dvd ) { + return NULL; + } + dvd->verbose = get_verbose(); dvd->isImageFile = 0; dvd->dev = 0; dvd->path_root = strdup( path_root ); - + if(!dvd->path_root) { + free(dvd); + return 0; + } dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; dvd->udfcache = NULL; + dvd->align = NULL; + dvd->css_state = 0; /* Only used in the UDF path */ dvd->css_title = 0; /* Only matters in the UDF path */ @@ -320,10 +443,16 @@ dvd_reader_t *DVDOpen( const char *path ) { struct stat fileinfo; int ret, have_css; - char *dev_name = 0; + char *dev_name = NULL; + int internal_errno = 0; + int verbose; - if( path == NULL ) - return 0; + if( path == NULL ) { + errno = EINVAL; + return NULL; + } + + verbose = get_verbose(); #ifdef WIN32 /* Stat doesn't work on devices under mingwin/cygwin. */ @@ -337,10 +466,14 @@ dvd_reader_t *DVDOpen( const char *path ) { ret = stat( path, &fileinfo ); if( ret < 0 ) { + int tmp_errno = errno; /* If we can't stat the file, give up */ - fprintf( stderr, "libdvdread: Can't stat %s\n", path ); - perror(""); - return 0; + if(verbose >= 1) { + fprintf( stderr, "libdvdread: Can't stat '%s': %s\n", + path, strerror(errno)); + } + errno = tmp_errno; + return NULL; } } @@ -375,24 +508,38 @@ dvd_reader_t *DVDOpen( const char *path ) /* XXX: We should scream real loud here. */ if( !(path_copy = strdup( path ) ) ) return 0; +#ifndef WIN32 /* don't have fchdir, and getcwd( NULL, ... ) is strange */ /* Resolve any symlinks and get the absolut dir name. */ { char *new_path; - int cdir = open( ".", O_RDONLY ); + char *current_path; - if( cdir >= 0 ) { + current_path = malloc(PATH_MAX); + if(current_path) { + if(!getcwd(current_path, PATH_MAX)) { + free(current_path); + current_path = NULL; + } + } + if(current_path) { chdir( path_copy ); - new_path = getcwd( NULL, PATH_MAX ); -#ifndef __MINGW32__ - fchdir( cdir ); -#endif - close( cdir ); + new_path = malloc(PATH_MAX); + if(new_path) { + if(!getcwd(new_path, PATH_MAX )) { + free(new_path); + new_path = NULL; + } + } + + chdir(current_path); + free(current_path); if( new_path ) { free( path_copy ); path_copy = new_path; } } } +#endif /** * If we're being asked to open a directory, check if that directory @@ -400,26 +547,37 @@ dvd_reader_t *DVDOpen( const char *path ) */ if( strlen( path_copy ) > 1 ) { - if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) + if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) { path_copy[ strlen( path_copy ) - 1 ] = '\0'; } + } - if( strlen( path_copy ) > 9 ) { + if( strlen( path_copy ) >= 9 ) { if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]), "/video_ts" ) ) { path_copy[ strlen( path_copy ) - 9 ] = '\0'; + if(path_copy[0] == '\0') { + path_copy[0] = '/'; + path_copy[1] = '\0'; + } } } #if defined(SYS_BSD) if( ( fe = getfsfile( path_copy ) ) ) { dev_name = bsd_block2char( fe->fs_spec ); + if(verbose >= 1) { fprintf( stderr, "libdvdread: Attempting to use device %s" - " mounted on %s for CSS authentication\n", + " mounted on %s%s\n", dev_name, - fe->fs_file ); + fe->fs_file, + have_css ? " for CSS authentication" : ""); + } auth_drive = DVDOpenImageFile( dev_name, have_css ); + if(!auth_drive) { + internal_errno = errno; + } } #elif defined(__sun) mntfile = fopen( MNTTAB, "r" ); @@ -430,12 +588,18 @@ dvd_reader_t *DVDOpen( const char *path ) while( ( res = getmntent( mntfile, &mp ) ) != -1 ) { if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) { dev_name = sun_block2char( mp.mnt_special ); + if(verbose >= 1) { fprintf( stderr, "libdvdread: Attempting to use device %s" - " mounted on %s for CSS authentication\n", + " mounted on %s%s\n", dev_name, - mp.mnt_mountp ); + mp.mnt_mountp, + have_css ? " for CSS authentication" : ""); + } auth_drive = DVDOpenImageFile( dev_name, have_css ); + if(!auth_drive) { + internal_errno = errno; + } break; } } @@ -448,12 +612,18 @@ dvd_reader_t *DVDOpen( const char *path ) while( ( me = getmntent( mntfile ) ) ) { if( !strcmp( me->mnt_dir, path_copy ) ) { + if(verbose >= 1) { fprintf( stderr, "libdvdread: Attempting to use device %s" - " mounted on %s for CSS authentication\n", + " mounted on %s%s\n", me->mnt_fsname, - me->mnt_dir ); + me->mnt_dir, + have_css ? " for CSS authentication" : ""); + } auth_drive = DVDOpenImageFile( me->mnt_fsname, have_css ); + if(!auth_drive) { + internal_errno = errno; + } dev_name = strdup(me->mnt_fsname); break; } @@ -465,10 +635,16 @@ dvd_reader_t *DVDOpen( const char *path ) auth_drive = DVDOpenImageFile( path, have_css ); #endif if( !dev_name ) { + if(verbose >= 1) { fprintf( stderr, "libdvdread: Couldn't find device name.\n" ); + } } else if( !auth_drive ) { - fprintf( stderr, "libdvdread: Device %s inaccessible, " - "CSS authentication not available.\n", dev_name ); + if(verbose >= 1) { + fprintf( stderr, "libdvdread: Device %s inaccessible%s: %s\n", + dev_name, + have_css ? ", CSS authentication not available" : "", + strerror(internal_errno)); + } } free( dev_name ); @@ -477,8 +653,9 @@ dvd_reader_t *DVDOpen( const char *path ) /** * If we've opened a drive, just use that. */ - if( auth_drive ) return auth_drive; - + if( auth_drive ) { + return auth_drive; + } /** * Otherwise, we now try to open the directory tree instead. */ @@ -486,7 +663,9 @@ dvd_reader_t *DVDOpen( const char *path ) } /* If it's none of the above, screw it. */ + if(verbose >= 1) { fprintf( stderr, "libdvdread: Could not open %s\n", path ); + } return 0; } @@ -495,11 +674,27 @@ void DVDClose( dvd_reader_t *dvd ) if( dvd ) { if( dvd->dev ) dvdinput_close( dvd->dev ); if( dvd->path_root ) free( dvd->path_root ); - if( dvd->udfcache ) FreeUDFCache( dvd->udfcache ); + if( dvd->udfcache ) FreeUDFCache( dvd, dvd->udfcache ); + if(dvd->align) { + if(dvd->verbose >= 0) { + fprintf(stderr, "libdvdread: DVDClose(): Memory leak in align functions\n"); + } + } + dvdinput_free(); free( dvd ); } } +void DVDInit(void) +{ + dvdinput_setup(); +} + +void DVDFinish(void) +{ + dvdinput_free(); +} + /** * Open an unencrypted file on a DVD image file. */ @@ -542,10 +737,11 @@ static int findDirFile( const char *path, const char *file, char *filename ) sprintf( filename, "%s%s%s", path, ( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ), ent->d_name ); + closedir(dir); return 0; } } - + closedir(dir); return -1; } @@ -606,7 +802,9 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename ) dvd_file->filesize = 0; if( stat( full_path, &fileinfo ) < 0 ) { + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); + } free( dvd_file ); return 0; } @@ -704,7 +902,9 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu ) } if( stat( full_path, &fileinfo ) < 0 ) { + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); + } free( dvd_file ); return 0; } @@ -722,7 +922,9 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu ) } if( stat( full_path, &fileinfo ) < 0 ) { + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); + } break; } @@ -746,8 +948,10 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum, char filename[ MAX_UDF_FILE_NAME_LEN ]; /* Check arguments. */ - if( dvd == NULL || titlenum < 0 ) + if( dvd == NULL || titlenum < 0 ) { + errno = EINVAL; return NULL; + } switch( domain ) { case DVD_READ_INFO_FILE: @@ -780,7 +984,10 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum, } break; default: + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Invalid domain for file open.\n" ); + } + errno = EINVAL; return NULL; } @@ -811,7 +1018,20 @@ void DVDCloseFile( dvd_file_t *dvd_file ) } } -/* Internal, but used from dvd_udf.c */ +/** + * Internal, but used from dvd_udf.c + * + * @param device A read handle. + * @param lb_number Logical block number to start read from. + * @param block_count Number of logical blocks to read. + * @param data Pointer to buffer where read data should be stored. + * This buffer must be large enough to hold lb_number*2048 bytes. + * The pointer must be aligned to the logical block size when + * reading from a raw/O_DIRECT device. + * @param encrypted 0 if no decryption shall be performed, + * 1 if decryption shall be performed + * @param return Returns number of blocks read on success, negative on error + */ int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ) @@ -819,13 +1039,19 @@ int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, int ret; if( !device->dev ) { + if(device->verbose >= 1) { fprintf( stderr, "libdvdread: Fatal error in block read.\n" ); + } return 0; } ret = dvdinput_seek( device->dev, (int) lb_number ); if( ret != (int) lb_number ) { - fprintf( stderr, "libdvdread: Can't seek to block %u\n", lb_number ); + if(device->verbose >= 1) { + fprintf( stderr, + "libdvdread: UDFReadBlocksRaw: Can't seek to block %u\n", + lb_number ); + } return 0; } @@ -833,12 +1059,20 @@ int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, (int) block_count, encrypted ); } -/* This is using a single input and starting from 'dvd_file->lb_start' offset. +/** + * This is using a single input and starting from 'dvd_file->lb_start' offset. * * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset' * into the buffer located at 'data' and if 'encrypted' is set * descramble the data if it's encrypted. Returning either an - * negative error or the number of blocks read. */ + * negative error or the number of blocks read. + * + * @param data Pointer to buffer where read data should be placed. + * This buffer must be large enough to hold block_count*2048 bytes. + * The pointer must be aligned to 2048 bytes when reading from + * a raw/O_DIRECT device. + * @return Returns the number of blocks read on success or a negative error. + */ static int DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset, size_t block_count, unsigned char *data, int encrypted ) @@ -847,12 +1081,19 @@ static int DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset, block_count, data, encrypted ); } -/* This is using possibly several inputs and starting from an offset of '0'. - * +/** + * This is using possibly several inputs and starting from an offset of '0'. + * data must be aligned to logical block size (2048 bytes) of the device + * for raw/O_DIRECT devices to work * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset' * into the buffer located at 'data' and if 'encrypted' is set * descramble the data if it's encrypted. Returning either an - * negative error or the number of blocks read. */ + * negative error or the number of blocks read. + * + * @param dvd_file A file read handle. + * @param offset Block offset from start of file. + * @return Returns number of blocks read on success, negative on error. + */ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset, size_t block_count, unsigned char *data, int encrypted ) @@ -869,8 +1110,10 @@ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset, if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) { off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); if( off < 0 || off != (int)offset ) { - fprintf( stderr, "libdvdread: Can't seek to block %d\n", + if(dvd_file->dvd->verbose >= 1) { + fprintf( stderr, "libdvdread: DVDReadBlocksPath1: Can't seek to block %d\n", offset ); + } return off < 0 ? off : 0; } ret = dvdinput_read( dvd_file->title_devs[ i ], data, @@ -884,8 +1127,10 @@ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset, /* Read part 1 */ off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); if( off < 0 || off != (int)offset ) { - fprintf( stderr, "libdvdread: Can't seek to block %d\n", + if(dvd_file->dvd->verbose >= 1) { + fprintf( stderr, "libdvdread: DVDReadBlocksPath2: Can't seek to block %d\n", offset ); + } return off < 0 ? off : 0; } ret = dvdinput_read( dvd_file->title_devs[ i ], data, @@ -900,8 +1145,9 |