📄 file_system.c
字号:
if(buffer>=Scratch && buffer<Scratch+Sect_Block_Size())
count=min(count,Sect_Block_Size()-f->pos%Sect_Block_Size());
while(count && !m_feof(f)) {
f->sector_current = fat_chain(f->cluster_start,f->pos/Sect_Block_Size());
Sect_Read(Sect_File_Data() + f->sector_current);
cnt=min(Sect_Block_Size()-f->pos%Sect_Block_Size(),count);
cnt=min(cnt,f->size-f->pos);
memmove(buffer,Scratch+f->pos%Sect_Block_Size(),cnt); // MUST be overlap-safe
// copy operation!
total_cnt+=cnt;
f->pos+=cnt;
count-=cnt;
buffer+=cnt;
}
return total_cnt;
}
//-----------------------------------------------------------------------------
// m_fwrite
//-----------------------------------------------------------------------------
//
// Return Value : amount of written bytes
// Parameters : f - pointer to file structure
// buffer - pinter to buffer
// count - number of bytes to write
//
// This function writes the file
//-----------------------------------------------------------------------------
uint mm_fwrite(M_FILE * f,BYTE * buffer,ulong count)
{
int i,j;
dir_entry* entry;
int last_file_size,start_cluster;
int last_cluster;
int file_start_point;
int file_end_point;
int free_size_in_last_sect;
int new_sect_need;
unsigned short * fat_list;
if(count==0)
return 0;
//////////////////////////////////////update_dir
Sect_Read(f->sector_direntry);
entry = (dir_entry*)(Scratch+f->offset_direntry);
last_file_size=f->size;
start_cluster=entry->sfn.starting_cluster;
f->size+=count;
entry->sfn.filesize+=count;
Sect_Write(f->sector_direntry);
//get file end point ; write to file directly
last_cluster=last_file_size/Sect_Cluster_Size()+start_cluster;
file_start_point=(Sect_File_Data()+start_cluster*MBR.sectors_per_cluster)*512;
file_end_point=file_start_point+last_file_size;
direct_write(file_end_point,buffer,count);
//update the fat table
free_size_in_last_sect=512-(last_file_size%512);
if(count<=free_size_in_last_sect)
new_sect_need=0;
else
new_sect_need=(count-free_size_in_last_sect)/512+1;
fat_list=(unsigned short *)(get_vfile_add()+Sect_Fat1()*512);
if(new_sect_need>0)
{
for(i=0;i<new_sect_need;i++)
{
*(fat_list+i+last_cluster)=i+last_cluster+1;//fill the fat table
}
*(fat_list+i+last_cluster)=0xffff;//fill the end fat block;
}
//////////////////////////////////////update_fat
/*the_last_cluster=last_file_size/Sect_Cluster_Size()+last_start_cluster;
free_bytes_in_last_cluster=Sect_Cluster_Size()-last_file_size%Sect_Cluster_Size();
new_cluster_needed=(count>free_bytes_in_last_cluster)?((count-free_bytes_in_last_cluster-1)/Sect_Cluster_Size()+1):0;
if(new_cluster_needed!=0)
{
last_fat_sect=the_last_cluster/256;
free_fat_blocks=(256-the_last_cluster%Sect_Cluster_Size());
new_fat_sect_needed=(new_cluster_needed>free_fat_blocks)?((new_cluster_needed-free_fat_blocks-1)/256+1):0;
current_cluster_pos=the_last_cluster%256;
if(new_fat_sect_needed==0)
{
Sect_Read(Sect_Fat1()+last_fat_sect);
fats=(unsigned short *)Scratch;
for(i=current_cluster_pos;i<current_cluster_pos+new_cluster_needed;i++)
{
fats[i]=LSB_to_MSB(last_fat_sect*256+i+1);
}
fats[i]=LSB_to_MSB(0xffff);
Sect_Write(Sect_Fat1()+last_fat_sect);
}
else
{
//多fat section的情况
for(i=last_fat_sect;i<last_fat_sect+new_fat_sect_needed+1;i++)
{
write_fats=((current_cluster_pos+new_cluster_needed)>255)?(255-current_cluster_pos+1):(new_cluster_needed+1);
Sect_Read(Sect_Fat1()+i);
fats=(unsigned short *)Scratch;
for(j=current_cluster_pos;j<current_cluster_pos+write_fats;j++)
{
fats[j]=LSB_to_MSB(last_fat_sect*256+i*256+j+1);
}
if(j<=255)
fats[j]=LSB_to_MSB(0xffff);
Sect_Write(Sect_Fat1()+i);
current_cluster_pos=0;
new_cluster_needed-=write_fats;
}
}
}
//////////////////////////////////////update_file
//the first cluster
first_sect_in_cluster=(Sect_Cluster_Size()-free_bytes_in_last_cluster)/512;
free_sect_in_cluster=MBR.sectors_per_cluster-first_sect_in_cluster;
Sect_read(Sect_File_Data()+the_last_cluster*MBR.sectors_per_cluster+first_sect_in_cluster);
write_size=free_bytes_in_last_cluster%512;
write_pos=512-write_size;
read_pos=0;
memcpy(Scratch+write_pos,buffer+read_pos,write_size);*/
}
ulong m_fwrite(M_FILE* f,BYTE* buffer,ulong count)
{
ulong cnt,total_cnt=0,xtra,alloced;
dir_entry* entry;
if(!f->isopen || !count) return 0;
// First, extend the file so it can hold all the data:
if(f->pos+count>f->size) {
// If the new EOF ends up in the next FAT block, an extra block must be allocated.
// The number of blocks needed to store X bytes = 1+(X-1)/512 if X!=0, or =0 if X==0.
// We will need to store 'pos+count' bytes after the write operation
// This means we need 1+(pos+count-1)/512 blocks after the write operation
// We currently have 'size' bytes in the file, or 1+(size-1)/512 blocks (or 0 if size==0).
// So, we need to allocate (1+(pos+count-1)/512) - (1+(size-1)/512) extra blocks
xtra=(1+((f->pos+count-1)/Sect_Block_Size())/MBR.sectors_per_cluster);
if ( f->size )
xtra -= ( 1 +(( f->size - 1 ) / Sect_Block_Size() ) / MBR.sectors_per_cluster );
if(xtra) {
if(0xFFFF==(alloced=fat_chain_alloc(f->sector_current/MBR.sectors_per_cluster,xtra)))
return 0;
}
// Modify the direntry for this file:
Sect_Read(f->sector_direntry);
entry = (dir_entry*)(Scratch+f->offset_direntry);
if((entry->sfn.filesize==0) && (entry->sfn.starting_cluster<2 ||
entry->sfn.starting_cluster>=0xFFF0)) {
//entry->sfn.starting_cluster=ntohs(f->cluster_start=alloced);
entry->sfn.starting_cluster=(f->cluster_start=alloced);
}
//entry->sfn.filesize=ntohl(f->size=f->pos+count);
entry->sfn.filesize=(f->size=f->pos+count);
f->attrib=(entry->sfn.attrib|=ATTRIB_ARCHIVE);
Sect_Write(f->sector_direntry);
}
// Now we are sure the m_fwrite() operation can be performed
// in the existing file data blocks. Either because the file
// was big enough to start with, or because we have just
// allocated extra blocks for the new data.
while(count && !m_feof(f)) {
f->sector_current = fat_chain(f->cluster_start,f->pos/Sect_Block_Size());
Sect_Read(Sect_File_Data() + f->sector_current);
// Print_File(f);
// print_scratch();
cnt=min(Sect_Block_Size()-f->pos%Sect_Block_Size(),count);
cnt=min(cnt,f->size-f->pos);
memmove(Scratch+f->pos%Sect_Block_Size(),buffer,cnt);
// print_scratch();
Sect_Write(Sect_File_Data() + f->sector_current);
total_cnt+=cnt;
f->pos+=cnt;
count-=cnt;
buffer+=cnt;
}
return total_cnt;
}
//-----------------------------------------------------------------------------
// m_fclose
//-----------------------------------------------------------------------------
//
// Return Value :
// Parameters : f - pointer to file structure
//
// This function closes the file
//-----------------------------------------------------------------------------
void m_fclose(M_FILE* f)
{
f->isopen=0;
}
//-----------------------------------------------------------------------------
// m_fdelete
//-----------------------------------------------------------------------------
//
// Return Value :TRUE if everything is ok
// Parameters : name - pointer to filename
//
//
// This function deletes the file
//-----------------------------------------------------------------------------
int m_fdelete(char* name)
{
findfirst(&findinfo,0);
while(!file_name_match(name,findinfo.direntry->sfn.name)) {
if(!findnext(&findinfo)) {
return 0;
}
}
// Do not delete subdirectories or labels:
if(findinfo.direntry->sfn.attrib & (ATTRIB_SUBDIR|ATTRIB_LABEL)) return 0;
// Mark the direntry as "deleted" before freeing the fat chain.
// At this point, the findinfo is still valid in the 'Scratch' buffer.
// fat_chain_free() would overwrite the Scratch buffer.
findinfo.direntry->sfn.name[0]=0xE5; // Mark as "deleted"
Sect_Write(findinfo.block);
fat_chain_free(ntohs(findinfo.direntry->sfn.starting_cluster));
return 1;
}
//-------------------directory functions---------------------
//--------- findfirst, findnext directory functions ---------
static BYTE findvalid(find_info* findinfo)
{
char n0 = findinfo->direntry->sfn.name[0];
if(findinfo->findempty)
{
return (n0==(char)0xE5) || (n0=='\0');
}
return (n0!=(char)0xE5) && (n0>' ') && (findinfo->direntry->sfn.attrib!=0x0F);
}
BYTE findfirst(find_info* findinfo,BYTE empty) //empty=1 means find the first dir entry
{
Sect_Read(findinfo->block = Current_Dir_Block);
findinfo->findempty=empty;
findinfo->offset=0;
findinfo->direntry=(dir_entry*)(Scratch+findinfo->offset);
if(findvalid(findinfo))//check the first direntry valid or not
{
return 1;
}
else
{
findnext(findinfo);//如果第一个direntry不是空的,则继续查找下一个
return 2;//如果 不是第一个direntry 返回2
}
}
BYTE findnext(find_info* findinfo)
{
BYTE bRoot = (Current_Dir_Block == Sect_Root_Dir());
do
{
if((findinfo->offset+=32)>=Sect_Block_Size())
{
unsigned long dir_next_cluster_block = Get_First_Block_Directory_Cluster(findinfo->block);
if(bRoot && (findinfo->block>=Sect_Root_Dir_Last()))
{
// printf("NOT FOUND\r\n");
return 0;
}
else if((!bRoot) && (dir_next_cluster_block != 0xffffffff) && (findinfo->block>=(dir_next_cluster_block + MBR.sectors_per_cluster-1)))
{
// read next cluster occupied by directory
unsigned long next_next_block = Get_First_Block_Of_Next_Cluster(
Get_Cluster_From_Sector(dir_next_cluster_block));
if(next_next_block == (0xFFFFFFFF))
{
if(!findinfo->findempty)
return 0;
else
{
ulong new_cluster =
fat_chain_alloc(Get_Cluster_From_Sector(dir_next_cluster_block),1);
if(new_cluster == 0xFFFF)
return 0;
next_next_block = Get_First_Sector(new_cluster);
Clear_Cluster(new_cluster);
}
}
dir_next_cluster_block = next_next_block;
findinfo->offset=0;
Sect_Read(findinfo->block = dir_next_cluster_block);
}
else {
findinfo->offset=0;
Sect_Read(++findinfo->block);
}
}
findinfo->direntry=(dir_entry*)(Scratch+findinfo->offset);
} while(!findvalid(findinfo));
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -