📄 sma_fat16.c
字号:
HDN_SECS_SZ);
fat16_moveto (&data [LG_SECS_OFS], &fg->large_sectors,
LG_SECS_SZ);
fat16_moveto (&data [DV_NUM_OFS], &fg->drive_number, DV_NUM_SZ);
fat16_moveto (&data [RSV_OFS], &fg->reserved, RSV_SZ);
fat16_moveto (&data [BT_SIG_OFS], &fg->ext_boot_sig, BT_SIG_SZ);
fat16_moveto (&data [SERNUM_OFS], &fg->serial_number, SERNUM_SZ);
fat16_moveto (&data [LABEL_OFS], &fg->label, LABEL_SZ);
fat16_moveto (&data [FSNAME_OFS], &fg->fs_name, FSNAME_SZ);
// Compute the first sector in the partition (fatgeom)
fat_data->cfat.first_boot_sector =
fat_data->part [partnum].mbr_sec_offset;
// Compute reserved sectors
fat_data->cfat.boot_sectors = fat_data->pat_hdr.res_sectors;
// Compute sectors used for a single FAT
fat_data->cfat.fat_sectors = fat_data->pat_hdr.sectors_fat;
// Compute location of first and last FAT(1) sectors
fat_data->cfat.first_fat1_sector =
fat_data->cfat.first_boot_sector +
fat_data->cfat.boot_sectors;
fat_data->cfat.last_fat1_sector =
fat_data->cfat.first_fat1_sector +
fat_data->cfat.fat_sectors - 1;
// Compute location of first and last FAT(2) sectors. This may
// not exist in all implementations
fat_data->cfat.first_fat2_sector =
fat_data->cfat.last_fat1_sector + 1;
fat_data->cfat.last_fat2_sector =
fat_data->cfat.first_fat2_sector +
fat_data->cfat.fat_sectors - 1;
// Compute location of the root directory and # of root sectors
fat_data->cfat.first_root_sector =
fat_data->cfat.first_fat1_sector +
(fat_data->cfat.fat_sectors *
fat_data->pat_hdr.fat_copies);
fat_data->cfat.root_sectors = (fat_data->pat_hdr.root_entries *
sizeof (root_entry_type) / fat_data->pat_hdr.bytes_sector);
// Compute total number of sectors
fat_data->cfat.total_sectors = fat_data->pat_hdr.small_sectors;
if (fat_data->cfat.total_sectors == 0)
{
fat_data->cfat.total_sectors =
fat_data->pat_hdr.large_sectors;
}
// Compute location of the first data sector
fat_data->cfat.first_data_sector =
fat_data->cfat.first_root_sector +
fat_data->cfat.root_sectors;
// Compute total number of data sectors
fat_data->cfat.data_sectors = fat_data->cfat.total_sectors -
fat_data->cfat.root_sectors - (fat_data->cfat.fat_sectors *
(UNS_32) fat_data->pat_hdr.fat_copies) -
fat_data->cfat.boot_sectors;
// Compute the number of data clusters available
fat_data->cfat.clusters = fat_data->cfat.data_sectors /
fat_data->pat_hdr.sectors_cluster;
// Compute the total size of the device partition
fat_data->cfat.total_size = fat_data->cfat.total_sectors *
fat_data->pat_hdr.bytes_sector;
// Save computed cluster size (in bytes)
fat_data->cfat.cluster_size =
(UNS_16) fat_data->pat_hdr.sectors_cluster *
(UNS_16) fat_data->pat_hdr.bytes_sector;
// Compute the required size of the file cluster table
table_size = (UNS_32) (fat_data->cfat.fat_sectors *
(UNS_32) fat_data->pat_hdr.bytes_sector);
fat_data->clusters = (UNS_16 *) malloc (table_size);
// Read cluster data into file cluster table
fat16_read_sectors (fat_data, fat_data->clusters,
fat_data->cfat.first_fat1_sector,
fat_data->cfat.fat_sectors);
// Save new active partition number
fat_data->act_part = (INT_8) partnum;
// Valid operation
valid = 1;
}
return valid;
}
/***********************************************************************
*
* Function: fat16_create_new_file_descriptor
*
* Purpose:
* Creates a file structure with the device and FAT data.
*
* Processing:
* Allocates memory for a new file descriptor. Sets the initial file
* mode to FINVALID. Links the FAT device structure to the file
* descriptor. Sets up and caches the default directory used with the
* file descriptor as the root directory with an initial directory
* index at the start of the directory table. Allocates space for
* data storage during file operations (read/write).
*
* Parameters:
* fat_data : Pointer to a FAT device structure
*
* Outputs:
* None
*
* Returns:
* A pointer to a new file descriptor or NULL if there was not enough
* memory available.
*
* Notes:
* None
*
**********************************************************************/
file_type * fat16_create_new_file_descriptor (fat_device_type *fat_data)
{
file_type *file_data;
UNS_32 table_size;
// Allocate a new file data structure
file_data = malloc (sizeof (file_type));
if (file_data != (file_type *) NULL)
{
// Mode is initially invalid
file_data->fmode = FINVALID;
// Save binded FAT/device structure
file_data->fat_data = fat_data;
// Set the default startup directory to 'root'
file_data->sector_dir = fat_data->cfat.first_root_sector;
// Create data buffer pointer and clear buffer index
file_data->data = (UNS_8 *) malloc ((INT_32)
file_data->fat_data->cfat.cluster_size);
// Compute required size of the directory listing and
// allocate a new directory table
table_size = fat_data->cfat.root_sectors *
(UNS_32) fat_data->pat_hdr.bytes_sector;
file_data->dir_data = (root_entry_type *) malloc (
table_size);
// Cache in the directory table
fat16_read_sectors (fat_data, file_data->dir_data,
file_data->sector_dir, fat_data->cfat.root_sectors);
// Clear initial directory index
file_data->dir_index = 0;
// Initial directory is unchanged
file_data->dir_commit = 0;
}
return file_data;
}
/***********************************************************************
*
* Function: fat16_destroy_file_descriptor
*
* Purpose:
* Destroys a created file descriptor.
*
* Processing:
* Prior to destroying the file descriptor, a call to fat16_close is
* performed to write any data in the write buffer out to the device.
* If the directory has been changed in any way, the cached directory
* is written back to the device. The structures used in the file
* descriptor and the file descriptor itself are then de-allocated.
*
* Parameters:
* file_data : Pointer to a file descriptor to free.
*
* Outputs:
* None
*
* Returns:
* Nothing
*
* Notes:
* None
*
**********************************************************************/
void fat16_destroy_file_descriptor (file_type *file_data)
{
if (file_data != NULL)
{
// Close an open file
fat16_close_file (file_data);
// Write the active directory back to the device is it has
// changed
if (file_data->dir_commit == 1)
{
fat16_write_sectors (file_data->fat_data,
file_data->dir_data, file_data->sector_dir,
file_data->fat_data->cfat.root_sectors);
}
// Destroy the data and directory
free (file_data->data);
free (file_data->dir_data);
// Destroy the file data structure
free (file_data);
}
}
/***********************************************************************
*
* Function: fat16_cd
*
* Purpose:
* Set the active directory.
*
* Processing:
* Prior to any operations, the current directory index data is saved.
* If the first character is a '/', the directory pointer is set to
* the root directory. If the dir_commit flag is set, the cached
* directory will be written back to the device before the change.
*
* The next name in the path will then be parsed. The active directory
* will be searched for the name. If the name is found, the cluster
* number to the new directory will be fetched and the new directory
* cached in. This process continues for all parsed names. If no errors
* occurred, the active directory index is updated to the new index.
* If an error occurred, the original directory and index are restored.
*
* Parameters:
* path : Path of new directory
* file_data : Pointer to a FILE data structure to populate
*
* Outputs:
* Data in file_data will be updated.
*
* Returns:
* '1' if the operation was successful, '0' otherwise.
*
* Notes:
* None
*
**********************************************************************/
INT_32 fat16_cd (CHAR *path, file_type *file_data)
{
CHAR dirname [16];
INT_32 previous_dir, previous_dir_index, dir_index;
INT_32 size = 0;
INT_32 valid = 0;
INT_32 index = 0;
// Save previous path and index, in case this operation fails
previous_dir = file_data->sector_dir;
previous_dir_index = file_data->dir_index;
// Reset path to root if first character in the pathname is '/'
if (path [index] == '/')
{
// Before caching in new directory, rewrite the old directory
// back to the device if the directory has changed
if (file_data->dir_commit == 1)
{
fat16_write_sectors (file_data->fat_data,
file_data->dir_data, file_data->sector_dir,
file_data->fat_data->cfat.root_sectors);
file_data->dir_commit = 0;
}
// Set the default startup directory to 'root'
file_data->sector_dir =
file_data->fat_data->cfat.first_root_sector;
file_data->dir_index = 0;
// Cache in the new directory table
fat16_read_sectors (file_data->fat_data,
file_data->dir_data, file_data->sector_dir,
file_data->fat_data->cfat.root_sectors);
index = 1;
valid = 1;
}
// More data in the path name
if (path [1] != '\0')
{
valid = 1;
// Get the next directory name
size = fat16_parse_path (&path [index]);
while (size > 0)
{
// A valid name was found, copy name locally with terminator
fat16_moveto (&path [index], dirname, size);
dirname [size] = '\0';
dir_index = fat16_find_file (dirname, file_data);
if (dir_index == -1)
{
// Path/directory was not found, so quit
valid = 0;
size = -1;
}
// Only switch directories if it actually is a directory
else if (
file_data->dir_data [dir_index].attribute == ATTB_DIR)
{
// Before caching in new directory, rewrite the old
// directory back to the device if the directory has
// changed
if (file_data->dir_commit == 1)
{
fat16_write_sectors (file_data->fat_data,
file_data->dir_data, file_data->sector_dir,
file_data->fat_data->cfat.root_sectors);
file_data->dir_commit = 0;
}
// Good so far, set file directory pointer to new
// directory table
file_data->sector_dir =
fat16_translate_cluster_to_sector (
file_data->fat_data,
file_data->dir_data [dir_index].clusternum);
file_data->dir_index = 0;
// Cache in the new directory table
fat16_read_sectors (file_data->fat_data,
file_data->dir_data, file_data->sector_dir,
file_data->fat_data->cfat.root_sectors);
// Update index, skip past delimiters
index = index + size;
if (path [index] == '/')
{
index++;
}
// Check next field
size = fat16_parse_path (&path [index]);
}
else
{
// Check next field
size = fat16_parse_path (&path [index]);
}
}
}
if ((valid == 0) || (size < 0))
{
// Restore previous directory if needed
if (file_data->sector_dir != previous_dir)
{
// Error somewhere, restore previous path and index
file_data->sector_dir = previous_dir;
file_data->dir_index = previous_dir_index;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -