comparison dvdread/dvd_reader.c @ 24047:de28f9e8cb00

Sync libdvdread with version 0.9.5 (functional changes).
author diego
date Wed, 15 Aug 2007 11:47:22 +0000
parents 22cb9d5f1e21
children 1542693b2a30
comparison
equal deleted inserted replaced
24046:7e2808fb1807 24047:de28f9e8cb00
58 t->tv_sec=timebuffer.time; 58 t->tv_sec=timebuffer.time;
59 t->tv_usec=1000*timebuffer.millitm; 59 t->tv_usec=1000*timebuffer.millitm;
60 } 60 }
61 #endif 61 #endif
62 62
63 #include "dvd_reader.h"
64 #include "dvd_input.h"
63 #include "dvd_udf.h" 65 #include "dvd_udf.h"
64 #include "dvd_input.h"
65 #include "dvd_reader.h"
66 #include "md5.h" 66 #include "md5.h"
67
68 #include "dvdread_internal.h"
67 69
68 #define DEFAULT_UDF_CACHE_LEVEL 0 70 #define DEFAULT_UDF_CACHE_LEVEL 0
69 71
70 struct dvd_reader_s { 72 struct dvd_reader_s {
71 /* Basic information. */ 73 /* Basic information. */
83 char *path_root; 85 char *path_root;
84 86
85 /* Filesystem cache */ 87 /* Filesystem cache */
86 int udfcache_level; /* 0 - turned off, 1 - on */ 88 int udfcache_level; /* 0 - turned off, 1 - on */
87 void *udfcache; 89 void *udfcache;
90
91 /* block aligned malloc */
92 void *align;
93
94 /* error message verbosity level */
95 int verbose;
88 }; 96 };
89 97
90 struct dvd_file_s { 98 struct dvd_file_s {
91 /* Basic information. */ 99 /* Basic information. */
92 dvd_reader_t *dvd; 100 dvd_reader_t *dvd;
103 dvd_input_t title_devs[ 9 ]; 111 dvd_input_t title_devs[ 9 ];
104 112
105 /* Calculated at open-time, size in blocks. */ 113 /* Calculated at open-time, size in blocks. */
106 ssize_t filesize; 114 ssize_t filesize;
107 }; 115 };
116
117
118 #define DVDREAD_VERBOSE_DEFAULT 0
119
120 int get_verbose(void)
121 {
122 char *dvdread_verbose;
123 int verbose;
124
125 dvdread_verbose = getenv("DVDREAD_VERBOSE");
126 if(dvdread_verbose) {
127 verbose = (int)strtol(dvdread_verbose, NULL, 0);
128 } else {
129 verbose = DVDREAD_VERBOSE_DEFAULT;
130 }
131 return verbose;
132 }
133
134 int dvdread_verbose(dvd_reader_t *dvd)
135 {
136 return dvd->verbose;
137 }
138
139 dvd_reader_t *device_of_file(dvd_file_t *file)
140 {
141 return file->dvd;
142 }
143
144 /**
145 * Returns the compiled version. (DVDREAD_VERSION as an int)
146 */
147 int DVDVersion(void)
148 {
149 return DVDREAD_VERSION;
150 }
151
108 152
109 /** 153 /**
110 * Set the level of caching on udf 154 * Set the level of caching on udf
111 * level = 0 (no caching) 155 * level = 0 (no caching)
112 * level = 1 (caching filesystem info) 156 * level = 1 (caching filesystem info)
138 struct dvd_reader_s *dev = (struct dvd_reader_s *)device; 182 struct dvd_reader_s *dev = (struct dvd_reader_s *)device;
139 183
140 dev->udfcache = cache; 184 dev->udfcache = cache;
141 } 185 }
142 186
187 void *GetAlignHandle(dvd_reader_t *device)
188 {
189 struct dvd_reader_s *dev = (struct dvd_reader_s *)device;
190
191 return dev->align;
192 }
193
194 void SetAlignHandle(dvd_reader_t *device, void *align)
195 {
196 struct dvd_reader_s *dev = (struct dvd_reader_s *)device;
197
198 dev->align = align;
199 }
200
201 #ifdef WIN32 /* replacement gettimeofday implementation */
202 #include <sys/timeb.h>
203 static int gettimeofday( struct timeval *tv, void *tz )
204 {
205 struct timeb t;
206 ftime( &t );
207 tv->tv_sec = t.time;
208 tv->tv_usec = t.millitm * 1000;
209 return 0;
210 }
211 #endif
143 212
144 213
145 /* Loop over all titles and call dvdcss_title to crack the keys. */ 214 /* Loop over all titles and call dvdcss_title to crack the keys. */
146 static int initAllCSSKeys( dvd_reader_t *dvd ) 215 static int initAllCSSKeys( dvd_reader_t *dvd )
147 { 216 {
153 222
154 char *nokeys_str = getenv("DVDREAD_NOKEYS"); 223 char *nokeys_str = getenv("DVDREAD_NOKEYS");
155 if(nokeys_str != NULL) 224 if(nokeys_str != NULL)
156 return 0; 225 return 0;
157 226
227 if(dvd->verbose >= 1) {
158 fprintf( stderr, "\n" ); 228 fprintf( stderr, "\n" );
159 fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" ); 229 fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" );
160 fprintf( stderr, "libdvdread: This can take a _long_ time, " 230 fprintf( stderr, "libdvdread: This can take a _long_ time, "
161 "please be patient\n\n" ); 231 "please be patient\n\n" );
162 232 }
163 gettimeofday(&all_s, NULL); 233 gettimeofday(&all_s, NULL);
164 234
165 for( title = 0; title < 100; title++ ) { 235 for( title = 0; title < 100; title++ ) {
166 gettimeofday( &t_s, NULL ); 236 gettimeofday( &t_s, NULL );
167 if( title == 0 ) { 237 if( title == 0 ) {
170 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 ); 240 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 );
171 } 241 }
172 start = UDFFindFile( dvd, filename, &len ); 242 start = UDFFindFile( dvd, filename, &len );
173 if( start != 0 && len != 0 ) { 243 if( start != 0 && len != 0 ) {
174 /* Perform CSS key cracking for this title. */ 244 /* Perform CSS key cracking for this title. */
245 if(dvd->verbose >= 1) {
175 fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", 246 fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
176 filename, start ); 247 filename, start );
248 }
177 if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { 249 if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
250 if(dvd->verbose >= 0) {
178 fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)\n", filename, start); 251 fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)\n", filename, start);
179 } 252 }
253 }
180 gettimeofday( &t_e, NULL ); 254 gettimeofday( &t_e, NULL );
255 if(dvd->verbose >= 1) {
181 fprintf( stderr, "libdvdread: Elapsed time %ld\n", 256 fprintf( stderr, "libdvdread: Elapsed time %ld\n",
182 (long int) t_e.tv_sec - t_s.tv_sec ); 257 (long int) t_e.tv_sec - t_s.tv_sec );
183 } 258 }
259 }
184 260
185 if( title == 0 ) continue; 261 if( title == 0 ) continue;
186 262
187 gettimeofday( &t_s, NULL ); 263 gettimeofday( &t_s, NULL );
188 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 ); 264 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 );
189 start = UDFFindFile( dvd, filename, &len ); 265 start = UDFFindFile( dvd, filename, &len );
190 if( start == 0 || len == 0 ) break; 266 if( start == 0 || len == 0 ) break;
191 267
192 /* Perform CSS key cracking for this title. */ 268 /* Perform CSS key cracking for this title. */
269 if(dvd->verbose >= 1) {
193 fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", 270 fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
194 filename, start ); 271 filename, start );
272 }
195 if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { 273 if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
274 if(dvd->verbose >= 0) {
196 fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)!!\n", filename, start); 275 fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)!!\n", filename, start);
197 } 276 }
277 }
198 gettimeofday( &t_e, NULL ); 278 gettimeofday( &t_e, NULL );
279 if(dvd->verbose >= 1) {
199 fprintf( stderr, "libdvdread: Elapsed time %ld\n", 280 fprintf( stderr, "libdvdread: Elapsed time %ld\n",
200 (long int) t_e.tv_sec - t_s.tv_sec ); 281 (long int) t_e.tv_sec - t_s.tv_sec );
201 } 282 }
283 }
202 title--; 284 title--;
203 285
286 if(dvd->verbose >= 1) {
204 fprintf( stderr, "libdvdread: Found %d VTS's\n", title ); 287 fprintf( stderr, "libdvdread: Found %d VTS's\n", title );
288 }
205 gettimeofday(&all_e, NULL); 289 gettimeofday(&all_e, NULL);
290 if(dvd->verbose >= 1) {
206 fprintf( stderr, "libdvdread: Elapsed time %ld\n", 291 fprintf( stderr, "libdvdread: Elapsed time %ld\n",
207 (long int) all_e.tv_sec - all_s.tv_sec ); 292 (long int) all_e.tv_sec - all_s.tv_sec );
208 293 }
209 return 0; 294 return 0;
210 } 295 }
211 296
212 297
213 298
214 /** 299 /**
215 * Open a DVD image or block device file. 300 * Open a DVD image or block device file.
301 * Checks if the root directory in the udf image file can be found.
302 * If not it assumes this isn't a valid udf image and returns NULL
216 */ 303 */
217 static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ) 304 static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css )
218 { 305 {
219 dvd_reader_t *dvd; 306 dvd_reader_t *dvd;
220 dvd_input_t dev; 307 dvd_input_t dev;
308 int verbose;
309
310 verbose = get_verbose();
221 311
222 dev = dvdinput_open( location ); 312 dev = dvdinput_open( location );
223 if( !dev ) { 313 if( !dev ) {
224 fprintf( stderr, "libdvdread: Can't open %s for reading\n", location ); 314 if(verbose >= 1) {
225 return 0; 315 fprintf( stderr, "libdvdread: Can't open '%s' for reading: %s\n",
316 location, strerror(errno));
317 }
318 return NULL;
226 } 319 }
227 320
228 dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); 321 dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
229 if( !dvd ) return 0; 322 if( !dvd ) {
323 int tmp_errno = errno;
324 dvdinput_close(dev);
325 errno = tmp_errno;
326 return NULL;
327 }
328 dvd->verbose = verbose;
230 dvd->isImageFile = 1; 329 dvd->isImageFile = 1;
231 dvd->dev = dev; 330 dvd->dev = dev;
232 dvd->path_root = 0; 331 dvd->path_root = NULL;
233 332
234 dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; 333 dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL;
235 dvd->udfcache = NULL; 334 dvd->udfcache = NULL;
335
336 dvd->align = NULL;
236 337
237 if( have_css ) { 338 if( have_css ) {
238 /* Only if DVDCSS_METHOD = title, a bit if it's disc or if 339 /* Only if DVDCSS_METHOD = title, a bit if it's disc or if
239 * DVDCSS_METHOD = key but region missmatch. Unfortunaly we 340 * DVDCSS_METHOD = key but region missmatch. Unfortunaly we
240 * don't have that information. */ 341 * don't have that information. */
241 342
242 dvd->css_state = 1; /* Need key init. */ 343 dvd->css_state = 1; /* Need key init. */
243 } 344 }
244 dvd->css_title = 0; 345 dvd->css_title = 0;
245 346
347 /* sanity check, is it a valid UDF image, can we find the root dir */
348 if(!UDFFindFile(dvd, "/", NULL)) {
349 dvdinput_close(dvd->dev);
350 if(dvd->udfcache) {
351 FreeUDFCache(dvd, dvd->udfcache);
352 }
353 if(dvd->align) {
354 if(dvd->verbose >= 0) {
355 fprintf(stderr, "libdvdread: DVDOpenImageFile(): Memory leak in align functions 1\n");
356 }
357 }
358 free(dvd);
359 return NULL;
360 }
246 return dvd; 361 return dvd;
247 } 362 }
248 363
249 static dvd_reader_t *DVDOpenPath( const char *path_root ) 364 static dvd_reader_t *DVDOpenPath( const char *path_root )
250 { 365 {
251 dvd_reader_t *dvd; 366 dvd_reader_t *dvd;
252 367
253 dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); 368 dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
254 if( !dvd ) return 0; 369 if( !dvd ) {
370 return NULL;
371 }
372 dvd->verbose = get_verbose();
255 dvd->isImageFile = 0; 373 dvd->isImageFile = 0;
256 dvd->dev = 0; 374 dvd->dev = 0;
257 dvd->path_root = strdup( path_root ); 375 dvd->path_root = strdup( path_root );
258 376 if(!dvd->path_root) {
377 free(dvd);
378 return 0;
379 }
259 dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; 380 dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL;
260 dvd->udfcache = NULL; 381 dvd->udfcache = NULL;
261 382
383 dvd->align = NULL;
384
262 dvd->css_state = 0; /* Only used in the UDF path */ 385 dvd->css_state = 0; /* Only used in the UDF path */
263 dvd->css_title = 0; /* Only matters in the UDF path */ 386 dvd->css_title = 0; /* Only matters in the UDF path */
264 387
265 return dvd; 388 return dvd;
266 } 389 }
318 441
319 dvd_reader_t *DVDOpen( const char *path ) 442 dvd_reader_t *DVDOpen( const char *path )
320 { 443 {
321 struct stat fileinfo; 444 struct stat fileinfo;
322 int ret, have_css; 445 int ret, have_css;
323 char *dev_name = 0; 446 char *dev_name = NULL;
324 447 int internal_errno = 0;
325 if( path == NULL ) 448 int verbose;
326 return 0; 449
450 if( path == NULL ) {
451 errno = EINVAL;
452 return NULL;
453 }
454
455 verbose = get_verbose();
327 456
328 #ifdef WIN32 457 #ifdef WIN32
329 /* Stat doesn't work on devices under mingwin/cygwin. */ 458 /* Stat doesn't work on devices under mingwin/cygwin. */
330 if( path[0] && path[1] == ':' && path[2] == '\0' ) 459 if( path[0] && path[1] == ':' && path[2] == '\0' )
331 { 460 {
335 else 464 else
336 #endif 465 #endif
337 { 466 {
338 ret = stat( path, &fileinfo ); 467 ret = stat( path, &fileinfo );
339 if( ret < 0 ) { 468 if( ret < 0 ) {
469 int tmp_errno = errno;
340 /* If we can't stat the file, give up */ 470 /* If we can't stat the file, give up */
341 fprintf( stderr, "libdvdread: Can't stat %s\n", path ); 471 if(verbose >= 1) {
342 perror(""); 472 fprintf( stderr, "libdvdread: Can't stat '%s': %s\n",
343 return 0; 473 path, strerror(errno));
474 }
475 errno = tmp_errno;
476 return NULL;
344 } 477 }
345 } 478 }
346 479
347 /* Try to open libdvdcss or fall back to standard functions */ 480 /* Try to open libdvdcss or fall back to standard functions */
348 have_css = dvdinput_setup(); 481 have_css = dvdinput_setup();
373 #endif 506 #endif
374 507
375 /* XXX: We should scream real loud here. */ 508 /* XXX: We should scream real loud here. */
376 if( !(path_copy = strdup( path ) ) ) return 0; 509 if( !(path_copy = strdup( path ) ) ) return 0;
377 510
511 #ifndef WIN32 /* don't have fchdir, and getcwd( NULL, ... ) is strange */
378 /* Resolve any symlinks and get the absolut dir name. */ 512 /* Resolve any symlinks and get the absolut dir name. */
379 { 513 {
380 char *new_path; 514 char *new_path;
381 int cdir = open( ".", O_RDONLY ); 515 char *current_path;
382 516
383 if( cdir >= 0 ) { 517 current_path = malloc(PATH_MAX);
518 if(current_path) {
519 if(!getcwd(current_path, PATH_MAX)) {
520 free(current_path);
521 current_path = NULL;
522 }
523 }
524 if(current_path) {
384 chdir( path_copy ); 525 chdir( path_copy );
385 new_path = getcwd( NULL, PATH_MAX ); 526 new_path = malloc(PATH_MAX);
386 #ifndef __MINGW32__ 527 if(new_path) {
387 fchdir( cdir ); 528 if(!getcwd(new_path, PATH_MAX )) {
388 #endif 529 free(new_path);
389 close( cdir ); 530 new_path = NULL;
531 }
532 }
533
534 chdir(current_path);
535 free(current_path);
390 if( new_path ) { 536 if( new_path ) {
391 free( path_copy ); 537 free( path_copy );
392 path_copy = new_path; 538 path_copy = new_path;
393 } 539 }
394 } 540 }
395 } 541 }
542 #endif
396 543
397 /** 544 /**
398 * If we're being asked to open a directory, check if that directory 545 * If we're being asked to open a directory, check if that directory
399 * is the mountpoint for a DVD-ROM which we can use instead. 546 * is the mountpoint for a DVD-ROM which we can use instead.
400 */ 547 */
401 548
402 if( strlen( path_copy ) > 1 ) { 549 if( strlen( path_copy ) > 1 ) {
403 if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) 550 if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) {
404 path_copy[ strlen( path_copy ) - 1 ] = '\0'; 551 path_copy[ strlen( path_copy ) - 1 ] = '\0';
405 } 552 }
406 553 }
407 if( strlen( path_copy ) > 9 ) { 554
555 if( strlen( path_copy ) >= 9 ) {
408 if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]), 556 if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]),
409 "/video_ts" ) ) { 557 "/video_ts" ) ) {
410 path_copy[ strlen( path_copy ) - 9 ] = '\0'; 558 path_copy[ strlen( path_copy ) - 9 ] = '\0';
559 if(path_copy[0] == '\0') {
560 path_copy[0] = '/';
561 path_copy[1] = '\0';
562 }
411 } 563 }
412 } 564 }
413 565
414 #if defined(SYS_BSD) 566 #if defined(SYS_BSD)
415 if( ( fe = getfsfile( path_copy ) ) ) { 567 if( ( fe = getfsfile( path_copy ) ) ) {
416 dev_name = bsd_block2char( fe->fs_spec ); 568 dev_name = bsd_block2char( fe->fs_spec );
569 if(verbose >= 1) {
417 fprintf( stderr, 570 fprintf( stderr,
418 "libdvdread: Attempting to use device %s" 571 "libdvdread: Attempting to use device %s"
419 " mounted on %s for CSS authentication\n", 572 " mounted on %s%s\n",
420 dev_name, 573 dev_name,
421 fe->fs_file ); 574 fe->fs_file,
575 have_css ? " for CSS authentication" : "");
576 }
422 auth_drive = DVDOpenImageFile( dev_name, have_css ); 577 auth_drive = DVDOpenImageFile( dev_name, have_css );
578 if(!auth_drive) {
579 internal_errno = errno;
580 }
423 } 581 }
424 #elif defined(__sun) 582 #elif defined(__sun)
425 mntfile = fopen( MNTTAB, "r" ); 583 mntfile = fopen( MNTTAB, "r" );
426 if( mntfile ) { 584 if( mntfile ) {
427 struct mnttab mp; 585 struct mnttab mp;
428 int res; 586 int res;
429 587
430 while( ( res = getmntent( mntfile, &mp ) ) != -1 ) { 588 while( ( res = getmntent( mntfile, &mp ) ) != -1 ) {
431 if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) { 589 if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
432 dev_name = sun_block2char( mp.mnt_special ); 590 dev_name = sun_block2char( mp.mnt_special );
591 if(verbose >= 1) {
433 fprintf( stderr, 592 fprintf( stderr,
434 "libdvdread: Attempting to use device %s" 593 "libdvdread: Attempting to use device %s"
435 " mounted on %s for CSS authentication\n", 594 " mounted on %s%s\n",
436 dev_name, 595 dev_name,
437 mp.mnt_mountp ); 596 mp.mnt_mountp,
597 have_css ? " for CSS authentication" : "");
598 }
438 auth_drive = DVDOpenImageFile( dev_name, have_css ); 599 auth_drive = DVDOpenImageFile( dev_name, have_css );
600 if(!auth_drive) {
601 internal_errno = errno;
602 }
439 break; 603 break;
440 } 604 }
441 } 605 }
442 fclose( mntfile ); 606 fclose( mntfile );
443 } 607 }
446 if( mntfile ) { 610 if( mntfile ) {
447 struct mntent *me; 611 struct mntent *me;
448 612
449 while( ( me = getmntent( mntfile ) ) ) { 613 while( ( me = getmntent( mntfile ) ) ) {
450 if( !strcmp( me->mnt_dir, path_copy ) ) { 614 if( !strcmp( me->mnt_dir, path_copy ) ) {
615 if(verbose >= 1) {
451 fprintf( stderr, 616 fprintf( stderr,
452 "libdvdread: Attempting to use device %s" 617 "libdvdread: Attempting to use device %s"
453 " mounted on %s for CSS authentication\n", 618 " mounted on %s%s\n",
454 me->mnt_fsname, 619 me->mnt_fsname,
455 me->mnt_dir ); 620 me->mnt_dir,
621 have_css ? " for CSS authentication" : "");
622 }
456 auth_drive = DVDOpenImageFile( me->mnt_fsname, have_css ); 623 auth_drive = DVDOpenImageFile( me->mnt_fsname, have_css );
624 if(!auth_drive) {
625 internal_errno = errno;
626 }
457 dev_name = strdup(me->mnt_fsname); 627 dev_name = strdup(me->mnt_fsname);
458 break; 628 break;
459 } 629 }
460 } 630 }
461 fclose( mntfile ); 631 fclose( mntfile );
463 #elif defined(__MINGW32__) 633 #elif defined(__MINGW32__)
464 dev_name = strdup(path); 634 dev_name = strdup(path);
465 auth_drive = DVDOpenImageFile( path, have_css ); 635 auth_drive = DVDOpenImageFile( path, have_css );
466 #endif 636 #endif
467 if( !dev_name ) { 637 if( !dev_name ) {
638 if(verbose >= 1) {
468 fprintf( stderr, "libdvdread: Couldn't find device name.\n" ); 639 fprintf( stderr, "libdvdread: Couldn't find device name.\n" );
640 }
469 } else if( !auth_drive ) { 641 } else if( !auth_drive ) {
470 fprintf( stderr, "libdvdread: Device %s inaccessible, " 642 if(verbose >= 1) {
471 "CSS authentication not available.\n", dev_name ); 643 fprintf( stderr, "libdvdread: Device %s inaccessible%s: %s\n",
644 dev_name,
645 have_css ? ", CSS authentication not available" : "",
646 strerror(internal_errno));
647 }
472 } 648 }
473 649
474 free( dev_name ); 650 free( dev_name );
475 free( path_copy ); 651 free( path_copy );
476 652
477 /** 653 /**
478 * If we've opened a drive, just use that. 654 * If we've opened a drive, just use that.
479 */ 655 */
480 if( auth_drive ) return auth_drive; 656 if( auth_drive ) {
481 657 return auth_drive;
658 }
482 /** 659 /**
483 * Otherwise, we now try to open the directory tree instead. 660 * Otherwise, we now try to open the directory tree instead.
484 */ 661 */
485 return DVDOpenPath( path ); 662 return DVDOpenPath( path );
486 } 663 }
487 664
488 /* If it's none of the above, screw it. */ 665 /* If it's none of the above, screw it. */
666 if(verbose >= 1) {
489 fprintf( stderr, "libdvdread: Could not open %s\n", path ); 667 fprintf( stderr, "libdvdread: Could not open %s\n", path );
668 }
490 return 0; 669 return 0;
491 } 670 }
492 671
493 void DVDClose( dvd_reader_t *dvd ) 672 void DVDClose( dvd_reader_t *dvd )
494 { 673 {
495 if( dvd ) { 674 if( dvd ) {
496 if( dvd->dev ) dvdinput_close( dvd->dev ); 675 if( dvd->dev ) dvdinput_close( dvd->dev );
497 if( dvd->path_root ) free( dvd->path_root ); 676 if( dvd->path_root ) free( dvd->path_root );
498 if( dvd->udfcache ) FreeUDFCache( dvd->udfcache ); 677 if( dvd->udfcache ) FreeUDFCache( dvd, dvd->udfcache );
678 if(dvd->align) {
679 if(dvd->verbose >= 0) {
680 fprintf(stderr, "libdvdread: DVDClose(): Memory leak in align functions\n");
681 }
682 }
683 dvdinput_free();
499 free( dvd ); 684 free( dvd );
500 } 685 }
686 }
687
688 void DVDInit(void)
689 {
690 dvdinput_setup();
691 }
692
693 void DVDFinish(void)
694 {
695 dvdinput_free();
501 } 696 }
502 697
503 /** 698 /**
504 * Open an unencrypted file on a DVD image file. 699 * Open an unencrypted file on a DVD image file.
505 */ 700 */
540 while( ( ent = readdir( dir ) ) != NULL ) { 735 while( ( ent = readdir( dir ) ) != NULL ) {
541 if( !strcasecmp( ent->d_name, file ) ) { 736 if( !strcasecmp( ent->d_name, file ) ) {
542 sprintf( filename, "%s%s%s", path, 737 sprintf( filename, "%s%s%s", path,
543 ( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ), 738 ( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ),
544 ent->d_name ); 739 ent->d_name );
740 closedir(dir);
545 return 0; 741 return 0;
546 } 742 }
547 } 743 }
548 744 closedir(dir);
549 return -1; 745 return -1;
550 } 746 }
551 747
552 static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename ) 748 static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename )
553 { 749 {
604 memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); 800 memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
605 memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); 801 memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
606 dvd_file->filesize = 0; 802 dvd_file->filesize = 0;
607 803
608 if( stat( full_path, &fileinfo ) < 0 ) { 804 if( stat( full_path, &fileinfo ) < 0 ) {
805 if(dvd->verbose >= 1) {
609 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); 806 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
807 }
610 free( dvd_file ); 808 free( dvd_file );
611 return 0; 809 return 0;
612 } 810 }
613 dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; 811 dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
614 dvd_file->title_devs[ 0 ] = dev; 812 dvd_file->title_devs[ 0 ] = dev;
702 free( dvd_file ); 900 free( dvd_file );
703 return 0; 901 return 0;
704 } 902 }
705 903
706 if( stat( full_path, &fileinfo ) < 0 ) { 904 if( stat( full_path, &fileinfo ) < 0 ) {
905 if(dvd->verbose >= 1) {
707 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); 906 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
907 }
708 free( dvd_file ); 908 free( dvd_file );
709 return 0; 909 return 0;
710 } 910 }
711 dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; 911 dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
712 dvd_file->title_devs[ 0 ] = dev; 912 dvd_file->title_devs[ 0 ] = dev;
720 if( !findDVDFile( dvd, filename, full_path ) ) { 920 if( !findDVDFile( dvd, filename, full_path ) ) {
721 break; 921 break;
722 } 922 }
723 923
724 if( stat( full_path, &fileinfo ) < 0 ) { 924 if( stat( full_path, &fileinfo ) < 0 ) {
925 if(dvd->verbose >= 1) {
725 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); 926 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
927 }
726 break; 928 break;
727 } 929 }
728 930
729 dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; 931 dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
730 dvd_file->title_devs[ i ] = dvdinput_open( full_path ); 932 dvd_file->title_devs[ i ] = dvdinput_open( full_path );
744 dvd_read_domain_t domain ) 946 dvd_read_domain_t domain )
745 { 947 {
746 char filename[ MAX_UDF_FILE_NAME_LEN ]; 948 char filename[ MAX_UDF_FILE_NAME_LEN ];
747 949
748 /* Check arguments. */ 950 /* Check arguments. */
749 if( dvd == NULL || titlenum < 0 ) 951 if( dvd == NULL || titlenum < 0 ) {
952 errno = EINVAL;
750 return NULL; 953 return NULL;
954 }
751 955
752 switch( domain ) { 956 switch( domain ) {
753 case DVD_READ_INFO_FILE: 957 case DVD_READ_INFO_FILE:
754 if( titlenum == 0 ) { 958 if( titlenum == 0 ) {
755 sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" ); 959 sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" );
778 } else { 982 } else {
779 return DVDOpenVOBPath( dvd, titlenum, 0 ); 983 return DVDOpenVOBPath( dvd, titlenum, 0 );
780 } 984 }
781 break; 985 break;
782 default: 986 default:
987 if(dvd->verbose >= 1) {
783 fprintf( stderr, "libdvdread: Invalid domain for file open.\n" ); 988 fprintf( stderr, "libdvdread: Invalid domain for file open.\n" );
989 }
990 errno = EINVAL;
784 return NULL; 991 return NULL;
785 } 992 }
786 993
787 if( dvd->isImageFile ) { 994 if( dvd->isImageFile ) {
788 return DVDOpenFileUDF( dvd, filename ); 995 return DVDOpenFileUDF( dvd, filename );
809 free( dvd_file ); 1016 free( dvd_file );
810 dvd_file = 0; 1017 dvd_file = 0;
811 } 1018 }
812 } 1019 }
813 1020
814 /* Internal, but used from dvd_udf.c */ 1021 /**
1022 * Internal, but used from dvd_udf.c
1023 *
1024 * @param device A read handle.
1025 * @param lb_number Logical block number to start read from.
1026 * @param block_count Number of logical blocks to read.
1027 * @param data Pointer to buffer where read data should be stored.
1028 * This buffer must be large enough to hold lb_number*2048 bytes.
1029 * The pointer must be aligned to the logical block size when
1030 * reading from a raw/O_DIRECT device.
1031 * @param encrypted 0 if no decryption shall be performed,
1032 * 1 if decryption shall be performed
1033 * @param return Returns number of blocks read on success, negative on error
1034 */
815 int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, 1035 int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number,
816 size_t block_count, unsigned char *data, 1036 size_t block_count, unsigned char *data,
817 int encrypted ) 1037 int encrypted )
818 { 1038 {
819 int ret; 1039 int ret;
820 1040
821 if( !device->dev ) { 1041 if( !device->dev ) {
1042 if(device->verbose >= 1) {
822 fprintf( stderr, "libdvdread: Fatal error in block read.\n" ); 1043 fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
1044 }
823 return 0; 1045 return 0;
824 } 1046 }
825 1047
826 ret = dvdinput_seek( device->dev, (int) lb_number ); 1048 ret = dvdinput_seek( device->dev, (int) lb_number );
827 if( ret != (int) lb_number ) { 1049 if( ret != (int) lb_number ) {
828 fprintf( stderr, "libdvdread: Can't seek to block %u\n", lb_number ); 1050 if(device->verbose >= 1) {
1051 fprintf( stderr,
1052 "libdvdread: UDFReadBlocksRaw: Can't seek to block %u\n",
1053 lb_number );
1054 }
829 return 0; 1055 return 0;
830 } 1056 }
831 1057
832 return dvdinput_read( device->dev, (char *) data, 1058 return dvdinput_read( device->dev, (char *) data,
833 (int) block_count, encrypted ); 1059 (int) block_count, encrypted );
834 } 1060 }
835 1061
836 /* This is using a single input and starting from 'dvd_file->lb_start' offset. 1062 /**
1063 * This is using a single input and starting from 'dvd_file->lb_start' offset.
837 * 1064 *
838 * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset' 1065 * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset'
839 * into the buffer located at 'data' and if 'encrypted' is set 1066 * into the buffer located at 'data' and if 'encrypted' is set
840 * descramble the data if it's encrypted. Returning either an 1067 * descramble the data if it's encrypted. Returning either an
841 * negative error or the number of blocks read. */ 1068 * negative error or the number of blocks read.
1069 *
1070 * @param data Pointer to buffer where read data should be placed.
1071 * This buffer must be large enough to hold block_count*2048 bytes.
1072 * The pointer must be aligned to 2048 bytes when reading from
1073 * a raw/O_DIRECT device.
1074 * @return Returns the number of blocks read on success or a negative error.
1075 */
842 static int DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset, 1076 static int DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
843 size_t block_count, unsigned char *data, 1077 size_t block_count, unsigned char *data,
844 int encrypted ) 1078 int encrypted )
845 { 1079 {
846 return UDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset, 1080 return UDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset,
847 block_count, data, encrypted ); 1081 block_count, data, encrypted );
848 } 1082 }
849 1083
850 /* This is using possibly several inputs and starting from an offset of '0'. 1084 /**
851 * 1085 * This is using possibly several inputs and starting from an offset of '0'.
1086 * data must be aligned to logical block size (2048 bytes) of the device
1087 * for raw/O_DIRECT devices to work
852 * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset' 1088 * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset'
853 * into the buffer located at 'data' and if 'encrypted' is set 1089 * into the buffer located at 'data' and if 'encrypted' is set
854 * descramble the data if it's encrypted. Returning either an 1090 * descramble the data if it's encrypted. Returning either an
855 * negative error or the number of blocks read. */ 1091 * negative error or the number of blocks read.
1092 *
1093 * @param dvd_file A file read handle.
1094 * @param offset Block offset from start of file.
1095 * @return Returns number of blocks read on success, negative on error.
1096 */
856 static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset, 1097 static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset,
857 size_t block_count, unsigned char *data, 1098 size_t block_count, unsigned char *data,
858 int encrypted ) 1099 int encrypted )
859 { 1100 {
860 int i; 1101 int i;
867 1108
868 if( offset < dvd_file->title_sizes[ i ] ) { 1109 if( offset < dvd_file->title_sizes[ i ] ) {
869 if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) { 1110 if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
870 off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); 1111 off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset );
871 if( off < 0 || off != (int)offset ) { 1112 if( off < 0 || off != (int)offset ) {
872 fprintf( stderr, "libdvdread: Can't seek to block %d\n", 1113 if(dvd_file->dvd->verbose >= 1) {
1114 fprintf( stderr, "libdvdread: DVDReadBlocksPath1: Can't seek to block %d\n",
873 offset ); 1115 offset );
1116 }
874 return off < 0 ? off : 0; 1117 return off < 0 ? off : 0;
875 } 1118 }
876 ret = dvdinput_read( dvd_file->title_devs[ i ], data, 1119 ret = dvdinput_read( dvd_file->title_devs[ i ], data,
877 (int)block_count, encrypted ); 1120 (int)block_count, encrypted );
878 break; 1121 break;
882 * (This is only true if you try and read >1GB at a time) */ 1125 * (This is only true if you try and read >1GB at a time) */
883 1126
884 /* Read part 1 */ 1127 /* Read part 1 */
885 off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); 1128 off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset );
886 if( off < 0 || off != (int)offset ) { 1129 if( off < 0 || off != (int)offset ) {
887 fprintf( stderr, "libdvdread: Can't seek to block %d\n", 1130 if(dvd_file->dvd->verbose >= 1) {
1131 fprintf( stderr, "libdvdread: DVDReadBlocksPath2: Can't seek to block %d\n",
888 offset ); 1132 offset );
1133 }
889 return off < 0 ? off : 0; 1134 return off < 0 ? off : 0;
890 } 1135 }
891 ret = dvdinput_read( dvd_file->title_devs[ i ], data, 1136 ret = dvdinput_read( dvd_file->title_devs[ i ], data,
892 (int)part1_size, encrypted ); 1137 (int)part1_size, encrypted );
893 if( ret < 0 ) return ret; 1138 if( ret < 0 ) return ret;
898 if( !dvd_file->title_devs[ i + 1 ] ) return ret; 1143 if( !dvd_file->title_devs[ i + 1 ] ) return ret;
899 1144
900 /* Read part 2 */ 1145 /* Read part 2 */
901 off = dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0 ); 1146 off = dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0 );
902 if( off < 0 || off != 0 ) { 1147 if( off < 0 || off != 0 ) {
903 fprintf( stderr, "libdvdread: Can't seek to block %d\n", 1148 if(dvd_file->dvd->verbose >= 1) {
904 0 ); 1149 fprintf( stderr, "libdvdread: DVDReadBlocksPath3: Can't seek to block %d\n", 0 );
1150 }
905 return off < 0 ? off : 0; 1151 return off < 0 ? off : 0;
906 } 1152 }
907 ret2 = dvdinput_read( dvd_file->title_devs[ i + 1 ], 1153 ret2 = dvdinput_read( dvd_file->title_devs[ i + 1 ],
908 data + ( part1_size 1154 data + ( part1_size
909 * (int64_t)DVD_VIDEO_LB_LEN ), 1155 * (int64_t)DVD_VIDEO_LB_LEN ),
918 } 1164 }
919 1165
920 return ret + ret2; 1166 return ret + ret2;
921 } 1167 }
922 1168
923 /* This is broken reading more than 2Gb at a time is ssize_t is 32-bit. */ 1169 /**
1170 * This is broken reading more than 2Gb at a time if ssize_t is 32-bit.
1171 */
924 ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset, 1172 ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
925 size_t block_count, unsigned char *data ) 1173 size_t block_count, unsigned char *data )
926 { 1174 {
927 int ret; 1175 int ret;
928 1176
964 } 1212 }
965 dvd_file->seek_pos = (uint32_t) offset; 1213 dvd_file->seek_pos = (uint32_t) offset;
966 return offset; 1214 return offset;
967 } 1215 }
968 1216
1217 #ifndef HAVE_UINTPTR_T
1218 #warning "Assuming that (unsigned long) can hold (void *)"
1219 typedef unsigned long uintptr_t;
1220 #endif
1221
1222 #define DVD_ALIGN(ptr) (void *)((((uintptr_t)(ptr)) + (DVD_VIDEO_LB_LEN-1)) \
1223 / DVD_VIDEO_LB_LEN * DVD_VIDEO_LB_LEN)
1224
969 ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size ) 1225 ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
970 { 1226 {
971 unsigned char *secbuf; 1227 unsigned char *secbuf_start;
1228 unsigned char *secbuf; //must be aligned to 2048-bytes for raw/O_DIRECT
972 unsigned int numsec, seek_sector, seek_byte; 1229 unsigned int numsec, seek_sector, seek_byte;
973 int ret; 1230 int ret;
974 1231
975 /* Check arguments. */ 1232 /* Check arguments. */
976 if( dvd_file == NULL || data == NULL ) 1233 if( dvd_file == NULL || data == NULL ) {
1234 errno = EINVAL;
977 return -1; 1235 return -1;
978 1236 }
979 seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN; 1237 seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN;
980 seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN; 1238 seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN;
981 1239
982 numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + 1240 numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) +
983 ( ( ( seek_byte + byte_size ) % DVD_VIDEO_LB_LEN ) ? 1 : 0 ); 1241 ( ( ( seek_byte + byte_size ) % DVD_VIDEO_LB_LEN ) ? 1 : 0 );
984 1242
985 secbuf = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN ); 1243 /* must align to 2048 bytes if we are reading from raw/O_DIRECT */
986 if( !secbuf ) { 1244 secbuf_start = (unsigned char *) malloc( (numsec+1) * DVD_VIDEO_LB_LEN );
987 fprintf( stderr, "libdvdread: Can't allocate memory " 1245 if( !secbuf_start ) {
988 "for file read!\n" ); 1246 /* errno will be set to ENOMEM by malloc */
989 return 0; 1247 return -1;
990 } 1248 }
991 1249
1250 secbuf = DVD_ALIGN(secbuf_start);
1251
992 if( dvd_file->dvd->isImageFile ) { 1252 if( dvd_file->dvd->isImageFile ) {
993 ret = DVDReadBlocksUDF( dvd_file, (uint32_t) seek_sector, 1253 ret = DVDReadBlocksUDF( dvd_file, (uint32_t) seek_sector,
994 (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); 1254 (size_t) numsec, secbuf, DVDINPUT_NOFLAGS );
995 } else { 1255 } else {
996 ret = DVDReadBlocksPath( dvd_file, seek_sector, 1256 ret = DVDReadBlocksPath( dvd_file, seek_sector,
997 (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); 1257 (size_t) numsec, secbuf, DVDINPUT_NOFLAGS );
998 } 1258 }
999 1259
1000 if( ret != (int) numsec ) { 1260 if( ret != (int) numsec ) {
1001 free( secbuf ); 1261 free( secbuf_start );
1002 return ret < 0 ? ret : 0; 1262 return ret < 0 ? ret : 0;
1003 } 1263 }
1004 1264
1005 memcpy( data, &(secbuf[ seek_byte ]), byte_size ); 1265 memcpy( data, &(secbuf[ seek_byte ]), byte_size );
1006 free( secbuf ); 1266 free( secbuf_start );
1007 1267
1008 dvd_file->seek_pos += byte_size; 1268 dvd_file->seek_pos += byte_size;
1009 return byte_size; 1269 return byte_size;
1010 } 1270 }
1011 1271
1020 1280
1021 int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid ) 1281 int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid )
1022 { 1282 {
1023 struct md5_ctx ctx; 1283 struct md5_ctx ctx;
1024 int title; 1284 int title;
1025 1285 int nr_of_files = 0;
1286 int tmp_errno;
1287 int nofiles_errno = ENOENT;
1026 /* Check arguments. */ 1288 /* Check arguments. */
1027 if( dvd == NULL || discid == NULL ) 1289 if( dvd == NULL || discid == NULL ) {
1028 return 0; 1290 errno = EINVAL;
1029 1291 return -1;
1292 }
1030 /* Go through the first 10 IFO:s, in order, 1293 /* Go through the first 10 IFO:s, in order,
1031 * and md5sum them, i.e VIDEO_TS.IFO and VTS_0?_0.IFO */ 1294 * and md5sum them, i.e VIDEO_TS.IFO and VTS_0?_0.IFO */
1032 md5_init_ctx( &ctx ); 1295 md5_init_ctx( &ctx );
1033 for( title = 0; title < 10; title++ ) { 1296 for( title = 0; title < 10; title++ ) {
1034 dvd_file_t *dvd_file = DVDOpenFile( dvd, title, DVD_READ_INFO_FILE ); 1297 dvd_file_t *dvd_file = DVDOpenFile( dvd, title, DVD_READ_INFO_FILE );
1035 if( dvd_file != NULL ) { 1298 if( dvd_file != NULL ) {
1036 ssize_t bytes_read; 1299 ssize_t bytes_read;
1037 size_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN; 1300 size_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN;
1038 char *buffer = malloc( file_size ); 1301 char *buffer = malloc( file_size );
1039 1302
1303 nr_of_files++;
1304
1040 if( buffer == NULL ) { 1305 if( buffer == NULL ) {
1041 fprintf( stderr, "libdvdread: DVDDiscId, failed to " 1306 /* errno will be set to ENOMEM by malloc */
1042 "allocate memory for file read!\n" );
1043 return -1; 1307 return -1;
1044 } 1308 }
1309
1045 bytes_read = DVDReadBytes( dvd_file, buffer, file_size ); 1310 bytes_read = DVDReadBytes( dvd_file, buffer, file_size );
1046 if( bytes_read != file_size ) { 1311 if( bytes_read != file_size ) {
1312 tmp_errno = errno;
1313 if(dvd->verbose >= 1) {
1047 fprintf( stderr, "libdvdread: DVDDiscId read returned %d bytes" 1314 fprintf( stderr, "libdvdread: DVDDiscId read returned %d bytes"
1048 ", wanted %d\n", bytes_read, file_size ); 1315 ", wanted %d\n", (int)bytes_read, (int)file_size );
1316 }
1317 free(buffer);
1049 DVDCloseFile( dvd_file ); 1318 DVDCloseFile( dvd_file );
1319 errno = tmp_errno;
1050 return -1; 1320 return -1;
1051 } 1321 }
1052 1322
1053 md5_process_bytes( buffer, file_size, &ctx ); 1323 md5_process_bytes( buffer, file_size, &ctx );
1054 1324
1055 DVDCloseFile( dvd_file ); 1325 DVDCloseFile( dvd_file );
1056 free( buffer ); 1326 free( buffer );
1327 } else {
1328 if(errno != ENOENT) {
1329 nofiles_errno = errno;
1330 }
1057 } 1331 }
1058 } 1332 }
1059 md5_finish_ctx( &ctx, discid ); 1333 md5_finish_ctx( &ctx, discid );
1060 1334 if(nr_of_files == 0) {
1335 errno = nofiles_errno;
1336 return -1;
1337 }
1061 return 0; 1338 return 0;
1062 } 1339 }
1063 1340
1064 1341
1065 int DVDISOVolumeInfo( dvd_reader_t *dvd, 1342 int DVDISOVolumeInfo( dvd_reader_t *dvd,
1066 char *volid, unsigned int volid_size, 1343 char *volid, unsigned int volid_size,
1067 unsigned char *volsetid, unsigned int volsetid_size ) 1344 unsigned char *volsetid, unsigned int volsetid_size )
1068 { 1345 {
1069 unsigned char *buffer; 1346 unsigned char *buffer; /* must be aligned to 2048 for raw/O_DIRECT */
1347 unsigned char *buffer_start;
1070 int ret; 1348 int ret;
1071 1349
1072 /* Check arguments. */ 1350 /* Check arguments. */
1073 if( dvd == NULL ) 1351 if( dvd == NULL ) {
1074 return 0; 1352 errno = EINVAL;
1353 return -1;
1354 }
1075 1355
1076 if( dvd->dev == NULL ) { 1356 if( dvd->dev == NULL ) {
1077 /* No block access, so no ISO... */ 1357 /* No block access, so no ISO... */
1358 errno = EINVAL;
1078 return -1; 1359 return -1;
1079 } 1360 }
1080 1361
1081 buffer = malloc( DVD_VIDEO_LB_LEN ); 1362 buffer_start = malloc( 2 * DVD_VIDEO_LB_LEN );
1082 if( buffer == NULL ) { 1363 if( buffer_start == NULL ) {
1083 fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to "
1084 "allocate memory for file read!\n" );
1085 return -1; 1364 return -1;
1086 } 1365 }
1087 1366
1367 buffer = DVD_ALIGN(buffer_start);
1368
1088 ret = UDFReadBlocksRaw( dvd, 16, 1, buffer, 0 ); 1369 ret = UDFReadBlocksRaw( dvd, 16, 1, buffer, 0 );
1089 if( ret != 1 ) { 1370 if( ret != 1 ) {
1371 if(dvd->verbose >= 1) {
1090 fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " 1372 fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to "
1091 "read ISO9660 Primary Volume Descriptor!\n" ); 1373 "read ISO9660 Primary Volume Descriptor!\n" );
1374 }
1375 free(buffer_start);
1092 return -1; 1376 return -1;
1093 } 1377 }
1094 1378
1095 if( (volid != NULL) && (volid_size > 0) ) { 1379 if( (volid != NULL) && (volid_size > 0) ) {
1096 unsigned int n; 1380 unsigned int n;
1112 if(volsetid_size > 128) { 1396 if(volsetid_size > 128) {
1113 volsetid_size = 128; 1397 volsetid_size = 128;
1114 } 1398 }
1115 memcpy(volsetid, &buffer[190], volsetid_size); 1399 memcpy(volsetid, &buffer[190], volsetid_size);
1116 } 1400 }
1401 free(buffer_start);
1402
1117 return 0; 1403 return 0;
1118 } 1404 }
1119 1405
1120 1406
1121 int DVDUDFVolumeInfo( dvd_reader_t *dvd, 1407 int DVDUDFVolumeInfo( dvd_reader_t *dvd,