/** * Maps ICB to FileAD * ICB: Location of ICB of directory to scan * FileType: Type of the file * File: Location of file the ICB is pointing to * return 1 on success, 0 on error; */ static int UDFMapICB( UDF_DATA *device, struct AD ICB, uint8_t *FileType, struct Partition *partition, struct AD *File ) { 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 icbmap tmpmap; //lbnum = partition->Start + ICB.Location; lbnum = UDFGetBlock(partition, ICB.Partition, ICB.Location); //printf("lbnum: %d\n", lbnum); tmpmap.lbn = lbnum; if(GetBDUDFCache(device, MapCache, lbnum, &tmpmap)) { *FileType = tmpmap.filetype; memcpy(File, &tmpmap.file, sizeof(tmpmap.file)); return 1; } do { if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { return 0; TagID = 0; } else UDFDescriptor( LogBlock, &TagID ); //printf("icb tagid: %d\n", TagID); if( TagID == 261 ) { UDFFileEntry( LogBlock, FileType, partition, File ); memcpy(&tmpmap.file, File, sizeof(tmpmap.file)); tmpmap.filetype = *FileType; SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap); return 1; } else if ( TagID == 266 ) { UDFExtFileEntry( LogBlock, FileType, partition, File ); //printf("in file: part: %u, block: %u\n", File->Partition, File->Location); memcpy(&tmpmap.file, File, sizeof(tmpmap.file)); tmpmap.filetype = *FileType; SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap); return 1; } } while( ( lbnum <= lbnum + ( ICB.Length - 1 ) / DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) ); return 0; }
/** * Maps ICB to FileAD * ICB: Location of ICB of directory to scan * FileType: Type of the file * File: Location of file the ICB is pointing to * 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 ) { 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 icbmap tmpmap; lbnum = partition->Start + ICB.Location; tmpmap.lbn = lbnum; if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) { *FileType = tmpmap.filetype; memcpy(File, &tmpmap.file, sizeof(tmpmap.file)); return 1; } do { if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) TagID = 0; else UDFDescriptor( LogBlock, &TagID ); if( TagID == 261 ) { UDFFileEntry( LogBlock, FileType, partition, File ); memcpy(&tmpmap.file, File, sizeof(tmpmap.file)); tmpmap.filetype = *FileType; SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap); return 1; }; } while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 ) / DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) ); return 0; }
static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd) { uint8_t *pvd_buf; if(GetUDFCache(device, PVDCache, 0, pvd)) { return 1; } pvd_buf = dvdalign_lbmalloc(device, 1); if(!pvd_buf) { return 0; } if(!UDFGetDescriptor( device, 1, pvd_buf, 1*DVD_VIDEO_LB_LEN)) { dvdalign_lbfree(device, pvd_buf); return 0; } memcpy(pvd->VolumeIdentifier, &pvd_buf[24], 32); memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128); SetUDFCache(device, PVDCache, 0, pvd); dvdalign_lbfree(device, pvd_buf); return 1; }
static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd) { uint8_t pvd_buf_base[DVD_VIDEO_LB_LEN + 2048]; uint8_t *pvd_buf = (uint8_t *)(((uintptr_t)pvd_buf_base & ~((uintptr_t)2047)) + 2048); if(GetUDFCache(device, PVDCache, 0, pvd)) return 1; if(!UDFGetDescriptor( device, 1, pvd_buf, DVD_VIDEO_LB_LEN)) return 0; memcpy(pvd->VolumeIdentifier, &pvd_buf[24], 32); memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128); SetUDFCache(device, PVDCache, 0, pvd); return 1; }
/** * Maps ICB to FileAD * ICB: Location of ICB of directory to scan * FileType: Type of the file * File: Location of file the ICB is pointing to * 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 ) { uint8_t *LogBlock; uint32_t lbnum; uint16_t TagID; struct icbmap tmpmap; lbnum = partition->Start + ICB.Location; tmpmap.lbn = lbnum; if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) { *FileType = tmpmap.filetype; *File = tmpmap.file; return 1; } LogBlock = dvdalign_lbmalloc(device, 1); if(!LogBlock) { return 0; } do { if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { TagID = 0; } else { UDFDescriptor( LogBlock, &TagID ); } if( TagID == 261 ) { UDFFileEntry( LogBlock, FileType, partition, File ); tmpmap.file = *File; tmpmap.filetype = *FileType; SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap); dvdalign_lbfree(device, LogBlock); return 1; }; } while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 ) / DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) ); dvdalign_lbfree(device, LogBlock); return 0; }
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; }
static int UDFGetAVDP( dvd_reader_t *device, struct avdp_t *avdp) { uint8_t Anchor_base[ DVD_VIDEO_LB_LEN + 2048 ]; uint8_t *Anchor = (uint8_t *)(((uintptr_t)Anchor_base & ~((uintptr_t)2047)) + 2048); uint32_t lbnum, MVDS_location, MVDS_length; uint16_t TagID; uint32_t lastsector; int terminate; struct avdp_t; if(GetUDFCache(device, AVDPCache, 0, avdp)) return 1; /* Find Anchor */ lastsector = 0; lbnum = 256; /* Try #1, prime anchor */ terminate = 0; for(;;) { if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) { UDFDescriptor( Anchor, &TagID ); } else { TagID = 0; } if (TagID != 2) { /* Not an anchor */ if( terminate ) return 0; /* Final try failed */ if( lastsector ) { /* We already found the last sector. Try #3, alternative * backup anchor. If that fails, don't try again. */ lbnum = lastsector; terminate = 1; } else { /* TODO: Find last sector of the disc (this is optional). */ if( lastsector ) /* Try #2, backup anchor */ lbnum = lastsector - 256; else /* Unable to find last sector */ return 0; } } else /* It's an anchor! We can leave */ break; } /* Main volume descriptor */ UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location ); avdp->mvds.location = MVDS_location; avdp->mvds.length = MVDS_length; /* Backup volume descriptor */ UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location ); avdp->rvds.location = MVDS_location; avdp->rvds.length = MVDS_length; SetUDFCache(device, AVDPCache, 0, avdp); return 1; }
/** * 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; }
static int UDFCacheDir( UDF_DIR *device, struct AD Dir, struct Partition *partition, struct AD *FileICB) { 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 in_cache = 0; uint32_t file_num = 0; /* Scan dir for ICB of file */ //lbnum = partition->Start + Dir.Location; lbnum = UDFGetBlock(partition, Dir.Partition, Dir.Location); if(BDUDFCacheLevel(device->udf_data, -1) > 0) { /* caching */ if(!GetBDUDFCache(device->udf_data, LBUDFCache, lbnum, &cached_dir)) { dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN; if((cached_dir_base = (uint8_t*)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->udf_data, 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->udf_data, LBUDFCache, lbnum, data); } } else in_cache = 1; if(cached_dir == NULL) return 0; p = 0; device->aloc_num = 5; device->file_name = malloc(256 * device->aloc_num); while( p < Dir.Length ) { UDFDescriptor( &cached_dir[ p ], &TagID ); //printf("aaa TagID: %d, len: %d\n", TagID, Dir.Length); if( TagID == 257 ) { p += UDFFileIdentifier( &cached_dir[ p ], &filechar, filename, &tmpICB ); if (filename[0] == '\0') continue; if (file_num + 1 > device->aloc_num) { device->aloc_num += 5; device->file_name = realloc((void *)device->file_name, 256 * device->aloc_num); } //printf("add filename: '%s'\n", filename); strncpy((char *)(device->file_name + file_num), filename, 256); device->file_num = ++file_num; } else { return 0; } } return 1; } if( DVDReadLBUDF( device->udf_data, 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->udf_data, lbnum, 2, directory, 0 ) <= 0 ) { return 0; } } UDFDescriptor( &directory[ p ], &TagID ); if( TagID == 257 ) { p += UDFFileIdentifier( &directory[ p ], &filechar, filename, FileICB ); //printf("filename2: %s\n", filename); } } return 0; }
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; }
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; } }
static int UDFGetAVDP( dvd_reader_t *device, struct avdp_t *avdp) { uint8_t *Anchor; uint32_t lbnum, MVDS_location, MVDS_length; uint16_t TagID; uint32_t lastsector; int terminate; struct avdp_t; if(GetUDFCache(device, AVDPCache, 0, avdp)) { return 1; } /* Find Anchor */ lastsector = 0; lbnum = 256; /* Try #1, prime anchor */ terminate = 0; Anchor = dvdalign_lbmalloc(device, 1); if(!Anchor) { return 0; } for(;;) { if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) { UDFDescriptor( Anchor, &TagID ); } else { TagID = 0; } if (TagID != 2) { /* Not an anchor */ if( terminate ) { dvdalign_lbfree(device, Anchor); errno = EMEDIUMTYPE; return 0; /* Final try failed */ } if( lastsector ) { /* We already found the last sector. Try #3, alternative * backup anchor. If that fails, don't try again. */ lbnum = lastsector; terminate = 1; } else { /* TODO: Find last sector of the disc (this is optional). */ if( lastsector ) { /* Try #2, backup anchor */ lbnum = lastsector - 256; } else { /* Unable to find last sector */ dvdalign_lbfree(device, Anchor); errno = EMEDIUMTYPE; return 0; } } } else { /* It's an anchor! We can leave */ break; } } /* Main volume descriptor */ UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location ); avdp->mvds.location = MVDS_location; avdp->mvds.length = MVDS_length; /* Backup volume descriptor */ UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location ); avdp->rvds.location = MVDS_location; avdp->rvds.length = MVDS_length; SetUDFCache(device, AVDPCache, 0, avdp); dvdalign_lbfree(device, Anchor); return 1; }
/** * 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; }