dvd_reader_t *DVDOpen( const char *path ) { struct stat fileinfo; int ret, have_css; char *dev_name = NULL; int internal_errno = 0; int verbose; if( path == NULL ) { errno = EINVAL; return NULL; } verbose = get_verbose(); #ifdef WIN32 /* Stat doesn't work on devices under mingwin/cygwin. */ if( path[0] && path[1] == ':' && path[2] == '\0' ) { /* Don't try to stat the file */ fileinfo.st_mode = S_IFBLK; } else #endif { ret = stat( path, &fileinfo ); if( ret < 0 ) { int tmp_errno = errno; /* If we can't stat the file, give up */ if(verbose >= 1) { fprintf( stderr, "libdvdread: Can't stat '%s': %s\n", path, strerror(errno)); } errno = tmp_errno; return NULL; } } /* Try to open libdvdcss or fall back to standard functions */ have_css = dvdinput_setup(); /* First check if this is a block/char device or a file*/ if( S_ISBLK( fileinfo.st_mode ) || S_ISCHR( fileinfo.st_mode ) || S_ISREG( fileinfo.st_mode ) ) { /** * Block devices and regular files are assumed to be DVD-Video images. */ dvd_reader_t *dvd = NULL; #if defined(__sun) dev_name = sun_block2char( path ); #elif defined(SYS_BSD) dev_name = bsd_block2char( path ); #else dev_name = strdup( path ); #endif dvd = DVDOpenImageFile( dev_name, have_css ); free( dev_name ); 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__) || defined(__CYGWIN__) FILE *mntfile; #endif /* 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; char *current_path; 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 = 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 * is the mountpoint for a DVD-ROM which we can use instead. */ if( strlen( path_copy ) > 1 ) { if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) { path_copy[ strlen( path_copy ) - 1 ] = '\0'; } } 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%s\n", dev_name, 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" ); if( mntfile ) { struct mnttab mp; int res; 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%s\n", dev_name, mp.mnt_mountp, have_css ? " for CSS authentication" : ""); } auth_drive = DVDOpenImageFile( dev_name, have_css ); if(!auth_drive) { internal_errno = errno; } break; } } fclose( mntfile ); } #elif defined(__linux__) || defined(__CYGWIN__) mntfile = fopen( MOUNTED, "r" ); if( mntfile ) { struct mntent *me; 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%s\n", me->mnt_fsname, 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; } } fclose( mntfile ); } #elif defined(__MINGW32__) dev_name = strdup(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 ) { 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 ); free( path_copy ); /** * If we've opened a drive, just use that. */ if( auth_drive ) { return auth_drive; } /** * Otherwise, we now try to open the directory tree instead. */ return DVDOpenPath( path ); } /* If it's none of the above, screw it. */ if(verbose >= 1) { fprintf( stderr, "libdvdread: Could not open %s\n", path ); } return 0; }
static dvd_reader_t *DVDOpenCommon( const char *ppath, void *stream, dvd_reader_stream_cb *stream_cb ) { struct stat fileinfo; int ret, have_css, retval, cdir = -1; dvd_reader_t *ret_val = NULL; char *dev_name = NULL; char *path = NULL, *new_path = NULL, *path_copy = NULL; #if defined(_WIN32) || defined(__OS2__) int len; #endif /* Try to open DVD using stream_cb functions */ if( stream != NULL && stream_cb != NULL ) { have_css = dvdinput_setup( "" ); return DVDOpenImageFile( NULL, stream, stream_cb, have_css ); } if( ppath == NULL ) goto DVDOpen_error; path = strdup(ppath); if( path == NULL ) goto DVDOpen_error; /* Try to open libdvdcss or fall back to standard functions */ have_css = dvdinput_setup(path); #if defined(_WIN32) || defined(__OS2__) /* Strip off the trailing \ if it is not a drive */ len = strlen(path); if ((len > 1) && (path[len - 1] == '\\') && (path[len - 2] != ':')) { path[len-1] = '\0'; } #endif ret = mythfile_stat( path, &fileinfo ); if( ret < 0 ) { /* maybe "host:port" url? try opening it with acCeSS library */ if( strchr(path,':') ) { ret_val = DVDOpenImageFile( path, NULL, NULL, 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(""); goto DVDOpen_error; } /* First check if this is a block/char device or a file*/ if( S_ISBLK( fileinfo.st_mode ) || S_ISCHR( fileinfo.st_mode ) || S_ISREG( fileinfo.st_mode ) ) { /** * Block devices and regular files are assumed to be DVD-Video images. */ dvd_reader_t *dvd = NULL; #if defined(__sun) dev_name = sun_block2char( path ); #elif defined(SYS_BSD) dev_name = bsd_block2char( path ); #else dev_name = strdup( path ); #endif if(!dev_name) goto DVDOpen_error; dvd = DVDOpenImageFile( dev_name, NULL, NULL, have_css ); free( dev_name ); free(path); return dvd; } else if( S_ISDIR( fileinfo.st_mode ) ) { dvd_reader_t *auth_drive = 0; #if defined(SYS_BSD) struct fstab* fe; #elif defined(__sun) || defined(__linux__) FILE *mntfile; #endif /* XXX: We should scream real loud here. */ 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 absolute dir name. */ if (!strncmp(path, "myth://", 7)) dev_name = strdup( path ); else { if( ( cdir = open( ".", O_RDONLY ) ) >= 0 ) { if( chdir( path_copy ) == -1 ) { goto DVDOpen_error; } new_path = malloc(PATH_MAX+1); if(!new_path) { goto DVDOpen_error; } if( getcwd( new_path, PATH_MAX ) == NULL ) { goto DVDOpen_error; } retval = fchdir( cdir ); close( cdir ); cdir = -1; if( retval == -1 ) { goto DVDOpen_error; } free(path_copy); path_copy = new_path; new_path = NULL; } } #endif /** * If we're being asked to open a directory, check if that directory * is the mount point for a DVD-ROM which we can use instead. */ if( 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 ) > 9 ) { if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]), "\\video_ts")) path_copy[ strlen( path_copy ) - (9-1) ] = '\0'; } #endif 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') { free( path_copy ); if( !(path_copy = strdup( "/" ) ) ) goto DVDOpen_error; } #if defined(__APPLE__) struct statfs s[128]; int r = getfsstat(NULL, 0, MNT_NOWAIT); if (r > 0) { if (r > 128) r = 128; r = getfsstat(s, r * sizeof(s[0]), MNT_NOWAIT); int i; for (i=0; i<r; i++) { if (!strcmp(path_copy, s[i].f_mntonname)) { dev_name = bsd_block2char(s[i].f_mntfromname); fprintf( stderr, "libdvdread: Attempting to use device %s" " mounted on %s for CSS authentication\n", dev_name, s[i].f_mntonname); auth_drive = DVDOpenImageFile( dev_name, NULL, NULL, have_css ); break; } } } #elif defined(SYS_BSD) if( ( fe = getfsfile( path_copy ) ) ) { dev_name = bsd_block2char( fe->fs_spec ); fprintf( stderr, "libdvdread: Attempting to use device %s" " mounted on %s for CSS authentication\n", dev_name, fe->fs_file ); auth_drive = DVDOpenImageFile( dev_name, NULL, NULL, have_css ); } #elif defined(__sun) mntfile = fopen( MNTTAB, "r" ); if( mntfile ) { struct mnttab mp; int res; while( ( res = getmntent( mntfile, &mp ) ) != -1 ) { if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) { dev_name = sun_block2char( mp.mnt_special ); fprintf( stderr, "libdvdread: Attempting to use device %s" " mounted on %s for CSS authentication\n", dev_name, mp.mnt_mountp ); auth_drive = DVDOpenImageFile( dev_name, NULL, NULL, have_css ); break; } } fclose( mntfile ); } #elif defined(__linux__) mntfile = fopen( _PATH_MOUNTED, "r" ); if( mntfile ) { struct mntent *me; while( ( me = getmntent( mntfile ) ) ) { if( !strcmp( me->mnt_dir, path_copy ) ) { fprintf( stderr, "libdvdread: Attempting to use device %s" " mounted on %s for CSS authentication\n", me->mnt_fsname, me->mnt_dir ); auth_drive = DVDOpenImageFile( me->mnt_fsname, NULL, NULL, have_css ); dev_name = strdup(me->mnt_fsname); break; } } fclose( mntfile ); } #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, NULL, NULL, have_css ); #endif #if !defined(_WIN32) && !defined(__OS2__) if( !dev_name ) { 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 ); } #else if( !auth_drive ) { fprintf( stderr, "libdvdread: Device %s inaccessible, " "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. */ if( auth_drive ) { free(path); return auth_drive; } /** * Otherwise, we now try to open the directory tree instead. */ ret_val = DVDOpenPath( path ); free( path ); return ret_val; } DVDOpen_error: /* If it's none of the above, screw it. */ fprintf( stderr, "libdvdread: Could not open %s\n", path ); free( path ); free( path_copy ); if ( cdir >= 0 ) close( cdir ); free( new_path ); return NULL; }
dvd_reader_t *DVDOpen( const char *ppath ) { struct stat fileinfo; int ret; int have_css; dvd_reader_t *ret_val = NULL; char *dev_name = 0; char *path; #ifdef _MSC_VER int len; #endif if( ppath == NULL ) return 0; path = strdup(ppath); /* Try to open libdvdcss or fall back to standard functions */ have_css = dvdinput_setup(); #ifdef _MSC_VER /* Strip off the trailing \ if it is not a drive */ len = strlen(path); if ((len > 1) && (path[len - 1] == '\\') && (path[len - 2] != ':')) { path[len-1] = '\0'; } #endif 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 0; } /* First check if this is a block/char device or a file*/ if( S_ISBLK( fileinfo.st_mode ) || S_ISCHR( fileinfo.st_mode ) || S_ISREG( fileinfo.st_mode ) ) { /** * Block devices and regular files are assumed to be DVD-Video images. */ #if defined(__sun) ret_val = DVDOpenImageFile( sun_block2char( path ), have_css ); #elif defined(SYS_BSD) ret_val = DVDOpenImageFile( bsd_block2char( path ), have_css ); #else ret_val = DVDOpenImageFile( path, have_css ); #endif free(path); return ret_val; } 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__) FILE *mntfile; #endif /* XXX: We should scream real loud here. */ if( !(path_copy = strdup( path ) ) ) { free(path); return 0; } #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. */ { char *new_path; int cdir = open( ".", O_RDONLY ); if( cdir >= 0 ) { chdir( path_copy ); new_path = getcwd( NULL, XINE_PATH_MAX ); fchdir( cdir ); close( cdir ); if( new_path ) { free( path_copy ); path_copy = new_path; } } } #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 ] == '/' ) path_copy[ strlen( path_copy ) - 1 ] = '\0'; } if( strlen( path_copy ) > 9 ) { if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]), "/video_ts" ) ) { path_copy[ strlen( path_copy ) - 9 ] = '\0'; } } #if defined(SYS_BSD) if( ( fe = getfsfile( path_copy ) ) ) { dev_name = bsd_block2char( fe->fs_spec ); fprintf( stderr, "libdvdread: Attempting to use device %s" " mounted on %s for CSS authentication\n", dev_name, fe->fs_file ); auth_drive = DVDOpenImageFile( dev_name, have_css ); } #elif defined(__sun) mntfile = fopen( MNTTAB, "r" ); if( mntfile ) { struct mnttab mp; int res; while( ( res = getmntent( mntfile, &mp ) ) != -1 ) { if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) { dev_name = sun_block2char( mp.mnt_special ); fprintf( stderr, "libdvdread: Attempting to use device %s" " mounted on %s for CSS authentication\n", dev_name, mp.mnt_mountp ); auth_drive = DVDOpenImageFile( dev_name, have_css ); break; } } fclose( mntfile ); } #elif defined(__linux__) mntfile = fopen( MOUNTED, "r" ); if( mntfile ) { struct mntent *me; while( ( me = getmntent( mntfile ) ) ) { if( !strcmp( me->mnt_dir, path_copy ) ) { fprintf( stderr, "libdvdread: Attempting to use device %s" " mounted on %s for CSS authentication\n", me->mnt_fsname, me->mnt_dir ); auth_drive = DVDOpenImageFile( me->mnt_fsname, have_css ); /* If the device is not encrypted, don't access the device * directly as it would fail for non-UDF DVDs */ if ( auth_drive && dvdinput_is_encrypted( auth_drive->dev ) == 0) { DVDClose( auth_drive ); auth_drive = NULL; break; } dev_name = strdup(me->mnt_fsname); break; } } fclose( mntfile ); } #elif defined(_MSC_VER) auth_drive = DVDOpenImageFile( path, have_css ); #endif #ifndef _MSC_VER if( !dev_name ) { 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 ); } #else if( !auth_drive ) { fprintf( stderr, "libdvdread: Device %s inaccessible, " "CSS authentication not available.\n", dev_name ); } #endif free( dev_name ); free( path_copy ); /** * If we've opened a drive, just use that. */ if( auth_drive ) { free(path); return auth_drive; } /** * Otherwise, we now try to open the directory tree instead. */ ret_val = DVDOpenPath( path ); free( path ); return ret_val; } /* If it's none of the above, screw it. */ fprintf( stderr, "libdvdread: Could not open %s\n", path ); free( path ); return 0; }