aboutsummaryrefslogtreecommitdiff
path: root/lib/libdvd/libdvdread/src/dvd_reader.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libdvd/libdvdread/src/dvd_reader.c')
-rw-r--r--lib/libdvd/libdvdread/src/dvd_reader.c334
1 files changed, 271 insertions, 63 deletions
diff --git a/lib/libdvd/libdvdread/src/dvd_reader.c b/lib/libdvd/libdvdread/src/dvd_reader.c
index 8849e848e3..d9544b3264 100644
--- a/lib/libdvd/libdvdread/src/dvd_reader.c
+++ b/lib/libdvd/libdvdread/src/dvd_reader.c
@@ -1,25 +1,25 @@
/*
* Copyright (C) 2001-2004 Billy Biggs <vektor@dumbterm.net>,
- * HÂkan Hjort <d95hjort@dtek.chalmers.se>,
- * Bjˆrn Englund <d4bjorn@dtek.chalmers.se>
+ * Håkan Hjort <d95hjort@dtek.chalmers.se>,
+ * Björn Englund <d4bjorn@dtek.chalmers.se>
*
- * This program is free software; you can redistribute it and/or modify
+ * This file is part of libdvdread.
+ *
+ * libdvdread is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
+ * libdvdread is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with libdvdread; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "config.h"
-
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h> /* For the timing of dvdcss_title crack. */
@@ -28,6 +28,7 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
+#include <ctype.h>
#include <unistd.h>
#include <limits.h>
#include <dirent.h>
@@ -56,7 +57,7 @@ static inline int _private_gettimeofday( struct timeval *tv, void *tz )
#define lseek64 _lseeki64
#endif
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)|| defined(__DARWIN__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__) || defined(__APPLE__)
#define SYS_BSD 1
#endif
@@ -66,11 +67,12 @@ static inline int _private_gettimeofday( struct timeval *tv, void *tz )
#include <fstab.h>
#elif defined(__linux__)
#include <mntent.h>
+#include <paths.h>
#endif
-#include "dvd_udf.h"
+#include "dvdread/dvd_udf.h"
#include "dvd_input.h"
-#include "dvd_reader.h"
+#include "dvdread/dvd_reader.h"
#include "md5.h"
#define DEFAULT_UDF_CACHE_LEVEL 1
@@ -177,7 +179,6 @@ static int initAllCSSKeys( dvd_reader_t *dvd )
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++ ) {
@@ -257,7 +258,7 @@ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css )
if( have_css ) {
/* Only if DVDCSS_METHOD = title, a bit if it's disc or if
- * DVDCSS_METHOD = key but region missmatch. Unfortunaly we
+ * DVDCSS_METHOD = key but region mismatch. Unfortunately we
* don't have that information. */
dvd->css_state = 1; /* Need key init. */
@@ -280,7 +281,6 @@ static dvd_reader_t *DVDOpenPath( const char *path_root )
free(dvd);
return 0;
}
-
dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL;
dvd->udfcache = NULL;
@@ -313,17 +313,23 @@ static char *sun_block2char( const char *path )
#endif
#if defined(SYS_BSD)
-/* FreeBSD /dev/(r)(a)cd0c (a is for atapi), recomended to _not_ use r
+/* 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 */
- if( !strncmp( path, "/dev/", 5 ) || strncmp( path, "/dev/r", 6 ) )
+ if( strncmp( path, "/dev/", 5 ) || !strncmp( path, "/dev/r", 6 ) )
return (char *) strdup( path );
/* Replace "/dev/" with "/dev/r" */
@@ -332,33 +338,34 @@ static char *bsd_block2char( const char *path )
strcat( new_path, path + strlen( "/dev/" ) );
return new_path;
+#endif /* __FreeBSD__ || __DragonFly__ */
}
#endif
+
dvd_reader_t *DVDOpen( const char *ppath )
{
struct stat fileinfo;
- int ret;
- int have_css;
+ int ret, have_css, retval, cdir = -1;
dvd_reader_t *ret_val = NULL;
char *dev_name = NULL;
- char *path;
+ char *path = NULL, *new_path = NULL, *path_copy = NULL;
-#ifdef _MSC_VER
+#if defined(_WIN32) || defined(__OS2__)
int len;
#endif
if( ppath == NULL )
- return 0;
+ goto DVDOpen_error;
path = strdup(ppath);
if( path == NULL )
- return 0;
+ goto DVDOpen_error;
/* Try to open libdvdcss or fall back to standard functions */
have_css = dvdinput_setup();
-#ifdef _MSC_VER
+#if defined(_WIN32) || defined(__OS2__)
/* Strip off the trailing \ if it is not a drive */
len = strlen(path);
if ((len > 1) &&
@@ -372,17 +379,18 @@ dvd_reader_t *DVDOpen( const char *ppath )
ret = stat( path, &fileinfo );
if( ret < 0 ) {
+
/* maybe "host:port" url? try opening it with acCeSS library */
if( strchr(path,':') ) {
ret_val = DVDOpenImageFile( path, have_css );
free(path);
return ret_val;
}
+
/* If we can't stat the file, give up */
fprintf( stderr, "libdvdread: Can't stat %s\n", path );
perror("");
- free(path);
- return NULL;
+ goto DVDOpen_error;
}
/* First check if this is a block/char device or a file*/
@@ -393,20 +401,20 @@ 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;
- char *path_copy;
#if defined(SYS_BSD)
struct fstab* fe;
#elif defined(__sun) || defined(__linux__)
@@ -414,44 +422,55 @@ dvd_reader_t *DVDOpen( const char *ppath )
#endif
/* XXX: We should scream real loud here. */
- if( !(path_copy = strdup( path ) ) ) {
- free(path);
- return NULL;
- }
+ if( !(path_copy = strdup( path ) ) )
+ goto DVDOpen_error;
#ifndef WIN32 /* don't have fchdir, and getcwd( NULL, ... ) is strange */
/* Also WIN32 does not have symlinks, so we don't need this bit of code. */
- /* Resolve any symlinks and get the absolut dir name. */
+ /* Resolve any symlinks and get the absolute dir name. */
{
- char *new_path;
- int cdir = open( ".", O_RDONLY );
-
- if( cdir >= 0 ) {
- chdir( path_copy );
+ if( ( cdir = open( ".", O_RDONLY ) ) >= 0 ) {
+ if( chdir( path_copy ) == -1 ) {
+ goto DVDOpen_error;
+ }
new_path = malloc(PATH_MAX+1);
if(!new_path) {
- free(path);
- return NULL;
+ goto DVDOpen_error;
+ }
+ if( getcwd( new_path, PATH_MAX ) == NULL ) {
+ goto DVDOpen_error;
}
- getcwd(new_path, PATH_MAX );
- fchdir( cdir );
+ retval = fchdir( cdir );
close( cdir );
- free( path_copy );
+ cdir = -1;
+ if( retval == -1 ) {
+ goto DVDOpen_error;
+ }
path_copy = new_path;
+ new_path = NULL;
}
}
#endif
+
/**
* If we're being asked to open a directory, check if that directory
* is the mountpoint for a DVD-ROM which we can use instead.
*/
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 defined(_WIN32) || defined(__OS2__)
+ if(strlen(path_copy) > TITLES_MAX) {
+ if(!strcasecmp(&(path_copy[strlen( path_copy ) - TITLES_MAX]),
+ "\\video_ts"))
+ path_copy[strlen(path_copy) - (TITLES_MAX-1)] = '\0';
+ }
+#endif
if( strlen( path_copy ) > TITLES_MAX ) {
if( !strcasecmp( &(path_copy[ strlen( path_copy ) - TITLES_MAX ]),
"/video_ts" ) ) {
@@ -513,11 +532,17 @@ dvd_reader_t *DVDOpen( const char *ppath )
}
fclose( mntfile );
}
-#elif defined(_MSC_VER)
+#elif defined(_WIN32) || defined(__OS2__)
+#ifdef __OS2__
+ /* Use DVDOpenImageFile() only if it is a drive */
+ if(isalpha(path[0]) && path[1] == ':' &&
+ ( !path[2] ||
+ ((path[2] == '\\' || path[2] == '/') && !path[3])))
+#endif
auth_drive = DVDOpenImageFile( path, have_css );
#endif
-#ifndef _MSC_VER
+#if !defined(_WIN32) && !defined(__OS2__)
if( !dev_name ) {
fprintf( stderr, "libdvdread: Couldn't find device name.\n" );
} else if( !auth_drive ) {
@@ -527,12 +552,14 @@ dvd_reader_t *DVDOpen( const char *ppath )
#else
if( !auth_drive ) {
fprintf( stderr, "libdvdread: Device %s inaccessible, "
- "CSS authentication not available.\n", dev_name );
+ "CSS authentication not available.\n", path );
}
#endif
free( dev_name );
+ dev_name = NULL;
free( path_copy );
+ path_copy = NULL;
/**
* If we've opened a drive, just use that.
@@ -541,7 +568,6 @@ dvd_reader_t *DVDOpen( const char *ppath )
free(path);
return auth_drive;
}
-
/**
* Otherwise, we now try to open the directory tree instead.
*/
@@ -550,9 +576,17 @@ dvd_reader_t *DVDOpen( const char *ppath )
return ret_val;
}
+DVDOpen_error:
/* If it's none of the above, screw it. */
fprintf( stderr, "libdvdread: Could not open %s\n", path );
+ if( path != NULL )
free( path );
+ if ( path_copy != NULL )
+ free( path_copy );
+ if ( cdir >= 0 )
+ close( cdir );
+ if ( new_path != NULL )
+ free( new_path );
return NULL;
}
@@ -634,7 +668,6 @@ static int findDirFile( const char *path, const char *file, char *filename )
return 0;
}
}
-
closedir( dir );
#endif // _XBMC
return -1;
@@ -908,9 +941,7 @@ void DVDCloseFile( dvd_file_t *dvd_file )
int i;
if( dvd_file ) {
- if( dvd_file->dvd->isImageFile ) {
- ;
- } else {
+ if( !dvd_file->dvd->isImageFile ) {
for( i = 0; i < TITLES_MAX; ++i ) {
if( dvd_file->title_devs[ i ] ) {
dvdinput_close( dvd_file->title_devs[i] );
@@ -923,12 +954,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,
int encrypted )
{
int ret;
+
if( !device->dev ) {
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
return 0;
@@ -1132,6 +1338,7 @@ ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
size_t block_count, unsigned char *data )
{
int ret;
+
/* Check arguments. */
if( dvd_file == NULL || offset < 0 || data == NULL )
return -1;
@@ -1283,6 +1490,7 @@ int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid )
"allocate memory for file read!\n" );
return -1;
}
+
bytes_read = DVDReadBytes( dvd_file, buffer, file_size );
if( bytes_read != file_size ) {
fprintf( stderr, "libdvdread: DVDDiscId read returned %zd bytes"