📄 fs.c
字号:
{
num_of_large_read_clusters = 0;
size_of_post_read = length;
}
else
{
num_of_large_read_clusters = length / vpp->bytes_per_cluster;
size_of_post_read = length % vpp->bytes_per_cluster;
}
}
if ( size_of_pre_read )
{
size = fs_read_small( fp, buffer_ptr, size_of_pre_read );
buffer_ptr += size_of_pre_read;
size_of_total_read += size;
}
if ( num_of_large_read_clusters )
{
size = fs_read_large( fp, buffer_ptr, num_of_large_read_clusters );
buffer_ptr += (num_of_large_read_clusters * vpp->bytes_per_cluster);
size_of_total_read += size;
}
if ( size_of_post_read )
{
size = fs_read_small( fp, buffer_ptr, size_of_post_read );
size_of_total_read += size;
}
return ( size_of_total_read );
}
static unsigned short fs_read_large( fs_FILE *fp, unsigned char *buffer_ptr, unsigned long clusters )
{
unsigned short target_cluster_N;
unsigned short base_cluster;
unsigned short next_cluster;
unsigned short read_bytes;
unsigned short read_sectors;
unsigned short total_read_bytes = 0;
unsigned short continuous_length;
unsigned short i;
volume_param *vpp;
vpp = fp->volume_param_ptr;
target_cluster_N = fp->current_file_data_position / vpp->bytes_per_cluster;
// cluster buffer control
// if the target cluster number does not match to read cluster number,
// update the current cluster index.
continuous_length = 0;
do
{
if ( !continuous_length )
{
if ( fp->number_of_cluster_processed != (target_cluster_N + 1) )
{
if ( fp->current_cluster )
fp->current_cluster = read_FAT( fp->current_cluster );
else
fp->current_cluster = fp->start_cluster;
}
base_cluster = fp->current_cluster;
}
continuous_length++;
clusters--;
(fp->number_of_cluster_processed)++;
next_cluster = read_FAT( fp->current_cluster );
if ( (fp->current_cluster == (next_cluster - 1)) && clusters )
{
fp->current_cluster = next_cluster;
continue;
}
read_bytes = vpp->bytes_per_cluster * continuous_length;
read_sectors = vpp->sector_per_cluster * continuous_length;
if ( read_sectors != storage_read_sector( buffer_ptr, cluster_to_sector( base_cluster ), read_sectors ) )
{
//storage_unmount();
return ( 0 );
}
buffer_ptr += read_bytes;
total_read_bytes += read_bytes;
fp->current_file_data_position += read_bytes;
continuous_length = 0;
}
while ( clusters );
return ( total_read_bytes );
}
static unsigned short fs_read_small( fs_FILE *fp, unsigned char *buffer_ptr, unsigned short length )
{
unsigned long data_offset_in_cluster;
unsigned short target_cluster_N;
unsigned long remaining_file_size;
unsigned short remaining_size;
unsigned short reading_size;
volume_param *vpp;
if ( !length )
return ( 0 );
// get volume parameter pointer to refer volume information.
// this function needs information like sector size etc.
vpp = fp->volume_param_ptr;
#ifdef ALWAYS_SMALL_READ
// calcurate file data size left
if ( (fp->file_info).attributes & 0x10 )
remaining_file_size = vpp->bytes_per_cluster; // Possible problem : No bigger directory handling
else
remaining_file_size = (fp->file_info).size - fp->current_file_data_position;
// limit file reading size to file size.
// to prevent over reading.
length = ((unsigned long)length < remaining_file_size) ? length : (unsigned short)remaining_file_size;
// set "remaining_size".
// the "length" will kept to hold the expected data reading size untill this function end.
// it will be used to report read size as return value.
#endif // ALWAYS_SMALL_READ
remaining_size = length;
while ( remaining_size )
{
// find target cluster and ofset from data position in the file
data_offset_in_cluster = fp->current_file_data_position % vpp->bytes_per_cluster;
target_cluster_N = fp->current_file_data_position / vpp->bytes_per_cluster;
// cluster buffer control
// if the target cluster number does not match to read cluster number,
// update the current cluster index.
if ( fp->number_of_cluster_processed != (target_cluster_N + 1) )
{
if ( fp->current_cluster )
// if it is not first time to load,
// get the cluster index from FAT information.
fp->current_cluster = read_FAT( fp->current_cluster );
else
// if it is first time, set the index which was got in fs_open
// "fp->current_cluster" holds the index to the reading source cluster
fp->current_cluster = fp->start_cluster;
}
// check the index of reading source and buffered cluster.
if (fp->current_cluster != fp->buffered_cluster)
{
// if those are different, read from sectors to file buffer
if ( vpp->sector_per_cluster != storage_read_sector( fp->cluster_buffer_pointer, cluster_to_sector( fp->current_cluster ), vpp->sector_per_cluster ) )
{
//storage_unmount();
return ( 0 );
}
// update to show the current buffered cluster information
fp->buffered_cluster = fp->current_cluster;
// count up, the counter to count the cluster has been read.
(fp->number_of_cluster_processed)++;
}
// calculate the readout size.
// The data can be readout from the file data position to cluster end.
reading_size = (vpp->bytes_per_cluster < (remaining_size + data_offset_in_cluster)) ? (vpp->bytes_per_cluster - data_offset_in_cluster) : remaining_size;
// read out :
// copy data from file buffer to user buffer for size of reading_size.
//mprintf( LIGHTGRAY, CONTINUE, "remaining_size %d reading %d n_cluster %u offset %ld c 0x%04X\r\n", remaining_size, reading_size, target_cluster_N, data_offset_in_cluster, fp->current_cluster );
fs_data_copy( buffer_ptr, (fp->cluster_buffer_pointer) + data_offset_in_cluster, reading_size );
// update pointers
// when the remaining size is not zero, the loop will kepp execution.
fp->current_file_data_position += reading_size;
buffer_ptr += reading_size;
remaining_size -= reading_size;
}
return ( length - remaining_size );
}
//////////
////////// "write" file write
//////////
//#define ALWAYS_SMALL_WRITE
#ifdef ALWAYS_SMALL_WRITE
#else
unsigned short fs_write( fs_FILE *fp, unsigned char *buffer_ptr, unsigned short length )
{
unsigned short size_of_pre_write;
unsigned short num_of_large_write_clusters;
unsigned short size_of_post_write;
unsigned short data_offset_in_cluster;
unsigned short write_clusters;
unsigned short size;
unsigned short size_of_total_write = 0;
unsigned long remaining_file_size;
volume_param *vpp;
vpp = fp->volume_param_ptr;
if ( length < vpp->bytes_per_cluster )
{
size_of_pre_write = length;
num_of_large_write_clusters = 0;
size_of_post_write = 0;
}
else
{
data_offset_in_cluster = fp->current_file_data_position % vpp->bytes_per_cluster;
size_of_pre_write = data_offset_in_cluster ? (vpp->bytes_per_cluster - data_offset_in_cluster) : 0;
length -= size_of_pre_write;
if ( length < vpp->bytes_per_cluster )
{
num_of_large_write_clusters = 0;
size_of_post_write = length;
}
else
{
num_of_large_write_clusters = length / vpp->bytes_per_cluster;
size_of_post_write = length % vpp->bytes_per_cluster;
}
}
if ( size_of_pre_write )
{
size = fs_write_small( fp, buffer_ptr, size_of_pre_write );
buffer_ptr += size_of_pre_write;
size_of_total_write += size;
}
if ( num_of_large_write_clusters )
{
size = fs_write_large( fp, buffer_ptr, num_of_large_write_clusters );
buffer_ptr += (num_of_large_write_clusters * vpp->bytes_per_cluster);
size_of_total_write += size;
}
if ( size_of_post_write )
{
size = fs_write_small( fp, buffer_ptr, size_of_post_write );
size_of_total_write += size;
}
return ( size_of_total_write );
}
static unsigned short fs_write_large( fs_FILE *fp, unsigned char *buffer_ptr, unsigned long clusters )
{
unsigned short target_cluster_N;
unsigned short base_cluster;
unsigned short next_cluster;
unsigned short write_bytes;
unsigned short write_sectors;
unsigned short total_write_bytes = 0;
unsigned short continuous_length;
unsigned short i;
volume_param *vpp;
vpp = fp->volume_param_ptr;
fp->buffered_cluster = NULL;
target_cluster_N = fp->current_file_data_position / vpp->bytes_per_cluster;
// cluster buffer control
// if the target cluster number does not match to write cluster number,
// update the current cluster index.
continuous_length = 0;
do
{
if ( !continuous_length )
{
if ( fp->number_of_cluster_processed != (target_cluster_N + 1) )
{
if ( fp->current_cluster )
{
if ( !(next_cluster = find_free_cluster( fp->current_cluster )) )
return ( total_write_bytes );
write_FAT( fp->current_cluster, next_cluster );
write_FAT( next_cluster, 0xFFFF );
fp->current_cluster = next_cluster;
}
else
{
fp->current_cluster = fp->start_cluster;
(fp->file_info).cluster = fp->start_cluster;
write_FAT( fp->current_cluster, 0xFFFF );
}
}
base_cluster = fp->current_cluster;
}
continuous_length++;
clusters--;
(fp->number_of_cluster_processed)++;
if ( !(next_cluster = find_free_cluster( fp->current_cluster )) )
return ( total_write_bytes );
if ( (fp->current_cluster == (next_cluster - 1)) && clusters )
{
write_FAT( fp->current_cluster, next_cluster );
write_FAT( next_cluster, 0xFFFF );
fp->current_cluster = next_cluster;
continue;
}
write_bytes = vpp->bytes_per_cluster * continuous_length;
write_sectors = vpp->sector_per_cluster * continuous_length;
if ( write_sectors != storage_write_sector( buffer_ptr, cluster_to_sector( base_cluster ), write_sectors ) )
{
//storage_unmount();
return ( 0 );
}
write_FAT( fp->current_cluster, 0xFFFF );
buffer_ptr += write_bytes;
total_write_bytes += write_bytes;
fp->current_file_data_position += write_bytes;
(fp->file_info).size += write_bytes;
continuous_length = 0;
}
while ( clusters );
return ( total_write_bytes );
}
#endif //ALWAYS_SMALL_WRITE
#ifdef ALWAYS_SMALL_WRITE
unsigned short fs_write( fs_FILE *fp, unsigned char *buffer_ptr, unsigned short length )
#else
static unsigned short fs_write_small( fs_FILE *fp, unsigned char *buffer_ptr, unsigned short length )
#endif
{
unsigned long data_offset_in_cluster;
unsigned short target_cluster_N;
unsigned short next_cluster;
unsigned short remaining_size;
unsigned short writing_size;
volume_param *vpp;
if ( !length )
return ( 0 );
vpp = fp->volume_param_ptr;
remaining_size = length;
while ( remaining_size )
{
data_offset_in_cluster = fp->current_file_data_position % vpp->bytes_per_cluster;
target_cluster_N = fp->current_file_data_position / vpp->bytes_per_cluster;
// mprintf( LIGHTCYAN, CONTINUE, "remaining_size=%u data_offset_in_cluster=%lu target_cluster_N=%u\r\n", remaining_size, data_offset_in_cluster, target_cluster_N );
// mprintf( LIGHTCYAN, CONTINUE, "fp->start_cluster=%u fp->number_of_cluster_processed=%u fp->current_cluster=%u fp->buffered_cluster=%u\r\n", fp->start_cluster, fp->number_of_cluster_processed, fp->current_cluster, fp->buffered_cluster );
if ( fp->number_of_cluster_processed != (target_cluster_N + 1) )
{
// if the data on the boundary, new cluster will be allocated
if ( fp->current_cluster )
{
// if the new cluster required, search the open cluster from current
// cluster.
#if 0
if ( !(fp->current_cluster = find_free_cluster( fp->current_cluster )) )
return ( length - remaining_size );
#else
if ( !(next_cluster = find_free_cluster( fp->current_cluster )) )
return ( length - remaining_size );
write_FAT( fp->current_cluster, next_cluster );
write_FAT( next_cluster, 0xFFFF );
fp->current_cluster = next_cluster;
#endif
}
else
{
// the first cluster allocation is done by file open function.
// this action just doing the copying the cluster number to current.
fp->current_cluster = fp->start_cluster;
(fp->file_info).cluster = fp->start_cluster;
}
}
// if the curent cluster index and buffered cluster index are different
if (fp->current_cluster != fp->buffered_cluster)
{
// if the buffered data already exist
if ( fp->buffered_cluster )
{
#define FAST_WRITE
#ifdef FAST_WRITE
if ( vpp->sector_per_cluster != storage_write_sector( fp->cluster_buffer_pointer, cluster_to_sector( fp->buffered_cluster ), vpp->sector_per_cluster ) )
return ( 0 );
#else
flush_FILE_write_buffer( fp );
#endif
// set next cluster value to current cluster entry. links the clusters (FATs).
write_FAT( fp->buffered_cluster, fp->current_cluster );
}
write_FAT( fp->current_cluster, 0xFFFF );
fp->buffered_cluster = fp->current_cluster;
(fp->number_of_cluster_processed)++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -