📄 fs.c
字号:
}
writing_size = (vpp->bytes_per_cluster < (remaining_size + data_offset_in_cluster)) ? (vpp->bytes_per_cluster - data_offset_in_cluster) : remaining_size;
fs_data_copy( (fp->cluster_buffer_pointer) + data_offset_in_cluster, buffer_ptr, writing_size );
fp->current_file_data_position += writing_size;
remaining_size -= writing_size;
buffer_ptr += writing_size;
(fp->file_info).size += writing_size;
}
return ( length - remaining_size );
}
static void flush_FILE_write_buffer( fs_FILE *fp )
{
volume_param *vpp;
vpp = fp->volume_param_ptr;
if ( fp->buffered_cluster )
storage_write_sector( fp->cluster_buffer_pointer, cluster_to_sector( fp->buffered_cluster ), vpp->sector_per_cluster );
flush_FAT_cache( vpp );
update_directory_entry( fp );
}
//////////
////////// "rm" remove file
//////////
#define FLAG_LEAVE_CURR_DIR 0x01
#define FLAG_REMOVE_RECURSIVE 0x02
#define FLAG_REMOVE_SCAN_ONLY 0x04
unsigned char fs_rm( char *path, unsigned char recursive )
{
directory_entry *dp;
unsigned short base_cluster;
unsigned short index;
unsigned char flags = 0;
unsigned char err = no_error;
volume_param *vpp;
vpp = &g_volume_parameter;
flags |= recursive ? FLAG_REMOVE_RECURSIVE : 0;
if ( NULL == (dp = find_file_entry( path, &base_cluster, &index )) )
return ( FS_RM_DIRECTORY_ACCESS_ERR );
#if BIG_ENDIAN
if ( vpp->current_directory_cluster == swap16( dp->cluster ) )
flags |= FLAG_LEAVE_CURR_DIR;
#else
if ( vpp->current_directory_cluster == dp->cluster )
flags |= FLAG_LEAVE_CURR_DIR;
#endif
if ( !recursive )
{
remove_this_entry( base_cluster, index, flags | FLAG_REMOVE_SCAN_ONLY, &err, 0 );
if ( err )
return ( err );
}
remove_this_entry( base_cluster, index, flags, &err, 0 );
return ( err );
}
//////////
////////// "mv" move file
//////////
unsigned short fs_mv( char *from, char *to )
{
fs_FILE *fp;
directory_entry d;
directory_entry *dp;
unsigned short parent_cluster;
unsigned short index;
unsigned short i;
// volume_param *vpp;
// vpp = &g_volume_parameter;
// get source file entry information
if ( NULL == (dp = find_entry( from )) )
return ( FS_MV_SOURCE_NOT_FOUND );
fs_data_copy( (unsigned char *)(&d), (unsigned char *)dp, sizeof( directory_entry ) );
// make new file entry
if ( NULL == (fp = fs_fopen( to, P | W | D )) )
return ( FS_MV_CANNOT_OPEN_TARGET );
fs_fclose( fp ); // Just made a directory entry
if ( NULL == (dp = find_entry( to )) )
return ( FS_MV_SOURCE_NOT_FOUND );
for ( i = 11; i < sizeof( directory_entry ); i++ )
*((unsigned char *)dp + i) = *((unsigned char *)(&d) + i);
write_back_directory_entry();
// erase old file entry
if ( NULL == (dp = find_entry( from )) )
return ( FS_MV_SOURCE_NOT_FOUND );
*((unsigned char *)dp) = 0xE5;
write_back_directory_entry();
return ( no_error );
}
//////////
////////// "mkdir" make directory
//////////
unsigned char fs_mkdir( char *path )
{
fs_FILE *fp;
directory_entry *dp;
directory_entry cur_d = { ". ", " ", 0x10, {0,0,0,0,0,0,0,0,0,0}, 0, 0, 0, 0 };
directory_entry par_d = { ".. ", " ", 0x10, {0,0,0,0,0,0,0,0,0,0}, 0, 0, 0, 0 };
directory_entry null_d = { {0,0,0,0,0,0,0,0},{0,0,0},0, {0,0,0,0,0,0,0,0,0,0},0,0,0,0 };
unsigned short i;
volume_param *vpp;
vpp = &g_volume_parameter;
// open directory as writing data into file
if ( NULL == (fp = fs_fopen( path, W | D )) )
return ( error );
// write directory contents
#if BIG_ENDIAN
cur_d.cluster = swap16( fp->start_cluster );
par_d.cluster = (fp->directory_entry_cluster == 1) ? 0 : fp->directory_entry_cluster;
par_d.cluster = swap16( par_d.cluster );
#else
cur_d.cluster = fp->start_cluster;
par_d.cluster = (fp->directory_entry_cluster == 1) ? 0 : fp->directory_entry_cluster;
#endif
set_time_for_directory_entry( &cur_d );
set_time_for_directory_entry( &par_d );
fs_write( fp, (unsigned char *)(&cur_d), sizeof( directory_entry ) );
fs_write( fp, (unsigned char *)(&par_d), sizeof( directory_entry ) );
for ( i = 2; i < (vpp->bytes_per_cluster / sizeof( directory_entry )); i++ )
fs_write( fp, (unsigned char *)(&null_d), sizeof( directory_entry ) );
// close written file
fs_fclose( fp );
// modify file entry
if ( NULL == (dp = find_entry( path )) )
return ( error );
dp->attributes = 0x10;
dp->size = 0;
write_back_directory_entry();
return ( no_error );
}
//////////
////////// "df" free disk clusters
//////////
void fs_df( unsigned short *available, unsigned short *total, unsigned short *cluster_size )
{
unsigned short i;
volume_param *vpp;
vpp = &g_volume_parameter;
*cluster_size = vpp->bytes_per_cluster;
*total = vpp->number_of_clasters;
*available = 0;
for ( i = 2; i < (*total) + 2; i++ )
if ( !read_FAT( i ) )
(*available)++;
}
#ifdef SUPPORT_DISK_FORMAT
//////////
////////// "format" format disk
//////////
void fs_format( void )
{
#define BOOT 0x20
#define HIDDEN 0x20
#define CLTSZ 8
#define ROOTDIRENT 512
#define RESERVEDSEC 1
#define N_OF_FAT 2
MasterBootRecord *mbrt;
PartitionEntry *pet;
PartitionBootRecord *pbrt;
BoisParameterBlock *bpbt;
unsigned long disk_size;
unsigned long block_size;
unsigned long total_sector;
unsigned long available_sector;
unsigned long data_sector_size;
unsigned long start_sector;
unsigned short n_of_cluster;
unsigned short FAT_sector_size;
unsigned char b[ 512 ];
unsigned char blank_str[ 12 ] = " ";
unsigned short i;
// BASIC calc ///////////////////////////////////////////////////
total_sector = gp_drive_parameter.last_LBA + 1;
block_size = gp_drive_parameter.block_length;
disk_size = total_sector * block_size;
available_sector = total_sector - (BOOT + HIDDEN + RESERVEDSEC + ((sizeof( directory_entry ) * ROOTDIRENT) / block_size));
n_of_cluster = (available_sector / CLTSZ) + 2;
FAT_sector_size = (((unsigned long)n_of_cluster * 2) / block_size) + 1; // (* 2) means the entry has 2 bytes
data_sector_size = available_sector - (unsigned long)(FAT_sector_size * N_OF_FAT);
n_of_cluster = (data_sector_size / CLTSZ) + 2;
FAT_sector_size = (((unsigned long)n_of_cluster * 2) / block_size) + 1; // (* 2) means the entry has 2 bytes
#if 0
mprintf( LIGHTGRAY, CONTINUE, "\r\n" );
mprintf( LIGHTGRAY, CONTINUE, "total_sector 0x%08lX (%9lu)\r\n", total_sector, total_sector );
mprintf( LIGHTGRAY, CONTINUE, "block_size 0x%08lX (%9lu)\r\n", block_size, block_size );
mprintf( LIGHTGRAY, CONTINUE, "disk_size 0x%08lX (%9lu)\r\n", disk_size, disk_size );
mprintf( LIGHTGRAY, CONTINUE, "available_sector 0x%08lX (%9lu)\r\n", available_sector, available_sector );
mprintf( LIGHTGRAY, CONTINUE, "n_of_cluster 0x%08X (%9u)\r\n", n_of_cluster, n_of_cluster );
mprintf( LIGHTGRAY, CONTINUE, "FAT_sector_size 0x%08X (%9u)\r\n", FAT_sector_size, FAT_sector_size );
mprintf( LIGHTGRAY, CONTINUE, "data_sector_size 0x%08lX (%9lu)\r\n", data_sector_size, data_sector_size );
#endif
// MBR ////////////////////////////////////////////////////////
for ( i = 0; i < 512; i++ )
*(b + i) = 0;
mbrt = (MasterBootRecord *)b;
mbrt->Signature_Word = 0xAA55;
pet = &((mbrt->partition)[ 0 ]);
pet->DefaultBootPartition = 0x80;
pet->StartHead = 1;
pet->StartSector = 1;
pet->StartCylinder = 0;
pet->PartitionType = (disk_size >> 25) ? 6 : 4;
pet->EndHead = (total_sector >> 14) & 0xFF;
pet->EndSector = (total_sector >> 7) & 0x7F;
pet->EndCylinder = (total_sector >> 0) & 0x7F;
pet->StartLBASector = BOOT;
pet->NumSectors = total_sector;
start_sector = 0;
storage_write_sector( b, start_sector, 1 );
// PBR //////////////////////////////////////
for ( i = 0; i < 512; i++ )
*(b + i) = 0;
pbrt = (PartitionBootRecord *)b;
bpbt = &(pbrt->BPB);
(pbrt->JMP_instruction)[ 0 ] = 0xE9;
(pbrt->JMP_instruction)[ 1 ] = 0;
(pbrt->JMP_instruction)[ 2 ] = 0;
fs_data_copy( pbrt->OEM_name_version, blank_str, 8 );
pbrt->DriveNumber = 0;
pbrt->Reserved = 0;
pbrt->ExtBootSignature = 0;
pbrt->Volume_ID = 0;
fs_data_copy( pbrt->VolumeLabel, blank_str, 11 );
(pbrt->VolumeLabel)[ 0 ] = 'W';
(pbrt->VolumeLabel)[ 1 ] = 'A';
(pbrt->VolumeLabel)[ 2 ] = 'S';
(pbrt->VolumeLabel)[ 3 ] = 'A';
(pbrt->VolumeLabel)[ 4 ] = 'B';
(pbrt->VolumeLabel)[ 5 ] = 'I';
(pbrt->VolumeLabel)[ 6 ] = '-';
(pbrt->VolumeLabel)[ 7 ] = 'D';
(pbrt->VolumeLabel)[ 8 ] = 'I';
(pbrt->VolumeLabel)[ 9 ] = 'S';
(pbrt->VolumeLabel)[ 10] = 'K';
fs_data_copy( pbrt->FileSysType, blank_str, 8 );
(pbrt->FileSysType)[ 0 ] = 'F';
(pbrt->FileSysType)[ 1 ] = 'A';
(pbrt->FileSysType)[ 2 ] = 'T';
(pbrt->FileSysType)[ 3 ] = '1';
(pbrt->FileSysType)[ 4 ] = '6';
*((unsigned short *)(b + 510)) = 0xAA55;
bpbt->BytesPerSector = block_size;
bpbt->SectorsPerClustor = CLTSZ;
bpbt->ReservedSectors = RESERVEDSEC;
bpbt->NumFATs = N_OF_FAT;
bpbt->RootDirEntries = ROOTDIRENT;
if (disk_size >> 25)
{
bpbt->TotalSectors = 0;
bpbt->HugeSectors = data_sector_size;
}
else
{
bpbt->TotalSectors = (unsigned short)data_sector_size;
bpbt->HugeSectors = 0;
}
bpbt->MediaIDByte = 0xF8;
bpbt->NumFATSectors = FAT_sector_size;
bpbt->SectorsPerTrack = pet->EndSector;
bpbt->NumHeads = pet->EndHead;
bpbt->HiddenSectors = HIDDEN;
start_sector = BOOT;
storage_write_sector( b, start_sector, 1 );
// FAT1 //////////////////////////////////////
for ( i = 0; i < 512; i++ )
*(b + i) = 0;
start_sector += RESERVEDSEC;
i = 1;
while ( i < FAT_sector_size )
{
storage_write_sector( b, start_sector + i, 1 );
i++;
}
*(((unsigned short *)b) + 0) = 0xFFF8;
*(((unsigned short *)b) + 1) = 0xFFFF;
storage_write_sector( b, start_sector, 1 );
// FAT2 //////////////////////////////////////
for ( i = 0; i < 512; i++ )
*(b + i) = 0;
start_sector += FAT_sector_size;
i = 1;
while ( i < FAT_sector_size )
{
storage_write_sector( b, start_sector + i, 1 );
i++;
}
*(((unsigned short *)b) + 0) = 0xFFF8;
*(((unsigned short *)b) + 1) = 0xFFFF;
storage_write_sector( b, start_sector, 1 );
// ROOT DIR //////////////////////////////////
for ( i = 0; i < 512; i++ )
*(b + i) = 0;
start_sector += FAT_sector_size;
for ( i = 0; i < (ROOTDIRENT * sizeof( directory_entry )) / block_size; i++ )
storage_write_sector( b, start_sector++, 1 );
}
#endif
unsigned long fs_cluster_to_sector( unsigned short c )
{
return ( cluster_to_sector( c ) );
}
unsigned short fs_read_FAT( unsigned short current_cluster )
{
return ( read_FAT( current_cluster ) );
}
/*
==============================================================================
==============================================================================
==== Public functions for file system access
==== Functions for DRIVER side
==============================================================================
==============================================================================
*/
volume_param *fs_volume_open( void )
{
volume_param *vpp;
char fs_name[ 9 ];
unsigned char *buffer_ptr;
unsigned char partition; // ## Version 1.2c
unsigned char fs_type;
unsigned long start_lba;
unsigned char i;
// Make volume instance
// In this version, it is allocated as static
vpp = &g_volume_parameter;
// Allocate a temporary buffer for sector size
// At this moment, the cluster size is unknown. So this temporary buffer will be freed
// after getting cluster size information from boot block in the volume.
if ( NULL == (buffer_ptr = (unsigned char *)malloc( gp_drive_parameter.block_length )) )
{
mprintf( LIGHTGRAY, CONTINUE, "error : File system init (malloc) failed\r\n" );
return ( NULL );
}
// Read sector LBA=0 (MasterBootRecord : MBR) to get partition information (Partition entries).
// This version only support single partition.
// MBR : PC card standard section 3.2 and 3.2.4 (include "Partition entry" information)
// Also, see http://www.microsoft.com/hwdev/download/hardware/FATGEN103.doc
storage_read_sector( buffer_ptr, 0, 1 );
// ## Version 1.2c (from here)
//
// When the storage volume does not have partition table, it should be
// handled as a volume without partition table.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -