Removed Cosmetics, changed indentation to be "tighter" but kept Free call.




--
Jorgen Lundman       | <[email protected]>
Unix Administrator   | +81 (0)3 -5456-2687 ext 1017 (work)
Shibuya-ku, Tokyo    | +81 (0)90-5578-8500          (cell)
Japan                | +81 (0)3 -3375-1767          (home)
Index: src/dvd_reader.c
===================================================================
--- src/dvd_reader.c    (revision 1181)
+++ src/dvd_reader.c    (working copy)
@@ -100,7 +100,7 @@
   int css_title;
 
   /* Information required for an image file. */
-  uint32_t lb_start;
+  udf_file_t *udf_file;
   uint32_t seek_pos;
 
   /* Information required for a directory path drive. */
@@ -163,7 +163,8 @@
   struct timeval all_s, all_e;
   struct timeval t_s, t_e;
   char filename[ MAX_UDF_FILE_NAME_LEN ];
-  uint32_t start, len;
+  uint32_t len;
+  udf_file_t *udf_file;
   int title;
 
   char *nokeys_str = getenv("DVDREAD_NOKEYS");
@@ -183,31 +184,33 @@
     } else {
       sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 );
     }
-    start = UDFFindFile( dvd, filename, &len );
-    if( start != 0 && len != 0 ) {
+    udf_file = UDFFindFile( dvd, filename, &len );
+    if( udf_file != NULL && 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);
+               filename,  UDFFileBlockPos(udf_file, 0) );
+      if( dvdinput_title( dvd->dev, (int)UDFFileBlockPos(udf_file, 0) ) < 0 ) {
+        fprintf( stderr, "libdvdread: Error cracking CSS key for %s 
(0x%08x)\n", filename, UDFFileBlockPos(udf_file, 0));
       }
       gettimeofday( &t_e, NULL );
       fprintf( stderr, "libdvdread: Elapsed time %ld\n",
                (long int) t_e.tv_sec - t_s.tv_sec );
     }
 
+    UDFFreeFile(dvd, udf_file); udf_file = NULL;
+
     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;
+    udf_file = UDFFindFile( dvd, filename, &len );
+    if( udf_file == NULL || 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);
+             filename, UDFFileBlockPos(udf_file, 0) );
+    if( dvdinput_title( dvd->dev, (int)UDFFileBlockPos(udf_file, 0) ) < 0 ) {
+      fprintf( stderr, "libdvdread: Error cracking CSS key for %s 
(0x%08x)!!\n", filename, UDFFileBlockPos(udf_file, 0));
     }
     gettimeofday( &t_e, NULL );
     fprintf( stderr, "libdvdread: Elapsed time %ld\n",
@@ -220,6 +223,8 @@
   fprintf( stderr, "libdvdread: Elapsed time %ld\n",
            (long int) all_e.tv_sec - all_s.tv_sec );
 
+  UDFFreeFile(dvd, udf_file); udf_file = NULL;
+
   return 0;
 }
 
@@ -587,22 +592,24 @@
  */
 static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename )
 {
-  uint32_t start, len;
+  uint32_t len;
+  udf_file_t *udf_file;
   dvd_file_t *dvd_file;
 
-  start = UDFFindFile( dvd, filename, &len );
-  if( !start ) {
+  udf_file = UDFFindFile( dvd, filename, &len );
+  if( !udf_file ) {
     fprintf( stderr, "libdvdnav:DVDOpenFileUDF:UDFFindFile %s failed\n", 
filename );
     return NULL;
   }
 
   dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
   if( !dvd_file ) {
+    UDFFreeFile(dvd, udf_file);
     fprintf( stderr, "libdvdnav:DVDOpenFileUDF:malloc failed\n" );
     return NULL;
   }
   dvd_file->dvd = dvd;
-  dvd_file->lb_start = start;
+  dvd_file->udf_file = udf_file;
   dvd_file->seek_pos = 0;
   memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
   memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
@@ -698,7 +705,7 @@
     return NULL;
   }
   dvd_file->dvd = dvd;
-  dvd_file->lb_start = 0;
+  dvd_file->udf_file = NULL;
   dvd_file->seek_pos = 0;
   memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
   memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
@@ -719,7 +726,8 @@
 static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu )
 {
   char filename[ MAX_UDF_FILE_NAME_LEN ];
-  uint32_t start, len;
+  uint32_t len;
+  udf_file_t *udf_file;
   dvd_file_t *dvd_file;
 
   if( title == 0 ) {
@@ -727,18 +735,22 @@
   } else {
     sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
   }
-  start = UDFFindFile( dvd, filename, &len );
-  if( start == 0 ) return NULL;
+  udf_file = UDFFindFile( dvd, filename, &len );
+  if( udf_file == NULL ) return NULL;
 
   dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
-  if( !dvd_file ) return NULL;
+  if( !dvd_file ) {
+    UDFFreeFile(dvd, udf_file);
+    return NULL;
+  }
   dvd_file->dvd = dvd;
   /*Hack*/ dvd_file->css_title = title << 1 | menu;
-  dvd_file->lb_start = start;
+  dvd_file->udf_file = udf_file;
   dvd_file->seek_pos = 0;
   memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
   memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
   dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
+  udf_file = NULL;
 
   /* Calculate the complete file size for every file in the VOBS */
   if( !menu ) {
@@ -746,7 +758,8 @@
 
     for( cur = 2; cur < 10; cur++ ) {
       sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
-      if( !UDFFindFile( dvd, filename, &len ) ) break;
+      if( !(udf_file = UDFFindFile( dvd, filename, &len )) ) break;
+      UDFFreeFile(dvd, udf_file);
       dvd_file->filesize += len / DVD_VIDEO_LB_LEN;
     }
   }
@@ -777,7 +790,7 @@
   if( !dvd_file ) return NULL;
   dvd_file->dvd = dvd;
   /*Hack*/ dvd_file->css_title = title << 1 | menu;
-  dvd_file->lb_start = 0;
+  dvd_file->udf_file = NULL;
   dvd_file->seek_pos = 0;
   memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
   memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
@@ -904,6 +917,8 @@
       }
     }
 
+    if( dvd_file->udf_file ) UDFFreeFile( dvd_file->dvd, dvd_file->udf_file );
+
     free( dvd_file );
     dvd_file = 0;
   }
@@ -918,14 +933,16 @@
   off_t parts_size[ 9 ];
   int nr_parts = 0;
   int n;
+  udf_file_t *udf_file;
 
   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 ) )
+  if( !(udf_file = UDFFindFile( dvd, filename, &size ) ) )
     return -1;
+  UDFFreeFile(dvd, udf_file);
 
   tot_size = size;
   nr_parts = 1;
@@ -936,8 +953,9 @@
 
     for( cur = 2; cur < 10; cur++ ) {
       sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
-      if( !UDFFindFile( dvd, filename, &size ) )
+      if( !(udf_file = UDFFindFile( dvd, filename, &size ) ) )
         break;
+      UDFFreeFile(dvd, udf_file);
 
       parts_size[ nr_parts ] = size;
       tot_size += size;
@@ -1016,6 +1034,7 @@
   char full_path[ PATH_MAX + 1 ];
   struct stat fileinfo;
   uint32_t size;
+  udf_file_t *udf_file;
 
   /* Check arguments. */
   if( dvd == NULL || titlenum < 0 ) {
@@ -1062,10 +1081,11 @@
   }
 
   if( dvd->isImageFile ) {
-    if( UDFFindFile( dvd, filename, &size ) ) {
+    if( (udf_file = UDFFindFile( dvd, filename, &size ) ) ) {
       statbuf->size = size;
       statbuf->nr_parts = 1;
       statbuf->parts_size[ 0 ] = size;
+      UDFFreeFile(dvd, udf_file);
       return 0;
     }
   } else {
@@ -1116,7 +1136,8 @@
                              size_t block_count, unsigned char *data,
                              int encrypted )
 {
-  return UDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset,
+  return UDFReadBlocksRaw( dvd_file->dvd,
+                           UDFFileBlockPos(dvd_file->udf_file, offset),
                            block_count, data, encrypted );
 }
 
@@ -1208,11 +1229,11 @@
   if( dvd_file->dvd->css_title != dvd_file->css_title ) {
     dvd_file->dvd->css_title = dvd_file->css_title;
     if( dvd_file->dvd->isImageFile ) {
-      dvdinput_title( dvd_file->dvd->dev, (int)dvd_file->lb_start );
+      dvdinput_title( dvd_file->dvd->dev, 
(int)UDFFileBlockPos(dvd_file->udf_file, 0) );
     }
     /* Here each vobu has it's own dvdcss handle, so no need to update
     else {
-      dvdinput_title( dvd_file->title_devs[ 0 ], (int)dvd_file->lb_start );
+      dvdinput_title( dvd_file->title_devs[ 0 ], 
(int)UDFFileBlockPos(dvd_file->udf_file, 0) );
     }*/
   }
 
Index: src/dvd_udf.c
===================================================================
--- src/dvd_udf.c       (revision 1181)
+++ src/dvd_udf.c       (working copy)
@@ -93,6 +93,13 @@
   uint16_t Partition;
 };
 
+struct UDF_FILE {
+  uint64_t Length;
+  uint32_t num_AD;
+  uint32_t Partition_Start;
+  struct AD AD_chain[UDF_MAX_AD_CHAINS];
+};
+
 struct extent_ad {
   uint32_t location;
   uint32_t length;
@@ -117,7 +124,7 @@
 
 struct icbmap {
   uint32_t lbn;
-  struct AD file;
+  udf_file_t file;
   uint8_t filetype;
 };
 
@@ -327,6 +334,14 @@
                   | ((uint32_t)data[(p) + 1] << 8)      \
                   | ((uint32_t)data[(p) + 2] << 16)     \
                   | ((uint32_t)data[(p) + 3] << 24))
+#define GETN8(p) ((uint64_t)data[p]                 \
+                  | ((uint64_t)data[(p) + 1] << 8)  \
+                  | ((uint64_t)data[(p) + 2] << 16) \
+                  | ((uint64_t)data[(p) + 3] << 24) \
+                  | ((uint64_t)data[(p) + 4] << 32) \
+                  | ((uint64_t)data[(p) + 5] << 40) \
+                  | ((uint64_t)data[(p) + 6] << 48) \
+                  | ((uint64_t)data[(p) + 7] << 56))
 /* This is wrong with regard to endianess */
 #define GETN(p, n, target) memcpy(target, &data[p], n)
 
@@ -427,7 +442,7 @@
 }
 
 static int UDFFileEntry( uint8_t *data, uint8_t *FileType,
-                         struct Partition *partition, struct AD *ad )
+                         struct Partition *partition, udf_file_t *fad )
 {
   uint16_t flags;
   uint32_t L_EA, L_AD;
@@ -436,15 +451,22 @@
   UDFICB( &data[ 16 ], FileType, &flags );
 
   /* Init ad for an empty file (i.e. there isn't a AD, L_AD == 0 ) */
-  ad->Length = GETN4( 60 ); /* Really 8 bytes a 56 */
-  ad->Flags = 0;
-  ad->Location = 0; /* what should we put here?  */
-  ad->Partition = partition->Number; /* use number of current partition */
+  fad->Length = GETN8( 56 ); /* Really 8 bytes at 56 */
 
   L_EA = GETN4( 168 );
   L_AD = GETN4( 172 );
   p = 176 + L_EA;
+  fad->num_AD = 0;
   while( p < 176 + L_EA + L_AD ) {
+    struct AD *ad;
+
+    if (fad->num_AD >= UDF_MAX_AD_CHAINS) return 0;
+
+    ad =  &fad->AD_chain[fad->num_AD];
+    ad->Partition = partition->Number;
+    ad->Flags = 0;
+    fad->num_AD++;
+
     switch( flags & 0x0007 ) {
     case 0:
       UDFShortAD( &data[ p ], ad, partition );
@@ -503,7 +525,7 @@
  * return 1 on success, 0 on error;
  */
 static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType,
-                      struct Partition *partition, struct AD *File )
+                      struct Partition *partition, udf_file_t *File )
 {
   uint8_t LogBlock_base[DVD_VIDEO_LB_LEN + 2048];
   uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & 
~((uintptr_t)2047)) + 2048);
@@ -539,12 +561,12 @@
 }
 
 /**
- * Dir: Location of directory to scan
+ * Dir: Location of directory to scan (This is not a struct-ptr, so not ANSI C)
  * FileName: Name of file to look for
  * FileICB: Location of ICB of the found file
  * return 1 on success, 0 on error;
  */
-static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
+static int UDFScanDir( dvd_reader_t *device, udf_file_t Dir, char *FileName,
                        struct Partition *partition, struct AD *FileICB,
                        int cache_file_info)
 {
@@ -562,13 +584,13 @@
   int in_cache = 0;
 
   /* Scan dir for ICB of file */
-  lbnum = partition->Start + Dir.Location;
+  lbnum = partition->Start + Dir.AD_chain[0].Location;
 
   if(DVDUDFCacheLevel(device, -1) > 0) {
     /* caching */
 
     if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) {
-      dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN;
+      dir_lba = (Dir.AD_chain[0].Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN;
       if((cached_dir_base = malloc(dir_lba * DVD_VIDEO_LB_LEN + 2048)) == NULL)
         return 0;
       cached_dir = (uint8_t *)(((uintptr_t)cached_dir_base & 
~((uintptr_t)2047)) + 2048);
@@ -596,15 +618,17 @@
 
     p = 0;
 
-    while( p < Dir.Length ) {
+    while( p < Dir.AD_chain[0].Length ) {
       UDFDescriptor( &cached_dir[ p ], &TagID );
       if( TagID == 257 ) {
         p += UDFFileIdentifier( &cached_dir[ p ], &filechar,
                                 filename, &tmpICB );
         if(cache_file_info && !in_cache) {
           uint8_t tmpFiletype;
-          struct AD tmpFile;
+          udf_file_t tmpFile;
 
+          memset(&tmpFile, 0, sizeof(tmpFile));
+
           if( !strcasecmp( FileName, filename ) ) {
             memcpy(FileICB, &tmpICB, sizeof(tmpICB));
             found = 1;
@@ -631,11 +655,11 @@
     return 0;
 
   p = 0;
-  while( p < Dir.Length ) {
+  while( p < Dir.AD_chain[0].Length ) {
     if( p > DVD_VIDEO_LB_LEN ) {
       ++lbnum;
       p -= DVD_VIDEO_LB_LEN;
-      Dir.Length -= DVD_VIDEO_LB_LEN;
+      Dir.AD_chain[0].Length -= DVD_VIDEO_LB_LEN;
       if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
         return 0;
       }
@@ -782,7 +806,58 @@
   return part->valid;
 }
 
-uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
+
+/*
+ * Release a UDF file descriptor
+ */
+void UDFFreeFile(dvd_reader_t *device, udf_file_t *File)
+{
+  free(File);
+}
+
+
+/*
+ * The API users will refer to block 0 as start of file and going up
+ * we need to convert that to actual disk block; partition_start +
+ * file_start + offset, but keep in mind that file_start is chained,
+ * and not contiguous.
+ *
+ * We return "0" as error, since a File can not start at physical block 0
+ *
+ * It is perhaps unfortunate that Location is in blocks, but Length is
+ * in bytes..? Can bytes be uneven blocksize in the middle of a chain?
+ *
+ */
+uint32_t UDFFileBlockPos(udf_file_t *File, uint32_t file_block)
+{
+  uint32_t result, i, offset;
+
+  if (!File) return 0;
+
+  /* Look through the chain to see where this block would belong. */
+  for (i = 0, offset = 0; i < File->num_AD; i++) {
+    /* Is "file_block" inside this chain? Then use this chain. */
+    if (file_block < (offset +
+                      (File->AD_chain[i].Length /  DVD_VIDEO_LB_LEN))) break;
+    offset += (File->AD_chain[i].Length /  DVD_VIDEO_LB_LEN);
+  }
+
+  /* If it is not defined in the AD chains, we should return an error, but
+   * in the interest of being backward (in)compatible with the original
+   * libdvdread, we revert back to the traditional view that UDF file are
+   * one contiguous long chain, in case some API software out there relies on
+   * this incorrect behavior.
+   */
+  if (i >= File->num_AD) i = 0;
+
+  result = File->Partition_Start + File->AD_chain[i].Location + file_block - 
offset;
+  return result;
+}
+
+
+
+
+udf_file_t *UDFFindFile( dvd_reader_t *device, char *filename,
                       uint32_t *filesize )
 {
   uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ];
@@ -790,11 +865,12 @@
   uint32_t lbnum;
   uint16_t TagID;
   struct Partition partition;
-  struct AD RootICB, File, ICB;
+  struct AD RootICB, ICB;
+  udf_file_t File, *result;
   char tokenline[ MAX_UDF_FILE_NAME_LEN ];
   char *token;
   uint8_t filetype;
-
+  memset(&File, 0, sizeof(File));
   *filesize = 0;
   tokenline[0] = '\0';
   strncat(tokenline, filename, MAX_UDF_FILE_NAME_LEN - 1);
@@ -822,17 +898,17 @@
 
     /* Sanity checks. */
     if( TagID != 256 )
-      return 0;
+      return NULL;
     if( RootICB.Partition != 0 )
-      return 0;
+      return NULL;
     SetUDFCache(device, RootICBCache, 0, &RootICB);
   }
 
   /* Find root dir */
   if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) )
-    return 0;
+    return NULL;
   if( filetype != 4 )
-    return 0;  /* Root dir should be dir */
+    return NULL;  /* Root dir should be dir */
   {
     int cache_file_info = 0;
     /* Tokenize filepath */
@@ -841,9 +917,9 @@
     while( token != NULL ) {
       if( !UDFScanDir( device, File, token, &partition, &ICB,
                        cache_file_info))
-        return 0;
+        return NULL;
       if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) )
-        return 0;
+        return NULL;
       if(!strcmp(token, "VIDEO_TS"))
         cache_file_info = 1;
       token = strtok( NULL, "/" );
@@ -851,14 +927,23 @@
   }
 
   /* Sanity check. */
-  if( File.Partition != 0 )
-    return 0;
+  if( File.AD_chain[0].Partition != 0 )
+    return NULL;
   *filesize = File.Length;
   /* Hack to not return partition.Start for empty files. */
-  if( !File.Location )
-    return 0;
-  else
-    return partition.Start + File.Location;
+  if( !File.AD_chain[0].Location )
+    return NULL;
+
+  // Allocate a UDF_FILE node for the API user
+  result = (udf_file_t *) malloc(sizeof(*result));
+  if (!result) return NULL;
+
+  // Copy over the information
+  memcpy(result, &File, sizeof(*result));
+
+  result->Partition_Start = partition.Start;
+
+  return result;
 }
 
 
Index: src/dvdread/dvd_udf.h
===================================================================
--- src/dvdread/dvd_udf.h       (revision 1181)
+++ src/dvdread/dvd_udf.h       (working copy)
@@ -39,6 +39,32 @@
 extern "C" {
 #endif
 
+
+
+/*
+ *
+ * UDF defines struct AD, which dvdread unfortunately overloads to refer to
+ * a file, creating problems with chained ADs. We need to define a generic
+ * UDF_FILE structure to hold the information required.
+ * It could be worth a separate struct for Directories, since they are 
(probably)
+ * only ever in 1 chain.
+ *
+ * Is there a real max number of chains? What can fit in 2048?
+ * My 4.4GB file example uses 5 chains. A BD ISO can store 50GB of data, so
+ * potentially we could have a 50GB file, so we would need to be able to
+ * support 62 chains.
+ *
+ */
+
+#ifndef UDF_MAX_AD_CHAINS     // Allow MAX to be increased by API.
+#define UDF_MAX_AD_CHAINS 50
+#endif
+
+
+typedef struct UDF_FILE udf_file_t;
+
+
+
 /**
  * Looks for a file on the UDF disc/imagefile and returns the block number
  * where it begins, or 0 if it is not found.  The filename should be an
@@ -46,8 +72,9 @@
  * '/VIDEO_TS/VTS_01_1.IFO'.  On success, filesize will be set to the size of
  * the file in bytes.
  */
-uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *size );
-
+udf_file_t *UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *size 
);
+void        UDFFreeFile( dvd_reader_t *device, udf_file_t *udf_file );
+uint32_t    UDFFileBlockPos( udf_file_t *udf_file, uint32_t file_block);
 void FreeUDFCache(void *cache);
 int UDFGetVolumeIdentifier(dvd_reader_t *device,
                            char *volid, unsigned int volid_size);
_______________________________________________
DVDnav-discuss mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/dvdnav-discuss

Reply via email to