I have a program and a FAT16 image. Conveniently, the image begins with the boot sector. From there I have extracted the root directory, bytes per sector, and bytes per cluster.
The algorithm for obtaining the byte offset for a subdirectory from the root directory, setting r
to the byte offset from image[ 0 ]
to the subdirectory entry for a given subfolder named path
, is:
// 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 ] = '\0';
// 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 ] = '\0';
}
// 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;
}
I've run this program and have verified that
- sectors_per_cluster
( == 4 ), and
- bytes_per_sector
( == 512 )
match the values in the image ( via hex_editor ). I have also verified that cluster_idx
matches what's in the image ( via hex_editor + FAT16 browser ).
The value r = cluster_idx * sectors_per_cluster * bytes_per_sector = 960 * 4 * 512
is set to is: 0x1E0000. Using the FAT16 browser, I was able to find files in the subdirectory argument I gave. With one of those filenames now obtained, I looked for it in the image using a hex_editor. The location of the subdirectory listing was: 0x1ED200.
I'm pretty sure I've obtained all the values correctly, except r
. I'm not sure which values to take to obtain the missing 53760 bytes that r
is off by. Is there something missing from how r
is set?