uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *filesize ) { uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ]; uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048); uint32_t lbnum; uint16_t TagID; struct Partition partition; struct AD RootICB, File, ICB; char tokenline[ MAX_UDF_FILE_NAME_LEN ]; char *token; uint8_t filetype; *filesize = 0; tokenline[0] = '\0'; strncat(tokenline, filename, MAX_UDF_FILE_NAME_LEN - 1); memset(&ICB, 0, sizeof(ICB)); if(!(GetUDFCache(device, PartitionCache, 0, &partition) && GetUDFCache(device, RootICBCache, 0, &RootICB))) { /* Find partition, 0 is the standard location for DVD Video.*/ if( !UDFFindPartition( device, 0, &partition ) ) return 0; SetUDFCache(device, PartitionCache, 0, &partition); /* Find root dir ICB */ lbnum = partition.Start; do { if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) TagID = 0; else UDFDescriptor( LogBlock, &TagID ); /* File Set Descriptor */ if( TagID == 256 ) /* File Set Descriptor */ UDFLongAD( &LogBlock[ 400 ], &RootICB ); } while( ( lbnum < partition.Start + partition.Length ) && ( TagID != 8 ) && ( TagID != 256 ) ); /* Sanity checks. */ if( TagID != 256 ) return 0; if( RootICB.Partition != 0 ) return 0; SetUDFCache(device, RootICBCache, 0, &RootICB); } /* Find root dir */ if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) return 0; if( filetype != 4 ) return 0; /* Root dir should be dir */ { int cache_file_info = 0; /* Tokenize filepath */ token = strtok(tokenline, "/"); while( token != NULL ) { if( !UDFScanDir( device, File, token, &partition, &ICB, cache_file_info)) return 0; if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) return 0; if(!strcmp(token, "VIDEO_TS")) cache_file_info = 1; token = strtok( NULL, "/" ); } } /* Sanity check. */ if( File.Partition != 0 ) return 0; *filesize = File.Length; /* Hack to not return partition.Start for empty files. */ if( !File.Location ) return 0; else return partition.Start + File.Location; }
/** * 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; */ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName, struct Partition *partition, struct AD *FileICB, int cache_file_info) { 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; uint8_t *cached_dir_base = NULL, *cached_dir; uint32_t dir_lba; struct AD tmpICB; int found = 0; int in_cache = 0; /* Scan dir for ICB of file */ lbnum = partition->Start + Dir.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; 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); if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) { free(cached_dir_base); cached_dir_base = NULL; cached_dir = NULL; } /* if(cached_dir) { fprintf(stderr, "malloc dir: %d\n", dir_lba * DVD_VIDEO_LB_LEN); } */ { uint8_t *data[2]; data[0] = cached_dir_base; data[1] = cached_dir; SetUDFCache(device, LBUDFCache, lbnum, data); } } else in_cache = 1; if(cached_dir == NULL) { free(cached_dir_base); return 0; } p = 0; while( p < Dir.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; if( !strcasecmp( FileName, filename ) ) { memcpy(FileICB, &tmpICB, sizeof(tmpICB)); found = 1; } UDFMapICB(device, tmpICB, &tmpFiletype, partition, &tmpFile); } else { if( !strcasecmp( FileName, filename ) ) { memcpy(FileICB, &tmpICB, sizeof(tmpICB)); return 1; } } } else { if(cache_file_info && (!in_cache) && found) return 1; return 0; } } if(cache_file_info && (!in_cache) && found) return 1; return 0; } if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) return 0; p = 0; while( p < Dir.Length ) { if( p > DVD_VIDEO_LB_LEN ) { ++lbnum; p -= DVD_VIDEO_LB_LEN; Dir.Length -= DVD_VIDEO_LB_LEN; if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) { return 0; } } UDFDescriptor( &directory[ p ], &TagID ); if( TagID == 257 ) { p += UDFFileIdentifier( &directory[ p ], &filechar, filename, FileICB ); if( !strcasecmp( FileName, filename ) ) { return 1; } } else return 0; } return 0; }
uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *filesize ) { uint8_t *LogBlock; uint32_t lbnum; uint16_t TagID; struct Partition partition; struct AD RootICB, File, ICB; char tokenline[ MAX_UDF_FILE_NAME_LEN ]; char *token; uint8_t filetype; if(filesize) { *filesize = 0; } tokenline[0] = '\0'; strcat( tokenline, filename ); if(!(GetUDFCache(device, PartitionCache, 0, &partition) && GetUDFCache(device, RootICBCache, 0, &RootICB))) { /* Find partition, 0 is the standard location for DVD Video.*/ if( !UDFFindPartition( device, 0, &partition ) ) { return 0; } SetUDFCache(device, PartitionCache, 0, &partition); LogBlock = dvdalign_lbmalloc(device, 1); if(!LogBlock) { return 0; } /* Find root dir ICB */ lbnum = partition.Start; do { if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { TagID = 0; } else { UDFDescriptor( LogBlock, &TagID ); } /* File Set Descriptor */ if( TagID == 256 ) { // File Set Descriptor UDFLongAD( &LogBlock[ 400 ], &RootICB ); } } while( ( lbnum < partition.Start + partition.Length ) && ( TagID != 8 ) && ( TagID != 256 ) ); dvdalign_lbfree(device, LogBlock); /* Sanity checks. */ if( TagID != 256 ) { return 0; } if( RootICB.Partition != 0 ) { return 0; } SetUDFCache(device, RootICBCache, 0, &RootICB); } /* Find root dir */ if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) { return 0; } if( filetype != 4 ) { return 0; /* Root dir should be dir */ } { int cache_file_info = 0; /* Tokenize filepath */ token = strtok(tokenline, "/"); while( token != NULL ) { if( !UDFScanDir( device, File, token, &partition, &ICB, cache_file_info)) { return 0; } if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) { return 0; } if(!strcmp(token, "VIDEO_TS")) { cache_file_info = 1; } token = strtok( NULL, "/" ); } } /* Sanity check. */ if( File.Partition != 0 ) { return 0; } if(filesize) { *filesize = File.Length; } /* Hack to not return partition.Start for empty files. */ if( !File.Location ) { return 0; } else { return partition.Start + File.Location; } }
uint32_t BDUDFDirFile( UDF_DIR *device, const char *filename) { uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ]; uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048); uint32_t lbnum; uint16_t TagID; struct Partition partition; struct AD RootICB, File, ICB; char tokenline[ MAX_UDF_FILE_NAME_LEN ]; char *token; uint8_t filetype; tokenline[0] = '\0'; strncat(tokenline, filename, MAX_UDF_FILE_NAME_LEN - 1); memset(&ICB, 0, sizeof(struct AD)); memset(&File, 0, sizeof(struct AD)); memset(&RootICB, 0, sizeof(struct AD)); memset(&partition, 0, sizeof(struct Partition)); if(!(GetBDUDFCache(device->udf_data, PartitionCache, 0, &partition) && GetBDUDFCache(device->udf_data, RootICBCache, 0, &RootICB))) { /* Find partition, 0 is the standard location for DVD Video.*/ if( !UDFFindPartition( device->udf_data, 0, &partition ) ) { UDFFreePartition(&partition); return 0; } /* Find root dir ICB */ //lbnum = partition.Start; lbnum = UDFGetBlock(&partition, partition.vol.FSD.Partition, partition.vol.FSD.Location); do { if( DVDReadLBUDF( device->udf_data, lbnum++, 1, LogBlock, 0 ) <= 0 ) TagID = 0; else UDFDescriptor( LogBlock, &TagID ); /* File Set Descriptor */ if( TagID == 256 ) /* File Set Descriptor */ { UDFLongAD( &LogBlock[ 400 ], &RootICB ); partition.Number = RootICB.Partition; } } while( ( lbnum < partition.Start + partition.Length ) && ( TagID != 8 ) && ( TagID != 256 ) ); SetUDFCache(device->udf_data, PartitionCache, 0, &partition); /* Sanity checks. */ if( TagID != 256 ) return 0; //if( RootICB.Partition != 0 ) // return 0; SetUDFCache(device->udf_data, RootICBCache, 0, &RootICB); } /* Find root dir */ if( !UDFMapICB( device->udf_data, RootICB, &filetype, &partition, &File ) ) return 0; if( filetype != 4 ) return 0; /* Root dir should be dir */ { /* Tokenize filepath */ token = strtok(tokenline, "/"); while( token != NULL ) { if( !UDFScanDir( device->udf_data, File, token, &partition, &ICB, 0) ) return 0; //printf("icb: part: %u, block: %u\n", ICB.Partition, ICB.Location); if( !UDFMapICB( device->udf_data, ICB, &filetype, &partition, &File ) ) return 0; //printf("file: part: %u, block: %u\n", File.Partition, File.Location); token = strtok( NULL, "/" ); } if( UDFCacheDir( device, File, &partition, &ICB) ) { return 1; } } return 0; }
/** * 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; */ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName, struct Partition *partition, struct AD *FileICB, int cache_file_info) { char filename[ MAX_UDF_FILE_NAME_LEN ]; uint8_t *directory; uint32_t lbnum; uint16_t TagID; uint8_t filechar; unsigned int p; uint8_t *cached_dir = NULL; uint32_t dir_lba; struct AD tmpICB; int found = 0; int in_cache = 0; /* Scan dir for ICB of file */ lbnum = partition->Start + Dir.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; if((cached_dir = dvdalign_lbmalloc(device, dir_lba)) == NULL) { return 0; } if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) { dvdalign_lbfree(device, cached_dir); cached_dir = NULL; } SetUDFCache(device, LBUDFCache, lbnum, &cached_dir); } else { in_cache = 1; } if(cached_dir == NULL) { return 0; } p = 0; while( p < Dir.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; if( !strcasecmp( FileName, filename ) ) { *FileICB = tmpICB; found = 1; } UDFMapICB(device, tmpICB, &tmpFiletype, partition, &tmpFile); } else { if( !strcasecmp( FileName, filename ) ) { *FileICB = tmpICB; return 1; } } } else { if(cache_file_info && (!in_cache) && found) { return 1; } return 0; } } if(cache_file_info && (!in_cache) && found) { return 1; } return 0; } directory = dvdalign_lbmalloc(device, 2); if(!directory) { return 0; } if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) { dvdalign_lbfree(device, directory); return 0; } p = 0; while( p < Dir.Length ) { if( p > DVD_VIDEO_LB_LEN ) { ++lbnum; p -= DVD_VIDEO_LB_LEN; Dir.Length -= DVD_VIDEO_LB_LEN; if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) { dvdalign_lbfree(device, directory); return 0; } } UDFDescriptor( &directory[ p ], &TagID ); if( TagID == 257 ) { p += UDFFileIdentifier( &directory[ p ], &filechar, filename, FileICB ); if( !strcasecmp( FileName, filename ) ) { dvdalign_lbfree(device, directory); return 1; } } else { dvdalign_lbfree(device, directory); return 0; } } dvdalign_lbfree(device, directory); return 0; }