📄 fs.c
字号:
if ( !(flags & FLAG_REMOVE_SCAN_ONLY) && !(!depth && (flags & FLAG_LEAVE_CURR_DIR)) )
{
*((unsigned char *)dp) = 0xE5;
write_back_directory_entry();
#if BIG_ENDIAN
clear_FAT_chain( swap16( dp->cluster ) );
#else
clear_FAT_chain( dp->cluster );
#endif
}
return ( no_error );
}
//
// FAT operation
//
static unsigned short count_free_cluster( void )
{
unsigned short count = 0;
unsigned short i;
volume_param *vpp;
vpp = &g_volume_parameter;
for ( i = 0; i < vpp->number_of_clasters; i++ )
if ( !read_FAT( i + 2 ) )
count++;
return ( count );
}
static unsigned short find_free_cluster( unsigned short start_cluster )
{
unsigned short i;
volume_param *vpp;
vpp = &g_volume_parameter;
for ( i = start_cluster; i < (vpp->number_of_clasters + 2); i++ )
if ( !read_FAT( i ) )
return ( i );
return ( 0 );
}
static unsigned char clear_FAT_chain( unsigned short cluster )
{
unsigned short count;
unsigned short i;
volume_param *vpp;
vpp = &g_volume_parameter;
count = 0;
while ( valid_cluster( cluster, vpp ) )
{
cluster = write_FAT( cluster, 0x0000 );
if ( count++ == 0xFFFF )
break;
}
flush_FAT_cache( vpp );
if ( (i == 0xFFFF) || (cluster == 0x0000) )
return ( error );
return ( no_error );
}
static unsigned char valid_cluster( unsigned short cluster, volume_param *vpp )
{
if ( (cluster - 2) < vpp->number_of_clasters )
return ( True );
return ( False );
}
static unsigned short read_FAT( unsigned short current_cluster )
{
volume_param *vpp;
vpp = &g_volume_parameter;
if ( vpp->file_system == FILE_SYSTEM_FAT16 )
return ( access_FAT16( FAT_READ, current_cluster, NULL ) );
else if ( vpp->file_system == FILE_SYSTEM_FAT12 )
return ( access_FAT12( FAT_READ, current_cluster, NULL ) );
return ( 0 );
}
static unsigned short write_FAT( unsigned short cluster, unsigned short value )
{
volume_param *vpp;
vpp = &g_volume_parameter;
if ( vpp->file_system == FILE_SYSTEM_FAT16 )
return ( access_FAT16( FAT_WRITE, cluster, value ) );
else if ( vpp->file_system == FILE_SYSTEM_FAT12 )
return ( access_FAT12( FAT_WRITE, cluster, value ) );
return ( 0 );
}
static unsigned short flush_FAT_cache( volume_param *vpp )
{
if ( vpp->file_system == FILE_SYSTEM_FAT16 )
return ( flush_FAT16_cache( vpp ) );
else if ( vpp->file_system == FILE_SYSTEM_FAT12 )
return ( flush_FAT12_cache( vpp ) );
return ( 0 );
}
static unsigned short flush_FAT16_cache( volume_param *vpp )
{
if ( vpp->FAT_cached_sector == FAT_CACHE_NOT_VALID )
return ( 0 );
storage_write_sector( (unsigned char *)(vpp->FAT_cache), vpp->start_sector_FAT1 + vpp->FAT_cached_sector, 1 );
storage_write_sector( (unsigned char *)(vpp->FAT_cache), vpp->start_sector_FAT2 + vpp->FAT_cached_sector, 1 );
vpp->FAT_cached_sector = FAT_CACHE_NOT_VALID;
vpp->FAT_cache_dirty = False;
return ( 0 );
}
static unsigned short flush_FAT12_cache( volume_param *vpp )
{
if ( !(vpp->FAT_cache_dirty) )
return ( 0 );
storage_write_sector( (unsigned char *)(vpp->FAT_cache), vpp->start_sector_FAT1, vpp->number_of_FAT_sectors );
storage_write_sector( (unsigned char *)(vpp->FAT_cache), vpp->start_sector_FAT2, vpp->number_of_FAT_sectors );
vpp->FAT_cache_dirty = False;
return ( 0 );
}
static unsigned short access_FAT16( unsigned char mode, unsigned short cluster, unsigned short value )
{
unsigned long target_sector;
unsigned long entry_offset;
unsigned short previous_value;
volume_param *vpp;
vpp = &g_volume_parameter;
target_sector = cluster / (vpp->bytes_per_sector >> 1);
entry_offset = cluster % (vpp->bytes_per_sector >> 1);
if ( vpp->FAT_cached_sector != target_sector )
{
if ( vpp->FAT_cache_dirty )
flush_FAT_cache( vpp );
storage_read_sector( (unsigned char *)(vpp->FAT_cache), vpp->start_sector_FAT1 + target_sector, 1 );
vpp->FAT_cached_sector = target_sector;
}
if ( mode == FAT_WRITE )
{
#if BIG_ENDIAN
previous_value = *(vpp->FAT_cache + entry_offset);
*(vpp->FAT_cache + entry_offset) = swap16( value );
vpp->FAT_cache_dirty = True;
return ( swap16( previous_value ) );
#else
previous_value = *(vpp->FAT_cache + entry_offset);
*(vpp->FAT_cache + entry_offset) = value;
vpp->FAT_cache_dirty = True;
return ( previous_value );
#endif
}
//else if ( mode == FAT_READ )
#if BIG_ENDIAN
return ( swap16( *(vpp->FAT_cache + entry_offset) ) );
#else
return ( *(vpp->FAT_cache + entry_offset) );
#endif
}
static unsigned short access_FAT12( unsigned char mode, unsigned short cluster, unsigned short value )
{
unsigned long *target;
unsigned long offset;
unsigned char odd;
unsigned long tmp;
unsigned short target_cluster;
volume_param *vpp;
vpp = &g_volume_parameter;
odd = cluster & 0x1;
cluster &= 0xFFF;
offset = (cluster >> 1) * 3;
target = (unsigned long *)(((unsigned char *)vpp->FAT_cache) + offset);
#if BIG_ENDIAN
tmp = swap32( *target );
#else
tmp = *target;
#endif
target_cluster = odd ? ((tmp >> 12) & 0xFFF) : (tmp & 0xFFF);
target_cluster |= (target_cluster & 0x0800) ? 0xF000 : 0x0000;
if ( mode == FAT_WRITE )
{
value &= 0xFFF;
if ( odd )
{
tmp &= 0xFF000FFF;
tmp |= (unsigned long)value << 12;
}
else
{
tmp &= 0xFFFFF000;
tmp |= (unsigned long)value;
}
#if BIG_ENDIAN
*target = swap32( tmp );
#else
*target = tmp;
#endif
vpp->FAT_cache_dirty = True;
}
return ( target_cluster );
}
//
// Sector operation
//
static unsigned long cluster_to_sector( unsigned short cluster )
{
volume_param *vpp;
vpp = &g_volume_parameter;
if ( cluster == ROOT_DIRECTORY_CLUSTER )
return ( vpp->start_sector_root_directory );
else if ( valid_cluster( cluster, vpp ) )
return ( vpp->start_sector_claster_region + ((((unsigned long)cluster) - 2) * (unsigned long)(vpp->sector_per_cluster)) );
else
return ( 0xFFFFFFFF );
}
//
// Cluster operation
//
static directory_entry *find_entry( char *path )
{
unsigned short dummy_c;
unsigned short dummy_i;
return ( find_file_entry( path, &dummy_c, &dummy_i ) );
}
static directory_entry *find_file_entry( char *path, unsigned short *dir_cluster_ptr, unsigned short *index_ptr )
{
char full_path[ MAX_PATH_STRING_LENGTH ];
char *fpp;
char file_entry_string[ 12 ];
directory_entry *dp;
volume_param *vpp;
vpp = &g_volume_parameter;
dp = &g_root_dumy;
#if BIG_ENDIAN
*dir_cluster_ptr = swap16( dp->cluster );
#else
*dir_cluster_ptr = dp->cluster;
#endif
fpp = full_path;
make_full_path( fpp, path, vpp->current_dir );
while ( 1 )
{
if ( *fpp == '/' )
fpp++;
if ( !(*fpp) )
break;
format_file_name_directory_entry( file_entry_string, fpp ); // This formats the name first directory name in the path
#if BIG_ENDIAN
*dir_cluster_ptr = swap16( dp->cluster );
if ( NULL == (dp = find_directory_index( index_ptr, swap16( dp->cluster ), file_entry_string )) )
break;
#else
*dir_cluster_ptr = dp->cluster;
if ( NULL == (dp = find_directory_index( index_ptr, dp->cluster, file_entry_string )) )
break;
#endif
fpp += first_char_position( fpp, '/' );
}
return ( dp );
}
static directory_entry *find_directory_index( unsigned short *found_index, unsigned short base_cluster, char *name )
{
directory_entry *dp;
*found_index = 0;
while ( 1 )
{
dp = get_directory_entry( base_cluster, *found_index, NO_MAKE_NEW_DIR_ENT );
if ( NULL == dp )
return ( NULL );
if ( *((unsigned char *)dp) == 0 )
return ( NULL );
if ( str_match( (char *)dp, name, 11 ) )
return ( dp );
(*found_index)++;
}
}
static directory_entry *find_free_directory_entry( unsigned short *found_index, unsigned short base_cluster, char *name )
{
directory_entry *dp;
*found_index = 0;
while ( 1 )
{
dp = get_directory_entry( base_cluster, *found_index, OK_MAKE_NEW_DIR_ENT );
if ( NULL == dp )
return ( NULL );
if ( *((unsigned char *)dp) == 0 )
return ( dp );
if ( str_match( (char *)dp, name, 11 ) )
return ( NULL );
if ( *((unsigned char *)dp) == 0xE5 )
return ( dp );
(*found_index)++;
}
}
static directory_entry *get_directory_entry( unsigned short base_cluster, unsigned short index, unsigned char new_entry_ok )
{
unsigned short cluster_offset;
unsigned short entry_offset;
unsigned short target_cluster;
unsigned short new_cluster;
unsigned long read_start_sector = 0;
unsigned char new_sector_allocated = False;
unsigned short i;
volume_param *vpp;
vpp = &g_volume_parameter;
entry_offset = index % (vpp->bytes_per_cluster / sizeof(directory_entry));
cluster_offset = index / (vpp->bytes_per_cluster / sizeof(directory_entry));
if ( base_cluster == ROOT_DIRECTORY_CLUSTER )
{
read_start_sector = vpp->start_sector_root_directory + vpp->sector_per_cluster * cluster_offset;
}
else
{
target_cluster = base_cluster;
for ( i = 0; i < cluster_offset; i++ )
{
new_cluster = read_FAT( target_cluster );
if ( new_cluster == 0xFFFF )
{
if ( new_entry_ok )
{
new_cluster = find_free_cluster( target_cluster );
if ( !valid_cluster( new_cluster, vpp ) )
return ( NULL );
write_FAT( target_cluster, new_cluster );
write_FAT( new_cluster, 0xFFFF );
new_sector_allocated = True;
}
else
{
return ( NULL );
}
}
target_cluster = new_cluster;
}
read_start_sector = cluster_to_sector( target_cluster );
}
if ( read_start_sector != vpp->dir_cached_sector )
{
if ( new_sector_allocated )
for ( i = 0; i < vpp->bytes_per_cluster; i++ )
*(vpp->dir_cache + i) = 0;
else
storage_read_sector( vpp->dir_cache, read_start_sector, vpp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -