📄 dvd_reader.c
字号:
/* * Copyright (C) 2001, 2002, 2003 Billy Biggs <vektor@dumbterm.net>, * H錵an Hjort <d95hjort@dtek.chalmers.se>, * Bj鰎n Englund <d4bjorn@dtek.chalmers.se> * * This program 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. * * 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. * * 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. */#include "config.h"#include <sys/types.h>#include <sys/stat.h>#include <sys/time.h> /* For the timing of dvdcss_title crack. */#include <fcntl.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <limits.h>#include <dirent.h> #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)|| defined(__DARWIN__)#define SYS_BSD 1#endif#if defined(__sun)#include <sys/mnttab.h>#elif defined(SYS_BSD)#include <fstab.h>#elif defined(__linux__)#include <mntent.h>#endif#include "dvd_udf.h"#include "dvd_input.h"#include "dvd_reader.h"#include "md5.h"#define DEFAULT_UDF_CACHE_LEVEL 1struct dvd_reader_s { /* Basic information. */ int isImageFile; /* Hack for keeping track of the css status. * 0: no css, 1: perhaps (need init of keys), 2: have done init */ int css_state; int css_title; /* Last title that we have called dvdinpute_title for. */ /* Information required for an image file. */ dvd_input_t dev; /* Information required for a directory path drive. */ char *path_root; /* Filesystem cache */ int udfcache_level; /* 0 - turned off, 1 - on */ void *udfcache;};struct dvd_file_s { /* Basic information. */ dvd_reader_t *dvd; /* Hack for selecting the right css title. */ int css_title; /* Information required for an image file. */ uint32_t lb_start; uint32_t seek_pos; /* Information required for a directory path drive. */ size_t title_sizes[ 9 ]; dvd_input_t title_devs[ 9 ]; /* Calculated at open-time, size in blocks. */ ssize_t filesize;};/** * Set the level of caching on udf * level = 0 (no caching) * level = 1 (caching filesystem info) */int DVDUDFCacheLevel(dvd_reader_t *device, int level){ struct dvd_reader_s *dev = (struct dvd_reader_s *)device; if(level > 0) { level = 1; } else if(level < 0) { return dev->udfcache_level; } dev->udfcache_level = level; return level;}void *GetUDFCacheHandle(dvd_reader_t *device){ struct dvd_reader_s *dev = (struct dvd_reader_s *)device; return dev->udfcache;}void SetUDFCacheHandle(dvd_reader_t *device, void *cache){ struct dvd_reader_s *dev = (struct dvd_reader_s *)device; dev->udfcache = cache;}/* Loop over all titles and call dvdcss_title to crack the keys. */static int initAllCSSKeys( dvd_reader_t *dvd ){ struct timeval all_s, all_e; struct timeval t_s, t_e; char filename[ MAX_UDF_FILE_NAME_LEN ]; uint32_t start, len; int title; char *nokeys_str = getenv("DVDREAD_NOKEYS"); if(nokeys_str != NULL) return 0; 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++ ) { gettimeofday( &t_s, NULL ); if( title == 0 ) { sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); } else { sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 ); } start = UDFFindFile( dvd, filename, &len ); if( start != 0 && len != 0 ) { /* Perform CSS key cracking for this title. */ fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", filename, start ); if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)\n", filename, start); } gettimeofday( &t_e, NULL ); fprintf( stderr, "libdvdread: Elapsed time %ld\n", (long int) t_e.tv_sec - t_s.tv_sec ); } if( title == 0 ) continue; gettimeofday( &t_s, NULL ); sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 ); start = UDFFindFile( dvd, filename, &len ); if( start == 0 || len == 0 ) break; /* Perform CSS key cracking for this title. */ fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", filename, start ); if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)!!\n", filename, start); } gettimeofday( &t_e, NULL ); fprintf( stderr, "libdvdread: Elapsed time %ld\n", (long int) t_e.tv_sec - t_s.tv_sec ); } title--; fprintf( stderr, "libdvdread: Found %d VTS's\n", title ); gettimeofday(&all_e, NULL); fprintf( stderr, "libdvdread: Elapsed time %ld\n", (long int) all_e.tv_sec - all_s.tv_sec ); return 0;}/** * Open a DVD image or block device file. */static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ){ dvd_reader_t *dvd; dvd_input_t dev; dev = dvdinput_open( location ); if( !dev ) { fprintf( stderr, "libdvdread: Can't open %s for reading\n", location ); return 0; } dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); if( !dvd ) return 0; dvd->isImageFile = 1; dvd->dev = dev; dvd->path_root = 0; dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; dvd->udfcache = 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 * don't have that information. */ dvd->css_state = 1; /* Need key init. */ } dvd->css_title = 0; return dvd;}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; dvd->isImageFile = 0; dvd->dev = 0; dvd->path_root = strdup( path_root ); dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; dvd->udfcache = NULL; dvd->css_state = 0; /* Only used in the UDF path */ dvd->css_title = 0; /* Only matters in the UDF path */ return dvd;}#if defined(__sun)/* /dev/rdsk/c0t6d0s0 (link to /devices/...) /vol/dev/rdsk/c0t6d0/?? /vol/rdsk/<name> */static char *sun_block2char( const char *path ){ char *new_path; /* Must contain "/dsk/" */ if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path ); /* Replace "/dsk/" with "/rdsk/" */ new_path = malloc( strlen(path) + 2 ); strcpy( new_path, path ); strcpy( strstr( new_path, "/dsk/" ), "" ); strcat( new_path, "/rdsk/" ); strcat( new_path, strstr( path, "/dsk/" ) + strlen( "/dsk/" ) ); return new_path;}#endif#if defined(SYS_BSD)/* FreeBSD /dev/(r)(a)cd0c (a is for atapi), recomended to _not_ use r 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) */static char *bsd_block2char( const char *path ){ 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 ) ) return (char *) strdup( path ); /* Replace "/dev/" with "/dev/r" */ new_path = malloc( strlen(path) + 2 ); strcpy( new_path, "/dev/r" ); strcat( new_path, path + strlen( "/dev/" ) ); return new_path;}#endifdvd_reader_t *DVDOpen( const char *path ){ struct stat fileinfo; int ret, have_css; char *dev_name = 0; if( path == NULL ) return 0; ret = stat( path, &fileinfo ); if( ret < 0 ) { /* If we can't stat the file, give up */ fprintf( stderr, "libdvdread: Can't stat %s\n", path ); perror(""); return 0; } /* 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. */#if defined(__sun) return DVDOpenImageFile( sun_block2char( path ), have_css );#elif defined(SYS_BSD) return DVDOpenImageFile( bsd_block2char( path ), have_css );#else return DVDOpenImageFile( path, have_css );#endif } 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 ) ) ) return 0; /* 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, PATH_MAX ); fchdir( cdir ); close( cdir ); if( new_path ) { free( path_copy ); path_copy = new_path; } } } /** * 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'; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -