⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 file_system.c

📁 能够在单片机等小型处理器上使用的fat16文件系统
💻 C
📖 第 1 页 / 共 3 页
字号:
  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 + -