📄 dvd_udf.c
字号:
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 ); tmpmap.file = *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;}/** * 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[ 2 * DVD_VIDEO_LB_LEN ]; 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 = malloc(dir_lba * DVD_VIDEO_LB_LEN)) == NULL) { return 0; } if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) { free(cached_dir); cached_dir = NULL; } /* if(cached_dir) { fprintf(stderr, "malloc dir: %d\n", dir_lba * DVD_VIDEO_LB_LEN); } */ 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; } 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 UDFGetAVDP( dvd_reader_t *device, struct avdp_t *avdp){ uint8_t Anchor[ DVD_VIDEO_LB_LEN ]; 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;}/** * Looks for partition on the disc. Returns 1 if partition found, 0 on error. * partnum: Number of the partition, starting at 0. * part: structure to fill with the partition information */static int UDFFindPartition( dvd_reader_t *device, int partnum, struct Partition *part ) { uint8_t LogBlock[ DVD_VIDEO_LB_LEN ]; uint32_t lbnum, MVDS_location, MVDS_length; uint16_t TagID; int i, volvalid; struct avdp_t avdp; if(!UDFGetAVDP(device, &avdp)) { return 0; } /* Main volume descriptor */ MVDS_location = avdp.mvds.location; MVDS_length = avdp.mvds.length; part->valid = 0; volvalid = 0; part->VolumeDesc[ 0 ] = '\0'; i = 1; do { /* Find Volume Descriptor */ lbnum = MVDS_location; do { if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { TagID = 0; } else { UDFDescriptor( LogBlock, &TagID ); } if( ( TagID == 5 ) && ( !part->valid ) ) { /* Partition Descriptor */ UDFPartition( LogBlock, &part->Flags, &part->Number, part->Contents, &part->Start, &part->Length ); part->valid = ( partnum == part->Number ); } else if( ( TagID == 6 ) && ( !volvalid ) ) { /* Logical Volume Descriptor */ if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) { /* TODO: sector size wrong! */ } else { volvalid = 1; } } } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) / DVD_VIDEO_LB_LEN ) && ( TagID != 8 ) && ( ( !part->valid ) || ( !volvalid ) ) ); if( ( !part->valid) || ( !volvalid ) ) { /* Backup volume descriptor */ MVDS_location = avdp.mvds.location; MVDS_length = avdp.mvds.length; } } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) ); /* We only care for the partition, not the volume */ return part->valid;}uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *filesize ){ uint8_t LogBlock[ DVD_VIDEO_LB_LEN ]; 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'; 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); /* 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;}/** * Gets a Descriptor . * Returns 1 if descriptor found, 0 on error. * id, tagid of descriptor * bufsize, size of BlockBuf (must be >= DVD_VIDEO_LB_LEN). */static int UDFGetDescriptor( dvd_reader_t *device, int id, uint8_t *descriptor, int bufsize) { uint32_t lbnum, MVDS_location, MVDS_length; struct avdp_t avdp; uint16_t TagID; uint32_t lastsector; int i, terminate; int desc_found = 0; /* Find Anchor */ lastsector = 0; lbnum = 256; /* Try #1, prime anchor */ terminate = 0; if(bufsize < DVD_VIDEO_LB_LEN) { return 0; } if(!UDFGetAVDP(device, &avdp)) { return 0; } /* Main volume descriptor */ MVDS_location = avdp.mvds.location; MVDS_length = avdp.mvds.length; i = 1; do { /* Find Descriptor */ lbnum = MVDS_location; do { if( DVDReadLBUDF( device, lbnum++, 1, descriptor, 0 ) <= 0 ) { TagID = 0; } else { UDFDescriptor( descriptor, &TagID ); } if( (TagID == id) && ( !desc_found ) ) { /* Descriptor */ desc_found = 1; } } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) / DVD_VIDEO_LB_LEN ) && ( TagID != 8 ) && ( !desc_found) ); if( !desc_found ) { /* Backup volume descriptor */ MVDS_location = avdp.rvds.location; MVDS_length = avdp.rvds.length; } } while( i-- && ( !desc_found ) ); return desc_found;}static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd){ uint8_t pvd_buf[DVD_VIDEO_LB_LEN]; if(GetUDFCache(device, PVDCache, 0, pvd)) { return 1; } if(!UDFGetDescriptor( device, 1, pvd_buf, sizeof(pvd_buf))) { return 0; } memcpy(pvd->VolumeIdentifier, &pvd_buf[24], 32); memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128); SetUDFCache(device, PVDCache, 0, pvd); return 1;}/** * Gets the Volume Identifier string, in 8bit unicode (latin-1) * volid, place to put the string * volid_size, size of the buffer volid points to * returns the size of buffer needed for all data */int UDFGetVolumeIdentifier(dvd_reader_t *device, char *volid, unsigned int volid_size){ struct pvd_t pvd; unsigned int volid_len; /* get primary volume descriptor */ if(!UDFGetPVD(device, &pvd)) { return 0; } volid_len = pvd.VolumeIdentifier[31]; if(volid_len > 31) { /* this field is only 32 bytes something is wrong */ volid_len = 31; } if(volid_size > volid_len) { volid_size = volid_len; } Unicodedecode(pvd.VolumeIdentifier, volid_size, volid); return volid_len;}/** * Gets the Volume Set Identifier, as a 128-byte dstring (not decoded) * WARNING This is not a null terminated string * volsetid, place to put the data * volsetid_size, size of the buffer volsetid points to * the buffer should be >=128 bytes to store the whole volumesetidentifier * returns the size of the available volsetid information (128) * or 0 on error */int UDFGetVolumeSetIdentifier(dvd_reader_t *device, uint8_t *volsetid, unsigned int volsetid_size){ struct pvd_t pvd; /* get primary volume descriptor */ if(!UDFGetPVD(device, &pvd)) { return 0; } if(volsetid_size > 128) { volsetid_size = 128; } memcpy(volsetid, pvd.VolumeSetIdentifier, volsetid_size); return 128;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -