计算 FAT16 文件的字节偏移量需要什么?
What is needed to calculate the byte offset for a file in FAT16?
我有一个程序和一个 FAT16 映像。方便的是,映像从引导扇区开始。从那里我提取了根目录、每个扇区的字节数和每个簇的字节数。
从根目录获取子目录的字节偏移量的算法,将r
设置为从image[ 0 ]
到名为path
的给定子文件夹的子目录条目的字节偏移量, 是:
// non-C formatted externally defined values
image = open_some_fat16_image()
path = the_name_of_a_directory_whose_parent_is_root()
LEN_DIR_NAME = 2
LEN_DIRECTORY_ENTRY = 32
FREE_ENTRY_MARKER = 0xE5
END_OF_DIR_MARKER = 0
OFFSET_DIR_ATTR = 11
FLAG_DIRECTORY = 0x10
OFFSET_FIRST_CLUSTER = 26
current_dir = byte_loc_root;
unsigned long r = 0;
for ( int i = 0; i < ( *fat_fs ).root_entry_count && r == 0; i++ )
{
// get the name
char dir_name[ LEN_DIR_NAME +1 ];
unsigned long byte_loc_dir_name = current_dir + ( i * LEN_DIRECTORY_ENTRY );
lseek( image, byte_loc_dir_name, SEEK_SET );
read( image, dir_name, LEN_DIR_NAME );
dir_name[ LEN_DIR_NAME ] = '[=10=]';
// is valid entry
if ( FREE_ENTRY_MARKER == ( unsigned char ) dir_name[ 0 ] ) { continue; }
if ( END_OF_DIR_MARKER == ( unsigned char ) dir_name[ 0 ] ) { break; }
// no right whitespace
for ( int i = 0; i < LEN_DIR_NAME; i ++ )
{
if ( ! isspace( dir_name[ i ] ) ) { continue; }
dir_name[ i ] = '[=10=]';
}
// is a match
if ( 0 != strcmp( dir_name, path ) ) { continue; }
// is a directory
unsigned long byte_loc_dir_attr = byte_loc_dir_name + OFFSET_DIR_ATTR;
lseek( image, byte_loc_dir_attr, SEEK_SET );
uint8_t attr;
read( image, &attr, 1 );
if ( FLAG_DIRECTORY != attr ) { continue; }
// get cluster
unsigned long byte_loc_dir_first_cluster = byte_loc_dir_name + OFFSET_FIRST_CLUSTER;
lseek( image, byte_loc_dir_first_cluster, SEEK_SET );
uint16_t cluster_idx;
read( image, & cluster_idx, LEN_FIRST_CLUSTER );
r = cluster_idx * ( *fat_fs ).sectors_per_cluster * ( *fat_fs ).bytes_per_sector;
}
我已经 运行 这个程序并且已经验证
- sectors_per_cluster
( == 4 ), 和
- bytes_per_sector
( == 512 )
匹配图像中的值(通过 hex_editor )。我还验证了 cluster_idx
与图像中的内容匹配(通过 hex_editor + FAT16 浏览器)。
值r = cluster_idx * sectors_per_cluster * bytes_per_sector = 960 * 4 * 512
设置为:0x1E0000。使用 FAT16 浏览器,我能够在我提供的子目录参数中找到文件。现在获得其中一个文件名后,我使用 hex_editor 在图像中查找它。子目录列表的位置是:0x1ED200。
我很确定我已经正确获取了所有值,除了 r
。我不确定要获取 r
丢失的缺失 53760 字节要采用哪些值。 r
的设置方式是否遗漏了什么?
您应该发送引导扇区内的 BPB 转储。参见 https://en.wikipedia.org/wiki/BIOS_parameter_block and https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#BPB
对于 FAT 16,磁盘通常布局为:
boot sector
fat 1
fat 2
root dir
cluster 2
cluster 3
...
所以你需要调整:
RootDirSectors = <round up (32 bytes *
BPB.RootDirectoryEntries) to be a multiple of BPB.BytesPerSector> / BPB.BytesPerSector
Cluster2SectorNumber =
BPB.ReservedSectors
+ BPB.NumberOfFats * BPB.SectorsPerFat
+ RootDirSectors
ClusterSectorNumber =
Cluster2SectorNumber
+ (cluster_idx - 2) * BPB.SectorsPerCluster
ClusterByteNumber =
ClusterSectorNumber * BPB.BytesPerSector
我有一个程序和一个 FAT16 映像。方便的是,映像从引导扇区开始。从那里我提取了根目录、每个扇区的字节数和每个簇的字节数。
从根目录获取子目录的字节偏移量的算法,将r
设置为从image[ 0 ]
到名为path
的给定子文件夹的子目录条目的字节偏移量, 是:
// non-C formatted externally defined values
image = open_some_fat16_image()
path = the_name_of_a_directory_whose_parent_is_root()
LEN_DIR_NAME = 2
LEN_DIRECTORY_ENTRY = 32
FREE_ENTRY_MARKER = 0xE5
END_OF_DIR_MARKER = 0
OFFSET_DIR_ATTR = 11
FLAG_DIRECTORY = 0x10
OFFSET_FIRST_CLUSTER = 26
current_dir = byte_loc_root;
unsigned long r = 0;
for ( int i = 0; i < ( *fat_fs ).root_entry_count && r == 0; i++ )
{
// get the name
char dir_name[ LEN_DIR_NAME +1 ];
unsigned long byte_loc_dir_name = current_dir + ( i * LEN_DIRECTORY_ENTRY );
lseek( image, byte_loc_dir_name, SEEK_SET );
read( image, dir_name, LEN_DIR_NAME );
dir_name[ LEN_DIR_NAME ] = '[=10=]';
// is valid entry
if ( FREE_ENTRY_MARKER == ( unsigned char ) dir_name[ 0 ] ) { continue; }
if ( END_OF_DIR_MARKER == ( unsigned char ) dir_name[ 0 ] ) { break; }
// no right whitespace
for ( int i = 0; i < LEN_DIR_NAME; i ++ )
{
if ( ! isspace( dir_name[ i ] ) ) { continue; }
dir_name[ i ] = '[=10=]';
}
// is a match
if ( 0 != strcmp( dir_name, path ) ) { continue; }
// is a directory
unsigned long byte_loc_dir_attr = byte_loc_dir_name + OFFSET_DIR_ATTR;
lseek( image, byte_loc_dir_attr, SEEK_SET );
uint8_t attr;
read( image, &attr, 1 );
if ( FLAG_DIRECTORY != attr ) { continue; }
// get cluster
unsigned long byte_loc_dir_first_cluster = byte_loc_dir_name + OFFSET_FIRST_CLUSTER;
lseek( image, byte_loc_dir_first_cluster, SEEK_SET );
uint16_t cluster_idx;
read( image, & cluster_idx, LEN_FIRST_CLUSTER );
r = cluster_idx * ( *fat_fs ).sectors_per_cluster * ( *fat_fs ).bytes_per_sector;
}
我已经 运行 这个程序并且已经验证
- sectors_per_cluster
( == 4 ), 和
- bytes_per_sector
( == 512 )
匹配图像中的值(通过 hex_editor )。我还验证了 cluster_idx
与图像中的内容匹配(通过 hex_editor + FAT16 浏览器)。
值r = cluster_idx * sectors_per_cluster * bytes_per_sector = 960 * 4 * 512
设置为:0x1E0000。使用 FAT16 浏览器,我能够在我提供的子目录参数中找到文件。现在获得其中一个文件名后,我使用 hex_editor 在图像中查找它。子目录列表的位置是:0x1ED200。
我很确定我已经正确获取了所有值,除了 r
。我不确定要获取 r
丢失的缺失 53760 字节要采用哪些值。 r
的设置方式是否遗漏了什么?
您应该发送引导扇区内的 BPB 转储。参见 https://en.wikipedia.org/wiki/BIOS_parameter_block and https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#BPB
对于 FAT 16,磁盘通常布局为:
boot sector
fat 1
fat 2
root dir
cluster 2
cluster 3
...
所以你需要调整:
RootDirSectors = <round up (32 bytes *
BPB.RootDirectoryEntries) to be a multiple of BPB.BytesPerSector> / BPB.BytesPerSector
Cluster2SectorNumber =
BPB.ReservedSectors
+ BPB.NumberOfFats * BPB.SectorsPerFat
+ RootDirSectors
ClusterSectorNumber =
Cluster2SectorNumber
+ (cluster_idx - 2) * BPB.SectorsPerCluster
ClusterByteNumber =
ClusterSectorNumber * BPB.BytesPerSector