~ubuntu-branches/debian/squeeze/mplayer/squeeze

« back to all changes in this revision

Viewing changes to libdvdread4/dvd_reader.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2010-07-31 23:44:52 UTC
  • mfrom: (1.1.4 upstream) (8.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20100731234452-j7yyrgsh1wustazr
Tags: 2:1.0~rc3++final.dfsg1-1
* upload to unstable
* enable mencoder and mplayer-gui package
* build again against the system FFmpeg 0.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
21
 */
22
22
 
 
23
#include "config.h"
 
24
 
23
25
#include <sys/types.h>
24
26
#include <sys/stat.h>
25
27
#include <sys/time.h> /* For the timing of dvdcss_title crack. */
51
53
#define lseek64 _lseeki64
52
54
#endif
53
55
 
54
 
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__) || defined(__APPLE__)
 
56
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__) || defined(__DARWIN__)
55
57
#define SYS_BSD 1
56
58
#endif
57
59
 
303
305
 
304
306
#if defined(SYS_BSD)
305
307
/* FreeBSD /dev/(r)(a)cd0c (a is for atapi), recommended to _not_ use r
306
 
   update: FreeBSD and DragonFly no longer uses the prefix so don't add it.
307
308
   OpenBSD /dev/rcd0c, it needs to be the raw device
308
309
   NetBSD  /dev/rcd0[d|c|..] d for x86, c (for non x86), perhaps others
309
310
   Darwin  /dev/rdisk0,  it needs to be the raw device
310
 
   BSD/OS  /dev/sr0c (if not mounted) or /dev/rsr0c ('c' any letter will do)
311
 
   returns a string allocated with strdup. It should be freed when no longer
312
 
   used. */
 
311
   BSD/OS  /dev/sr0c (if not mounted) or /dev/rsr0c ('c' any letter will do) */
313
312
static char *bsd_block2char( const char *path )
314
313
{
315
 
#if defined(__FreeBSD__) || defined(__DragonFly__)
316
 
  return (char *) strdup( path );
317
 
#else
318
314
  char *new_path;
319
315
 
320
316
  /* If it doesn't start with "/dev/" or does start with "/dev/r" exit */
327
323
  strcat( new_path, path + strlen( "/dev/" ) );
328
324
 
329
325
  return new_path;
330
 
#endif /* __FreeBSD__ || __DragonFly__ */
331
326
}
332
327
#endif
333
328
 
335
330
dvd_reader_t *DVDOpen( const char *ppath )
336
331
{
337
332
  struct stat fileinfo;
338
 
  int ret, have_css, retval, cdir = -1;
 
333
  int ret, have_css;
339
334
  dvd_reader_t *ret_val = NULL;
340
335
  char *dev_name = NULL;
341
 
  char *path = NULL, *new_path = NULL, *path_copy = NULL;
 
336
  char *path;
342
337
 
343
 
#ifdef _WIN32
 
338
#ifdef _MSC_VER
344
339
      int len;
345
340
#endif
346
341
 
347
342
  if( ppath == NULL )
348
 
    goto DVDOpen_error;
 
343
    return 0;
349
344
 
350
345
      path = strdup(ppath);
351
346
  if( path == NULL )
352
 
    goto DVDOpen_error;
 
347
    return 0;
353
348
 
354
349
  /* Try to open libdvdcss or fall back to standard functions */
355
350
  have_css = dvdinput_setup();
356
351
 
357
 
#ifdef _WIN32
 
352
#ifdef _MSC_VER
358
353
  /* Strip off the trailing \ if it is not a drive */
359
354
  len = strlen(path);
360
355
  if ((len > 1) &&
379
374
    /* If we can't stat the file, give up */
380
375
    fprintf( stderr, "libdvdread: Can't stat %s\n", path );
381
376
    perror("");
382
 
    goto DVDOpen_error;
 
377
    free(path);
 
378
    return NULL;
383
379
  }
384
380
 
385
381
  /* First check if this is a block/char device or a file*/
390
386
    /**
391
387
     * Block devices and regular files are assumed to be DVD-Video images.
392
388
     */
393
 
    dvd_reader_t *dvd = NULL;
394
389
#if defined(__sun)
395
 
    dev_name = sun_block2char( path );
 
390
    ret_val = DVDOpenImageFile( sun_block2char( path ), have_css );
396
391
#elif defined(SYS_BSD)
397
 
    dev_name = bsd_block2char( path );
 
392
    ret_val = DVDOpenImageFile( bsd_block2char( path ), have_css );
398
393
#else
399
 
    dev_name = strdup( path );
 
394
    ret_val = DVDOpenImageFile( path, have_css );
400
395
#endif
401
 
    dvd = DVDOpenImageFile( dev_name, have_css );
402
 
    free( dev_name );
 
396
 
403
397
    free(path);
404
 
    return dvd;
 
398
    return ret_val;
 
399
 
405
400
  } else if( S_ISDIR( fileinfo.st_mode ) ) {
406
401
    dvd_reader_t *auth_drive = 0;
 
402
    char *path_copy;
407
403
#if defined(SYS_BSD)
408
404
    struct fstab* fe;
409
405
#elif defined(__sun) || defined(__linux__)
411
407
#endif
412
408
 
413
409
    /* XXX: We should scream real loud here. */
414
 
    if( !(path_copy = strdup( path ) ) )
415
 
      goto DVDOpen_error;
 
410
    if( !(path_copy = strdup( path ) ) ) {
 
411
      free(path);
 
412
      return NULL;
 
413
    }
416
414
 
417
415
#ifndef WIN32 /* don't have fchdir, and getcwd( NULL, ... ) is strange */
418
416
              /* Also WIN32 does not have symlinks, so we don't need this bit of code. */
419
417
 
420
418
    /* Resolve any symlinks and get the absolute dir name. */
421
419
    {
422
 
      if( ( cdir  = open( ".", O_RDONLY ) ) >= 0 ) {
423
 
        if( chdir( path_copy ) == -1 ) {
424
 
          goto DVDOpen_error;
425
 
        }
 
420
      char *new_path;
 
421
      int cdir = open( ".", O_RDONLY );
 
422
 
 
423
      if( cdir >= 0 ) {
 
424
        chdir( path_copy );
426
425
        new_path = malloc(PATH_MAX+1);
427
426
        if(!new_path) {
428
 
          goto DVDOpen_error;
429
 
        }
430
 
        if( getcwd( new_path, PATH_MAX ) == NULL ) {
431
 
          goto DVDOpen_error;
432
 
        }
433
 
        retval = fchdir( cdir );
 
427
          free(path);
 
428
          return NULL;
 
429
        }
 
430
        getcwd(new_path, PATH_MAX );
 
431
        fchdir( cdir );
434
432
        close( cdir );
435
 
        cdir = -1;
436
 
        if( retval == -1 ) {
437
 
          goto DVDOpen_error;
438
 
        }
439
 
        path_copy = new_path;
440
 
        new_path = NULL;
 
433
          free( path_copy );
 
434
          path_copy = new_path;
441
435
      }
442
436
    }
443
437
#endif
514
508
      }
515
509
      fclose( mntfile );
516
510
    }
517
 
#elif defined(_WIN32) || defined(__OS2__)
 
511
#elif defined(_MSC_VER) || defined(__OS2__)
518
512
    auth_drive = DVDOpenImageFile( path, have_css );
519
513
#endif
520
514
 
521
 
#if !defined(_WIN32) && !defined(__OS2__)
 
515
#if !defined(_MSC_VER) && !defined(__OS2__)
522
516
    if( !dev_name ) {
523
517
      fprintf( stderr, "libdvdread: Couldn't find device name.\n" );
524
518
    } else if( !auth_drive ) {
533
527
#endif
534
528
 
535
529
    free( dev_name );
536
 
    dev_name = NULL;
537
530
    free( path_copy );
538
 
    path_copy = NULL;
539
531
 
540
532
    /**
541
533
     * If we've opened a drive, just use that.
552
544
      return ret_val;
553
545
  }
554
546
 
555
 
DVDOpen_error:
556
547
  /* If it's none of the above, screw it. */
557
548
  fprintf( stderr, "libdvdread: Could not open %s\n", path );
558
 
  if( path != NULL )
559
549
    free( path );
560
 
  if ( path_copy != NULL )
561
 
    free( path_copy );
562
 
  if ( cdir >= 0 )
563
 
    close( cdir );
564
 
  if ( new_path != NULL )
565
 
    free( new_path );
566
550
  return NULL;
567
551
}
568
552
 
890
874
  int i;
891
875
 
892
876
  if( dvd_file ) {
893
 
    if( !dvd_file->dvd->isImageFile ) {
 
877
    if( dvd_file->dvd->isImageFile ) {
 
878
      ;
 
879
    } else {
894
880
      for( i = 0; i < TITLES_MAX; ++i ) {
895
881
        if( dvd_file->title_devs[ i ] ) {
896
882
          dvdinput_close( dvd_file->title_devs[i] );
903
889
  }
904
890
}
905
891
 
906
 
static int DVDFileStatVOBUDF( dvd_reader_t *dvd, int title,
907
 
                              int menu, dvd_stat_t *statbuf )
908
 
{
909
 
  char filename[ MAX_UDF_FILE_NAME_LEN ];
910
 
  uint32_t size;
911
 
  off_t tot_size;
912
 
  off_t parts_size[ 9 ];
913
 
  int nr_parts = 0;
914
 
  int n;
915
 
 
916
 
  if( title == 0 )
917
 
    sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
918
 
  else
919
 
    sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
920
 
 
921
 
  if( !UDFFindFile( dvd, filename, &size ) )
922
 
    return -1;
923
 
 
924
 
  tot_size = size;
925
 
  nr_parts = 1;
926
 
  parts_size[ 0 ] = size;
927
 
 
928
 
  if( !menu ) {
929
 
    int cur;
930
 
 
931
 
    for( cur = 2; cur < 10; cur++ ) {
932
 
      sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
933
 
      if( !UDFFindFile( dvd, filename, &size ) )
934
 
        break;
935
 
 
936
 
      parts_size[ nr_parts ] = size;
937
 
      tot_size += size;
938
 
      nr_parts++;
939
 
    }
940
 
  }
941
 
 
942
 
  statbuf->size = tot_size;
943
 
  statbuf->nr_parts = nr_parts;
944
 
  for( n = 0; n < nr_parts; n++ )
945
 
    statbuf->parts_size[ n ] = parts_size[ n ];
946
 
 
947
 
  return 0;
948
 
}
949
 
 
950
 
 
951
 
static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title,
952
 
                               int menu, dvd_stat_t *statbuf )
953
 
{
954
 
  char filename[ MAX_UDF_FILE_NAME_LEN ];
955
 
  char full_path[ PATH_MAX + 1 ];
956
 
  struct stat fileinfo;
957
 
  off_t tot_size;
958
 
  off_t parts_size[ 9 ];
959
 
  int nr_parts = 0;
960
 
  int n;
961
 
 
962
 
  if( title == 0 )
963
 
    sprintf( filename, "VIDEO_TS.VOB" );
964
 
  else
965
 
    sprintf( filename, "VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
966
 
 
967
 
  if( !findDVDFile( dvd, filename, full_path ) )
968
 
    return -1;
969
 
 
970
 
  if( stat( full_path, &fileinfo ) < 0 ) {
971
 
    fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
972
 
    return -1;
973
 
  }
974
 
 
975
 
  tot_size = fileinfo.st_size;
976
 
  nr_parts = 1;
977
 
  parts_size[ 0 ] = fileinfo.st_size;
978
 
 
979
 
  if( !menu ) {
980
 
    int cur;
981
 
    for( cur = 2; cur < 10; cur++ ) {
982
 
      sprintf( filename, "VTS_%02d_%d.VOB", title, cur );
983
 
      if( !findDVDFile( dvd, filename, full_path ) )
984
 
        break;
985
 
 
986
 
      if( stat( full_path, &fileinfo ) < 0 ) {
987
 
        fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
988
 
        break;
989
 
      }
990
 
 
991
 
      parts_size[ nr_parts ] = fileinfo.st_size;
992
 
      tot_size += parts_size[ nr_parts ];
993
 
      nr_parts++;
994
 
    }
995
 
  }
996
 
 
997
 
  statbuf->size = tot_size;
998
 
  statbuf->nr_parts = nr_parts;
999
 
  for( n = 0; n < nr_parts; n++ )
1000
 
    statbuf->parts_size[ n ] = parts_size[ n ];
1001
 
 
1002
 
  return 0;
1003
 
}
1004
 
 
1005
 
 
1006
 
int DVDFileStat( dvd_reader_t *dvd, int titlenum,
1007
 
                 dvd_read_domain_t domain, dvd_stat_t *statbuf )
1008
 
{
1009
 
  char filename[ MAX_UDF_FILE_NAME_LEN ];
1010
 
  char full_path[ PATH_MAX + 1 ];
1011
 
  struct stat fileinfo;
1012
 
  uint32_t size;
1013
 
 
1014
 
  /* Check arguments. */
1015
 
  if( dvd == NULL || titlenum < 0 ) {
1016
 
    errno = EINVAL;
1017
 
    return -1;
1018
 
  }
1019
 
 
1020
 
  switch( domain ) {
1021
 
  case DVD_READ_INFO_FILE:
1022
 
    if( titlenum == 0 )
1023
 
      sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" );
1024
 
    else
1025
 
      sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum );
1026
 
 
1027
 
    break;
1028
 
  case DVD_READ_INFO_BACKUP_FILE:
1029
 
    if( titlenum == 0 )
1030
 
      sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" );
1031
 
    else
1032
 
      sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum );
1033
 
 
1034
 
    break;
1035
 
  case DVD_READ_MENU_VOBS:
1036
 
    if( dvd->isImageFile )
1037
 
      return DVDFileStatVOBUDF( dvd, titlenum, 1, statbuf );
1038
 
    else
1039
 
      return DVDFileStatVOBPath( dvd, titlenum, 1, statbuf );
1040
 
 
1041
 
    break;
1042
 
  case DVD_READ_TITLE_VOBS:
1043
 
    if( titlenum == 0 )
1044
 
      return -1;
1045
 
 
1046
 
    if( dvd->isImageFile )
1047
 
      return DVDFileStatVOBUDF( dvd, titlenum, 0, statbuf );
1048
 
    else
1049
 
      return DVDFileStatVOBPath( dvd, titlenum, 0, statbuf );
1050
 
 
1051
 
    break;
1052
 
  default:
1053
 
    fprintf( stderr, "libdvdread: Invalid domain for file stat.\n" );
1054
 
    errno = EINVAL;
1055
 
    return -1;
1056
 
  }
1057
 
 
1058
 
  if( dvd->isImageFile ) {
1059
 
    if( UDFFindFile( dvd, filename, &size ) ) {
1060
 
      statbuf->size = size;
1061
 
      statbuf->nr_parts = 1;
1062
 
      statbuf->parts_size[ 0 ] = size;
1063
 
      return 0;
1064
 
    }
1065
 
  } else {
1066
 
    if( findDVDFile( dvd, filename, full_path ) ) {
1067
 
      if( stat( full_path, &fileinfo ) < 0 )
1068
 
        fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
1069
 
      else {
1070
 
        statbuf->size = fileinfo.st_size;
1071
 
        statbuf->nr_parts = 1;
1072
 
        statbuf->parts_size[ 0 ] = statbuf->size;
1073
 
        return 0;
1074
 
      }
1075
 
    }
1076
 
  }
1077
 
  return -1;
1078
 
}
1079
 
 
1080
892
/* Internal, but used from dvd_udf.c */
1081
893
int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number,
1082
894
                      size_t block_count, unsigned char *data,