This patch adds the ability to search any UDF filesystem by regular
names and methods. It introduces POSIX style
opendir()/readdir()/closedir() methods to iterate directory contents.
This allows for complete navigation of UDF filesystem.
This is required to be able to read UDF2.50 file systems, to read files
in say STREAM/00001.m2ts
Example output:
./disc_info example-bd5.iso
libdvdread: Encrypted DVD support unavailable.
/BDMV: . (type 3) size 152
/BDMV: AUXDATA (type 3) size 40
/BDMV: BACKUP (type 3) size 332
/BDMV: BDJO (type 3) size 40
/BDMV: CLIPINF (type 3) size 100
/BDMV: index.bdmv (type 5) size 526
/BDMV: JAR (type 3) size 40
/BDMV: META (type 3) size 40
/BDMV: MovieObject.bdmv (type 5) size 278
/BDMV: PLAYLIST (type 3) size 100
/BDMV: STREAM (type 3) size 100
/BDMV/STREAM: 00001.m2ts (type 4)
Openfile said 0x1004d0
Size 4691957760
Lund
--
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)
diff -ruib ../../versions/libdvdread_patch3/libdvdread/src/dvd_reader.c
./dvd_reader.c
--- ../../versions/libdvdread_patch3/libdvdread/src/dvd_reader.c
2008-10-10 17:20:20.000000000 +0900
+++ ./dvd_reader.c 2008-10-10 17:32:13.000000000 +0900
@@ -592,6 +592,7 @@
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) {
fprintf( stderr, "libdvdnav:DVDOpenFileUDF:malloc failed\n" );
+ UDFFreeFile(dvd, udf_file);
return NULL;
}
dvd_file->dvd = dvd;
@@ -1356,6 +1357,8 @@
char *buffer_base = malloc( file_size + 2048 );
char *buffer = (char *)(((uintptr_t)buffer_base & ~((uintptr_t)2047)) +
2048);
+ dvd_file->udf_file = NULL;
+
if( buffer_base == NULL ) {
DVDCloseFile( dvd_file );
fprintf( stderr, "libdvdread: DVDDiscId, failed to "
@@ -1476,3 +1479,102 @@
return 0;
}
+
+/**
+ * opendir(3)-like function for traversing a UDF image.
+ *
+ * dvd_dir_t *DVDOpenDir( dvd_reader_t *dvd, char *subdir )
+ *
+ * Opens "subdir" directory for traversal. Returns NULL for failure
+ * or a valid dvd_dir_t * otherwise.
+ *
+ * This function differs from POSIX in that it must also be passed
+ * the dvd_reader_t *.
+ *
+ */
+dvd_dir_t *DVDOpenDir( dvd_reader_t *dvd, char *subdir )
+{
+ UDF_FILE udf_file;
+ uint64_t filesize;
+ dvd_dir_t *result;
+
+ udf_file = UDFFindFile( dvd, subdir, &filesize );
+
+ if (!udf_file) return NULL;
+
+#ifdef DEBUG
+ fprintf(stdout, "Found '%s' at %d (size %"PRIu64")\n", subdir,
+ UDFFileBlockPos(udf_file, 0), filesize);
+#endif
+
+ result = (dvd_dir_t *)malloc(sizeof(*result));
+ if (!result) {
+ UDFFreeFile(dvd, udf_file);
+ return NULL;
+ }
+
+ memset(result, 0, sizeof(*result));
+
+ result->dir_location = UDFFileBlockPos(udf_file, 0);
+ result->dir_current = UDFFileBlockPos(udf_file, 0);
+ result->dir_length = filesize;
+ UDFFreeFile(dvd, udf_file);
+
+ return result;
+}
+
+
+/**
+ * readdir(3)-like function for traversing a UDF image.
+ *
+ * This function differs from POSIX in that it must also be passed
+ * the dvd_reader_t *.
+ *
+ */
+dvd_dirent_t *DVDReadDir( dvd_reader_t *dvd, dvd_dir_t *dirp )
+{
+
+ if (!UDFScanDirX(dvd, dirp)) {
+ dirp->current_p = 0;
+ dirp->dir_current = dirp->dir_location; // this is a rewind, wanted?
+ return NULL;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "DVDReadDir(%s)\r\n", dirp->entry.d_name);
+#endif
+
+ return &dirp->entry;
+
+}
+
+/**
+ * closedir(3)-like function for traversing a UDF image.
+ *
+ * This function differs from POSIX in that it must also be passed
+ * the dvd_reader_t *.
+ *
+ */
+
+int DVDCloseDir( dvd_reader_t *dvd, dvd_dir_t *dirp )
+{
+ if (!dirp) return 0;
+
+ free(dirp);
+
+ return 0;
+
+}
+
+/**
+ * Nearly identical function to DVDOpenFile, but instead of mapping
+ * DVD domain and title, this takes an actual filename to open.
+ */
+dvd_file_t *DVDOpenFilename( dvd_reader_t *dvd, char *filename)
+{
+ if( dvd->isImageFile ) {
+ return DVDOpenFileUDF( dvd, filename );
+ } else {
+ return DVDOpenFilePath( dvd, filename );
+ }
+}
diff -ruib ../../versions/libdvdread_patch3/libdvdread/src/dvd_reader.h
./dvd_reader.h
--- ../../versions/libdvdread_patch3/libdvdread/src/dvd_reader.h
2008-10-10 17:19:36.000000000 +0900
+++ ./dvd_reader.h 2008-10-10 17:23:46.000000000 +0900
@@ -125,6 +125,47 @@
off_t parts_size[9]; /**< Size of each part in bytes */
} dvd_stat_t;
+/*
+ * DVDReaddir entry types.
+ */
+typedef enum {
+ DVD_DT_UNKNOWN = 0,
+ DVD_DT_FIFO,
+ DVD_DT_CHR,
+ DVD_DT_DIR,
+ DVD_DT_BLK,
+ DVD_DT_REG,
+ DVD_DT_LNK,
+ DVD_DT_SOCK,
+ DVD_DT_WHT
+} dvd_dir_type_t;
+
+/*
+ * DVDReaddir structure.
+ * Extended a little from POSIX to also return filesize.
+ */
+typedef struct {
+ unsigned char d_name[MAX_UDF_FILE_NAME_LEN];
+ // "Shall not exceed 1023; Ecma-167 page 123"
+ dvd_dir_type_t d_type; // DT_REG, DT_DIR
+ unsigned int d_namlen;
+ uint64_t d_filesize;
+} dvd_dirent_t;
+
+
+/*
+ * DVDOpendir DIR* structure
+ */
+typedef struct {
+ uint32_t dir_location;
+ uint32_t dir_length;
+ uint32_t dir_current; // Separate to _location should we one day want to
+ // implement dir_rewind()
+ unsigned int current_p; // Internal implementation specific. UDFScanDirX
+ dvd_dirent_t entry;
+} dvd_dir_t;
+
+
/**
* Stats a file on the DVD given the title number and domain.
* The information about the file is stored in a dvd_stat_t
@@ -312,6 +353,24 @@
*/
int DVDUDFCacheLevel( dvd_reader_t *, int );
+
+
+/*
+ * Directory iterator functions to mimick POSIX's opendir/readdir/closedir
+ */
+dvd_dir_t *DVDOpenDir ( dvd_reader_t *, char *);
+
+dvd_dirent_t *DVDReadDir ( dvd_reader_t *, dvd_dir_t *);
+
+int DVDCloseDir ( dvd_reader_t *, dvd_dir_t *);
+
+/*
+ * Open a file based on filename. Usually used after opendir()/readdir().
+ */
+dvd_file_t *DVDOpenFilename( dvd_reader_t *, char * );
+
+
+
#ifdef __cplusplus
};
#endif
diff -ruib ../../versions/libdvdread_patch3/libdvdread/src/dvd_udf.c ./dvd_udf.c
--- ../../versions/libdvdread_patch3/libdvdread/src/dvd_udf.c 2008-10-10
17:16:50.000000000 +0900
+++ ./dvd_udf.c 2008-10-10 17:26:20.000000000 +0900
@@ -820,6 +820,103 @@
return 0;
}
+/**
+ * Low-level function used by DVDReadDir to simulate readdir().
+ * Dir: Location of directory to scan
+ * FileName: Name of file to look for
+ * FileICB: Location of ICB of the found file
+ * return 1 on success, 0 on error;
+ *
+ * Perhaps a better name is more appropriate, it also does no longer use
+ * memory cache. FIXME. -Lund
+ */
+int UDFScanDirX( dvd_reader_t *device,
+ dvd_dir_t *dirp )
+{
+ char filename[ MAX_UDF_FILE_NAME_LEN ];
+ uint8_t directory_base[ 2 * DVD_VIDEO_LB_LEN + 2048];
+ uint8_t *directory = (uint8_t *)(((uintptr_t)directory_base &
~((uintptr_t)2047)) + 2048);
+ uint32_t lbnum;
+ uint16_t TagID;
+ uint8_t filechar;
+ unsigned int p;
+ struct AD FileICB;
+ struct FileAD File;
+ struct Partition partition;
+ uint8_t filetype;
+
+ if(!(GetUDFCache(device, PartitionCache, 0, &partition)))
+ return 0;
+
+ /* Scan dir for ICB of file */
+ lbnum = dirp->dir_current;
+
+ // I have cut out the caching part of the original UDFScanDir() function
+ // one day we should probably bring it back.
+ memset(&File, 0, sizeof(File));
+
+ if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
+ return 0;
+ }
+
+
+ p = dirp->current_p;
+ while( p < dirp->dir_length ) {
+ if( p > DVD_VIDEO_LB_LEN ) {
+ ++lbnum;
+ p -= DVD_VIDEO_LB_LEN;
+
+ //Dir.Length -= DVD_VIDEO_LB_LEN;
+ if (dirp->dir_length >= DVD_VIDEO_LB_LEN)
+ dirp->dir_length -= DVD_VIDEO_LB_LEN;
+ else
+ dirp->dir_length = 0;
+
+ if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
+ return 0;
+ }
+ }
+ UDFDescriptor( &directory[ p ], &TagID );
+
+ if( TagID == 257 ) {
+
+ p += UDFFileIdentifier( &directory[ p ], &filechar,
+ filename, &FileICB );
+
+ dirp->current_p = p;
+ dirp->dir_current = lbnum;
+
+ if (!*filename) // No filename, simulate "." dirname
+ strcpy((char *)dirp->entry.d_name, ".");
+ else {
+ // Bah, MSVC don't have strlcpy()
+ strncpy((char *)dirp->entry.d_name, filename,
+ sizeof(dirp->entry.d_name)-1);
+ dirp->entry.d_name[ sizeof(dirp->entry.d_name) - 1 ] = 0;
+ }
+
+
+ // Look up the Filedata
+ if( !UDFMapICB( device, FileICB, &filetype, &partition, &File))
+ return 0;
+ if (filetype == 4)
+ dirp->entry.d_type = DVD_DT_DIR;
+ else
+ dirp->entry.d_type = DVD_DT_REG; // Add more types?
+
+ dirp->entry.d_filesize = File.Length;
+
+ return 1;
+
+ } else {
+ // Not TagID 257
+ return 0;
+ }
+ }
+ // End of DIR
+ return 0;
+}
+
static int UDFGetAVDP( dvd_reader_t *device,
struct avdp_t *avdp)
diff -ruib ../../versions/libdvdread_patch3/libdvdread/src/dvd_udf.h ./dvd_udf.h
--- ../../versions/libdvdread_patch3/libdvdread/src/dvd_udf.h 2008-10-10
15:40:13.000000000 +0900
+++ ./dvd_udf.h 2008-10-10 17:25:20.000000000 +0900
@@ -51,6 +51,7 @@
UDF_FILE UDFFindFile( dvd_reader_t *device, char *filename, uint64_t *size );
void UDFFreeFile ( dvd_reader_t *device, UDF_FILE );
uint32_t UDFFileBlockPos( UDF_FILE, uint32_t file_block);
+int UDFScanDirX ( dvd_reader_t *device, dvd_dir_t *dirp );
void FreeUDFCache(void *cache);
int UDFGetVolumeIdentifier(dvd_reader_t *device,
_______________________________________________
DVDnav-discuss mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/dvdnav-discuss