www.pudn.com > flashfat16.rar > fat16.c


#include  
#include "fat16.h" 
#include "..\Target\44blib.h" 
#include "..\Target\44b.h" 
 
#define SEEK_SET 0 
#define SEEK_CUR 1 
#define SEEK_END 2 
 
#define DISK_32M  32 
#define DISK_16M  16 
 
#define DEBUG_FAT        1 
#define FAT_SIZEOFWORD   8*256 
//请注意每个扇区实际为528个字节,最后还有16个字节 
BYTE SectorBuffer[512];   //SectorBuffer 
BYTE SectorSpare[16];//Nandflash的备用区,防止sectorbuffer与clusterbuffer冲突 
BYTE ClusterBuffer[32][512];//ClusterBuffer 
WORD FatCache[FAT_SIZEOFWORD]; 
 
//unsigned char *SectorBuffer  =  (unsigned char *) SECTOR_BUFFER1_ADDR;//暂放sector的512字节空间 
//unsigned char *LongNameBuffer = (unsigned char *) LONGNAME_BUFFER_ADDR;//暂放长文件名的字节空间 
//unsigned char *DirNameBuffer =  (unsigned char *) DIRNAME_BUFFER_ADDR;//暂放路径名的字节空间  
extern unsigned char Erase_Cluster(unsigned int cluster); 
extern void ReadPage(unsigned int block,unsigned int page,unsigned char *pPage); 
extern int  WritePage(unsigned int block,unsigned int page,U8 *pPage);  
//--------------该函数用于将磁盘格式化----------------------------// 
int fat_format(unsigned char Media,unsigned char Sizeofdisk_M,unsigned char FilesysType) 
{ 
	//PARTSECTOR   *partsector; 
	//PARTRECORD   *partrecord; 
	int i,j,fatsec,temp,blocknum; 
	BOOTSECTOR50 *bootsector;  
	BPB50 *bpb; 
	EXTBOOT *ext; 
	 
	const CHAR *litai_str="-LiTai- "; 
	const CHAR *armsys_str="ARMSYS44B0 "; 
	const CHAR *fat16_str="FAT16   "; 
	blocknum=((Sizeofdisk_M<<20)>>9)>>5; 
    for(i=0;ibsBPB); 
		 ext = (EXTBOOT *)(bootsector->bsExt); 
		  
		 bootsector->bsJump[0] = 0xeb; 
		 bootsector->bsJump[1] = 0x03; 
		 bootsector->bsJump[2] = 0x90; 
		 for(i=0;i<7;i++) 
		   bootsector->bsOemName[i] = *litai_str++; 
		 bootsector->bsOemName[7]='\0';  
		 bootsector->bsBootSectSig0 = BOOTSIG0; 
		 bootsector->bsBootSectSig1 = BOOTSIG1; 
		  
		 bpb->bpbBytesPerSec = 512; 
		 bpb->bpbSecPerClust = 32; 
		 if(FilesysType==PART_TYPE_FAT12||FilesysType==PART_TYPE_DOSFAT16 
		 ||FilesysType==PART_TYPE_FAT16||FilesysType==PART_TYPE_FAT16LBA) 
		     bpb->bpbResSectors = 1; 
		 else if(FilesysType==PART_TYPE_FAT32||FilesysType==PART_TYPE_FAT32LBA) 
		     bpb->bpbResSectors = 32; 
		 bpb->bpbFATs = 2; 
		 bpb->bpbRootDirEnts = ((bpb->bpbSecPerClust)-1-(Sizeofdisk_M >> 1)) << 4; 
		 bpb->bpbSectors = Sizeofdisk_M << 11; 
		 bpb->bpbMedia = 0xf0;//必须与FAT[0]一致。 
		 fatsec = bpb->bpbFATsecs = Sizeofdisk_M >> 2; 
		 bpb->bpbSecPerTrack = 0; 
		 bpb->bpbHeads = 0; 
		 bpb->bpbHiddenSecs = 0; 
		 bpb->bpbHugeSectors = Sizeofdisk_M << 11; 
		  
		 ext->exDriveNumber = 0x80; 
		 ext->exReserved1 = 0; 
		 ext->exBootSignature = EXBOOTSIG; 
		 ext->exVolumeID = 0x88331446; 
		 for(i=0;i<10;i++) 
		 ext->exVolumeLabel[i] = *armsys_str++; 
		 ext->exVolumeLabel[10]='\0'; 
		 for(i=0;i<7;i++) 
		 ext->exFileSysType[i] = *fat16_str++; 
		 ext->exFileSysType[8]='\0'; 
		  
		 memcpy(ClusterBuffer[0],SectorBuffer,512); 
		  
		 //第1个扇区开始是FAT及FAT备份区 
		  
		 for(i=0;i<512;i++) 
		 SectorBuffer[i]=0x00; 
		  
		 for(i=1;i<(fatsec*2+1);i++) 
		 memcpy(ClusterBuffer[i],SectorBuffer,512); 
		  
		 ClusterBuffer[1][0]=0xf0;//0xf8? 
		 ClusterBuffer[1][1]=0xff; 
		 ClusterBuffer[1][2]=0xff; 
		 ClusterBuffer[1][3]=0xff; 
		  
		 ClusterBuffer[fatsec+1][0]=0xf0;//0xf8? 
		 ClusterBuffer[fatsec+1][1]=0xff; 
		 ClusterBuffer[fatsec+1][2]=0xff; 
		 ClusterBuffer[fatsec+1][3]=0xff; 
		  
		 //从第fatsec*2+1个扇区开始,是根目录区,到簇的最后,应该清零 
		 for(i=fatsec*2+1;i<32;i++) 
		 memcpy(ClusterBuffer[i],SectorBuffer,512); 
		  
		 for(i=0;i<32;i++)//一扇区接一扇区写入 
         { 
    	    for(j=0;j<255;j++);//延时 
    	    temp=WritePage(0,i,ClusterBuffer[i]); 
    	    if(temp==0) 
    	    { 
    	    	Uart_Printf("\nFormat Nand-flash failed!"); 
    	    	return 0; 
    	    } 
         }  
         Uart_Printf("\nFormat Nand-flash Successfully!\n"); 
         return 1; 
     } 
	return 0; 
} 
 
 //PARTRECORD PartInfo; 
 unsigned char Fat32Enabled; 
 unsigned int  FirstDataSector; 
 unsigned int  BytesPerSector; 
 unsigned int  FATsectors; 
 unsigned int  SectorsPerCluster; 
 unsigned int  FirstFATSector; 
 unsigned int  FirstDirSector; 
 unsigned int  FileSize; 
 unsigned int  FatInCache = 0;  
 DWORD RootDirSectors;	// Numbers of sectors occupied by Root Directory. 
 DWORD RootDirCount; 
 
//--------------该函数主要用于从已有的存储介质中获得文件系统信息------------------// 
 unsigned char fatInit(void) 
 { 
     BOOTSECTOR50 *bootsector;  
	 BPB50 *bpb; 
	 EXTBOOT *ext;	  
	 int i,j; 
	  
     for(j=0;j<255;j++); 
     ReadPage(0,0,SectorBuffer); 
     bootsector = (BOOTSECTOR50 *)SectorBuffer; 
	 bpb = (BPB50 *)(bootsector->bsBPB); 
	 ext = (EXTBOOT *)(bootsector->bsExt); 
     // setup global disk constants 
     FirstDataSector = 0;//PartInfo.prStartLBA; 
     if(bpb->bpbFATsecs) 
     { 
         // bpbFATsecs is non-zero and is therefore valid 
         FirstDirSector = bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbFATsecs; 
                           //FAT12,16 =1         =2(2份FAT,其中1份为备份)×每一份FAT所占用的sector数                
     } 
      
     SectorsPerCluster   = bpb->bpbSecPerClust;//每cluster的sector数目 
     BytesPerSector      = bpb->bpbBytesPerSec;//每sector的字节数 
     FirstFATSector      = bpb->bpbResSectors + 0;//PartInfo.prStartLBA;//FAT区的起始地址 
     FATsectors          = bpb->bpbFATsecs; 
     FirstDataSector  = FirstDirSector+((bpb->bpbRootDirEnts)>>4); 
     RootDirCount = bpb->bpbRootDirEnts; 
     RootDirSectors = (RootDirCount*32)>>9; 
            
 #ifdef DEBUG_FAT 
 
     Uart_Printf("\nOEM name        : %s",(char *)(bootsector->bsOemName)); 
      
     //Uart_Printf("\nFirst sector    : %4x",PartInfo.prStartLBA);     
     //Uart_Printf("\nSize            : %4x",PartInfo.prSize);         
     Uart_Printf("\nbytes per sector    : %4d",bpb->bpbBytesPerSec);     
     Uart_Printf("\nsectors per cluster : %4d",bpb->bpbSecPerClust);     
     Uart_Printf("\nreserved sectors: %4d",bpb->bpbResSectors);      
     Uart_Printf("\nRootDir Entrys  : %4d",bpb->bpbRootDirEnts); 
     Uart_Printf("\nTolSectors      : %4d",bpb->bpbSectors); 
     Uart_Printf("\nFatSectors      : %4d",bpb->bpbFATsecs);         
     //Uart_Printf("\nBigFatSectors   : %4x",bpb->bpbBigFATsecs);      
     Uart_Printf("\nNumber of Fats  : %4d",bpb->bpbFATs);            
     Uart_Printf("\nFirst Fat Sector: %4d",FirstFATSector);  
     Uart_Printf("\nFirst Dir sector: %4d",FirstDirSector);         
     Uart_Printf("\nFirst Data Sect : %4d",FirstDataSector);         
     //Uart_Printf("\nVolNumber       : %x",(unsigned int)(ext->exVolumeID));  
     Uart_Printf("\nVolumeLabel    : %s\n",(char *)(ext->exVolumeLabel));         
 #endif 
     for(i=0;i>8; 
		} 
		memcpy(ClusterBuffer[i+FirstFATSector],SectorBuffer,BytesPerSector); 
	} 
	for(i=0;i>8; 
		} 
		memcpy(ClusterBuffer[i+FirstFATSector+FATsectors],SectorBuffer,BytesPerSector); 
	} 
	Erase_Cluster(0);//写入之前,擦除当前簇; 
	for(i=0;ideName[0] == '\0' || dir->deName[0] == 0xe5) 
				{ 
					memcpy((BYTE *)dir, (BYTE *)new_dir, sizeof(DIRENTRY));	//将新的目录信息写入				 
					Flush();//更新disk中该扇区 
					if(fp)//更新文件信息 
					{ 
						fp->DirSectorNum = DirSectorNum;//当前目录项所在的扇区地址 
						fp->DirIndex = ((BYTE*)dir - Cache) / sizeof(DIRENTRY);//目录索引,即该扇区中第x个目录项 
						memcpy((BYTE *)(&fp->dir), (BYTE *)new_dir, sizeof(DIRENTRY));//新的目录信息写到文件结构中 
					} 
					return 0;//操作成功,退出 
				} 
			} 
			DirSectorNum++;//下一个根目录扇区 
		} 
		// root dir have no room. 
		return 3;  
	} 
	 
	else//不在根目录区 
	{ 
		Cluster = SectorNum2ClusterNum(DirSectorNum);// 
		 
		while(Cluster != 0xffff) 
		{ 
			for(i=0; i< SectorsPerCluster; i++)//在整个簇中搜索 
			{ 
				Cache = GetSectorData(DirSectorNum); 
				if(Cache == NULL) 
					return 2; 
				 
				for(dir = (DIRENTRY *)Cache; (BYTE*)dir < Cache + BytesPerSector; dir++) 
				{ 
					if(dir->deName[0] == '\0' || dir->deName[0] == 0xe5) 
					{ 
						memcpy((BYTE *)dir, (BYTE *)new_dir, sizeof(DIRENTRY)); 
						Flush(); 
						 
						if(fp) 
						{ 
							fp->DirSectorNum = DirSectorNum; 
							fp->DirIndex = ((BYTE*)dir - Cache) / sizeof(DIRENTRY); 
							memcpy((BYTE *)(&fp->dir),(BYTE *)new_dir, sizeof(DIRENTRY)); 
						} 
						return 0; 
					} 
				} 
				DirSectorNum++;//下一个扇区 
			} 
			//搜索完当前簇,没有空的目录项 
			PrevCluster = Cluster;//从FAT表中找出下一簇 
			Cluster = GetNextClusterNum(Cluster); 
			DirSectorNum = ClusterNum2SectorNum(Cluster);//刷新目录扇区 
		} 
		//且这已经是最后一个簇 
		// 
		// we have to extend this parent dir room. 
		// 
		Cluster = AllocCluster(PrevCluster);//利用FAT表获得一个空簇 
		if(Cluster == 0xffff)//没有空簇 
			return 4; 
		 
		DirSectorNum = ClusterNum2SectorNum(Cluster);//空簇做新的目录扇区地址 
		 
		Cache = GetSectorData(DirSectorNum); 
		if(Cache == NULL) 
			return 2; 
		 
		dir = (DIRENTRY *)Cache; 
		 
		memcpy((BYTE *)dir, (BYTE *)new_dir, sizeof(DIRENTRY)); 
		Flush(); 
		 
		if(fp) 
		{ 
			fp->DirSectorNum = DirSectorNum; 
			fp->DirIndex = ((BYTE*)dir - Cache) / sizeof(DIRENTRY); 
			memcpy((BYTE *)(&fp->dir), (BYTE *)new_dir, sizeof(DIRENTRY)); 
		} 
		 
		return 0; 
	} 
 
	return 5; 
} 
 
int DeleteDir(_FILE *file) 
{ 
	BYTE* Cache; 
	DIRENTRY *dir; 
 
	Cache = GetSectorData(file->DirSectorNum);//文件在目录区的扇区地址 
	if(Cache == NULL) 
		return 1; 
 
	dir = (DIRENTRY *)Cache; 
	dir += file->DirIndex;//目录的索引号 
 
	dir->deName[0] = 0xe5;//做删除标记 
	Flush(); 
 
	return 0; 
} 
 
// helper functions 
 
// NULL indicate failed. 
// Valid format is full path:	\[8.3\]*DIR_Name检验文件路径字符串是否合法 
// limits: 
// length < 80 && !(special char) 
char* get_valid_format(const char *fullpath) 
{ 
	static char static_path[512]; 
	char* p=static_path; 
	char path[80]; 
	char* ppath = path; 
	int dir_len_count; //count dir len. 
	int i; 
 
	if(fullpath == NULL || strlen(fullpath) >=80 || *fullpath != '\\')//第一个字符是‘\’ 
		return NULL; 
 
	if(strlen(fullpath) > 1 && fullpath[strlen(fullpath)-1] =='\\')//最后一个字符是‘\’ 
		return NULL; 
 
	strcpy(path, fullpath); 
	//strupr(path); 
	memset(p, 0, 512); 
 
	for(;;) 
	{ 
		switch(*ppath) 
		{ 
		case 0x00://结束符 
			{ 
				if(dir_len_count != 0) // prev is not '\\' 
				{ 
					for(i=0; i<(11 - dir_len_count); i++)//未满11字节,用blank填满 
					{ 
						*p = 0x20; 
						p++; 
					} 
				} 
			} 
			return static_path;//返回整个字符串 
 
		case '\\': 
			{ 
				if(p != static_path) // this is not the first '\\' 
				{ 
					if(dir_len_count == 0)// more than one '\\' 
						return NULL; 
 
					for(i=0; i<(11 - dir_len_count); i++) 
					{ 
						*p = 0x20; 
						p++; 
					} 
				} 
				 
				*p = '\\'; 
				p++; 
				 
				ppath++; 
				dir_len_count =0; 
				continue; 
			} 
			break; 
 
		case '.': 
			{ 
				if(dir_len_count > 8 || dir_len_count ==0) // '\\.' check 
					return NULL; 
 
				if(ppath[1] == '.' || ppath[1] == '\\') // more than one '.' or '.\\' check 
					return NULL; 
 
				for(i=0; i<(8 - dir_len_count); i++) 
				{ 
					*p = 0x20; 
					p++; 
				} 
 
				dir_len_count =8; 
				ppath++; 
				continue; 
			} 
			break; 
 
		case 0x22://非法字符 
		case 0x2A: 
		case 0x2B: 
		case 0x2C: 
		case 0x2F: 
		case 0x3A: 
		case 0x3B: 
		case 0x3C: 
		case 0x3D: 
		case 0x3E: 
		case 0x3F: 
		case 0x5B: 
		case 0x5D: 
		case 0x7C: 
			return NULL; 
 
		default: 
			{ 
				if(*ppath < 0x20) 
					return NULL;				 
			} 
			break; 
		} 
 
		*p = *ppath; 
		dir_len_count ++; 
 
		if(dir_len_count > 11) 
			return NULL; 
 
		p++; 
		ppath++; 
	} 
 
	return static_path; 
} 
//11个字符,其中8个字符为文件名,3个字符为文件后缀 
void unformat_name(char * filename, const unsigned char dirname[11]) 
{ 
	int i; 
	int j; 
 
	memset(filename, 0, 13); 
 
	for(i=0; i<8; i++) 
	{ 
		if(dirname[i] != 0x20) 
			filename[i] = dirname[i]; 
		else 
			break; 
	} 
	 
	if(dirname[8] != 0x20) 
	{ 
		filename[i] = '.'; 
		j = i + 1; 
		 
		for(i=8; i<11; i++,j++) 
		{ 
			if(dirname[i] != 0x20) 
				filename[j] = dirname[i]; 
			else 
				break; 
		} 
	} 
} 
//在所给的sector内寻找与dirname名称相同的项目 
DWORD SectorSearch(DWORD Sector, const char dirname[11],  _FILE *file) 
{ 
	BYTE* Cache; 
	DIRENTRY *dir; 
	unsigned int j; 
 
	Cache = GetSectorData(Sector); 
	if(Cache == NULL) 
		return 0xffffffff; 
	 
	dir = (DIRENTRY *)Cache; 
	for(j=0; (dir->deName[0] != '\0') && (j< BytesPerSector / sizeof(DIRENTRY)); j++)//不是空的目录项,在整个扇区搜索 
	{ 
		if(memcmp((const char*)dir->deName, dirname, 11) == 0 && (!(dir->deAttributes & ATTR_VOLUME)))// not volumn id or long name entry. 
		//如果目录名/文件名相同,且不是卷标项目 
		{ 
			if(file != NULL) 
			{ 
				memset((BYTE *)file, 0, sizeof(_FILE)); 
				file->DirSectorNum = Sector; 
				file->DirIndex = j; 
				memcpy((BYTE *)(&file->dir), (BYTE *)dir, sizeof(DIRENTRY)); 
			} 
			return ClusterNum2SectorNum(dir->deStartCluster);//返回该目录/文件的起始簇号 
		} 
		dir++; 
	} 
	return 0xffffffff; 
} 
//在所给sector内寻找未被删除且不是卷标项的目录项,记录项目名称 
int SectorGet(DWORD Sector, FatGet *fat_get) 
{ 
	BYTE* Cache; 
	DIRENTRY *dir; 
	unsigned int j; 
 
	Cache = GetSectorData(Sector); 
	if(Cache == NULL) 
		return 1; 
 
	dir = (DIRENTRY *)Cache; 
	dir += fat_get->DirIndex; 
 
	for(j=fat_get->DirIndex; (dir->deName[0] != '\0') && (j< BytesPerSector / sizeof(DIRENTRY)); j++) 
	{ 
		if(dir->deName[0] != 0xe5 && (!(dir->deAttributes & ATTR_VOLUME)))// not volumn id or long name entry. 
		{ 
			fat_get->DirSectorNum = Sector; 
			fat_get->DirIndex = j + 1; 
			unformat_name(fat_get->filename, dir->deName); 
 
			return 0; 
		} 
 
		dir++; 
	} 
 
	return 2; 
} 
//在根目录区或者数据区寻找是否有与dirname名称相同的项目 
// return the first sector number of dir/file entry. 
// 0xffffffff indicate failed. 
DWORD fat_search(DWORD Sector, const char dirname[11], _FILE *file) 
{	 
	unsigned int i; 
	WORD Cluster; 
	DWORD FirstSectorOfFile; 
 
	//if(dirname == NULL) 
		//return 0xffffffff; 
	 
	if(Sector == FirstDirSector)//指定根目录 
	{ 
		for(i=0; i<(RootDirCount * sizeof(DIRENTRY) / BytesPerSector); i++)//在整个根目录区寻找 
		{ 
			FirstSectorOfFile = SectorSearch(Sector++, dirname, file);//寻找与dirname名称相同的目录/文件 
			if(FirstSectorOfFile != 0xffffffff)                       //返回目录/文件的第一簇 
				return FirstSectorOfFile; 
		} 
	} 
	else 
	{ 
		Cluster = SectorNum2ClusterNum(Sector);//非根目录 
 
		// because arg Sector is the first sector of parent dir content, 
		// so it is the first sector of the cluster. 
		/* 
		i = (Sector - FirstDataSector) % Bpb.SecPerClus; 
		 
		if(i != 0) 
		{ 
			for(; i< Bpb.SecPerClus; i++) 
			{ 
				FirstSectorOfFile = SectorSearch(Sector++, dirname, file); 
				if(FirstSectorOfFile != 0xffffffff) 
					return FirstSectorOfFile; 
			} 
 
			Cluster = GetNextClusterNum(Cluster); 
			Sector = ClusterNum2SectorNum(Cluster); 
		}*/ 
		 
		while(Cluster != 0xffff)//不是最后一簇 
		{ 
			for(i=0; i< SectorsPerCluster; i++) 
			{ 
				FirstSectorOfFile = SectorSearch(Sector++, dirname, file);//寻找名称相同的目录/文件项 
				if(FirstSectorOfFile != 0xffffffff) 
					return FirstSectorOfFile; 
			} 
 
			Cluster = GetNextClusterNum(Cluster); 
			Sector = ClusterNum2SectorNum(Cluster); 
		} 
	} 
 
	return 0xffffffff;//找不到 
} 
//定位文件,即在根目录区查找到它的第一级目录,在下一个簇查找到它的第二级目录……,直到最终定位文件。 
// return the first sector number of dir/file content. 
// 0xffffffff indicate failed. 
// if path is root dir, file arg is ignore. 
DWORD fat_locate(const char *path, _FILE *file) 
{ 
	DWORD Sector = FirstDirSector; 
	char *p; 
 
	p = get_valid_format(path);//判断是否合法 
	if(p == NULL) 
		return 0xffffffff; 
 
	// locate first sub dir. 
	p++;//忽略第一个‘\’ 
 
	// locate next sub dir(s). 
	for(;;) 
	{ 
		if(*p == NULL) 
			return Sector; 
		Sector = fat_search(Sector, p, file);//在根目录区寻找是否有与P同名的目录/文件项 
		if(Sector == 0xffffffff) 
			return 0xffffffff; 
 
		p+=12; 
	} 
	// we never go here. 
	return 0xffffffff; 
} 
//获得当前的系统时间 
void fat_datetime(FatDateTime *fatdatetime) 
{ 
	int year,month,day,weekday,hour,min,sec; 
	WORD pdate = fatdatetime->Date; 
	WORD ptm = fatdatetime->Time; 
 
	if(rBCDYEAR == 0x99)  
	    year = 0x1999; 
	else  
	    year = 0x2000 + rBCDYEAR; 
	    month=rBCDMON; 
	    day=rBCDDAY; 
	    weekday=rBCDDATE; 
	    hour=rBCDHOUR; 
	    min=rBCDMIN; 
	    sec=rBCDSEC; 
 
	pdate = ((day << DD_DAY_SHIFT)&DD_DAY_MASK)+((month <TimeTenth = (sec % 2) * 100; //+ systm.wMilliseconds / 10; 
} 
 
/////////////////////////////////////////////////////////////////// 
// fat apis 
/////////////////////////////////////////////////////////////////// 
//创建目录 
int fat_mkdir( const char *dirname)//仅1级目录: 父目录\新目录 
{ 
	DIRENTRY dir; 
	DWORD SectorNum; 
	char path[512]; 
	char name[11]; 
	char *p; 
	FatDateTime tm; 
	_FILE file;	 
	BYTE* Cache; 
	DIRENTRY *pdir; 
	WORD NewCluster; 
	char dot[11] = {'.', 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; 
	char dotdot[11] = {'.', '.', 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; 
 
	// is path format correct ? 
	p = get_valid_format(dirname); 
	if(p == NULL) 
		return 1; 
 
	//if exist this dir ? 
	if(fat_locate(dirname, NULL) != 0xffffffff) 
		return 4; 
 
	//separate path into parent and name(directory name) 
	strncpy(name, &p[strlen(p)-11], 11);//拷贝新的目录名->name 
    //获得了文件的第一级目录(parent path)名称 
	strcpy(path, dirname); 
	p = strrchr(path, '\\');//返回path中‘\’第一次出现的指针 
	if(p == path) // it is root dir. 
		*(p+1) = '\0'; 
	else 
		*p = '\0'; 
     
	//locate parent path 
	SectorNum = fat_locate(path, NULL);//获取第一级目录指向第一个扇区的地址 
	if(SectorNum == 0xffffffff) 
		return 2; 
 
	//fill dir attributes 
	memset((BYTE *)&dir, 0, sizeof(dir)); 
	memcpy((BYTE *)(dir.deName), name, 11); 
	dir.deAttributes = ATTR_DIRECTORY;//目录属性 
	fat_datetime(&tm); 
	dir.CrtDate = dir.LstAccDate = dir.WrtDate = tm.Date; 
	dir.CrtTime = dir.WrtTime = tm.Time; 
	dir.CrtTimeTenth = tm.TimeTenth; 
 
	//alloc one dir在父目录所指的扇区下获得一个新的目录项 
	if(AllocDir(SectorNum, &dir, &file) != 0) 
		return 3; 
 
	//alloc a cluster 
	NewCluster = AllocCluster(0); 
	if(NewCluster == 0xffff) 
		return 4; 
 
	//flush to disk 
	Cache = GetSectorData(file.DirSectorNum);//将新的目录项所在扇区读入 
	if(Cache == NULL) 
		return 6; 
 
	pdir = (DIRENTRY *)Cache; 
	pdir += file.DirIndex; 
 
	pdir->deStartCluster = NewCluster;//指向新的一簇 
	Flush(); 
 
	//create . and .. dir items. 
	Cache = GetSectorData(ClusterNum2SectorNum(NewCluster));//将新簇的第一个扇区读入 
	if(Cache == NULL) 
		return 6; 
 
	pdir = (DIRENTRY *)Cache;//获得一个目录项本地目录:.? 
	memset((BYTE *)pdir, 0, sizeof(DIRENTRY)); 
	memcpy((BYTE *)(pdir->deName), dot, 11); 
	pdir->deAttributes = ATTR_DIRECTORY; 
	fat_datetime(&tm);//获得当前系统的时间,填写当前目录项的属性 
	pdir->CrtDate = pdir->LstAccDate = pdir->WrtDate = tm.Date; 
	pdir->CrtTime = pdir->WrtTime = tm.Time; 
	pdir->CrtTimeTenth = tm.TimeTenth; 
	pdir->deStartCluster = NewCluster;//指向本地 
 
	pdir++;//获得一个目录项父目录:.. 
	memset((BYTE *)pdir, 0, sizeof(DIRENTRY)); 
	memcpy((BYTE *)(pdir->deName), dotdot, 11); 
	pdir->deAttributes = ATTR_DIRECTORY; 
	fat_datetime(&tm); 
	pdir->CrtDate = pdir->LstAccDate = pdir->WrtDate = tm.Date; 
	pdir->CrtTime = pdir->WrtTime = tm.Time; 
	pdir->CrtTimeTenth = tm.TimeTenth; 
	pdir->deStartCluster = SectorNum2ClusterNum(SectorNum); 
 
	Flush(); 
 
	return 0; 
} 
 
//删除目录 
int fat_rmdir( const char *dirname) 
{ 
	DWORD SectorNum; 
	_FILE file; 
	char filename[13]; 
 
	//is dir have no sub dir or file ? 
	if(fat_getfirst(dirname, filename) == 0) 
		return 3; 
 
	//locate 
	SectorNum = fat_locate(dirname, &file); 
	if(SectorNum == 0xffffffff) 
		return 4; 
 
	// is it a dir ? 
	if(!(file.dir.deAttributes & ATTR_DIRECTORY)) 
		return 6; 
 
	if(DeleteDir(&file) != 0) 
		return 5; 
 
	FreeCluster(file.dir.deStartCluster); 
 
	return 0; 
} 
 
FatGet fat_get; 
//path所指目录下是否有子目录或文件,获得第一个子目录/文件名 
int fat_getfirst(const char *path, char* filename) 
{ 
	DWORD Sector; 
	unsigned int i; 
	WORD Cluster; 
 
	//if exist this dir ? 
	Sector = fat_locate(path, NULL); 
	if(Sector == 0xffffffff) 
		return 1; 
 
	if(Sector ==FirstDirSector) 
	{ 
		fat_get.IsRootDir = 1; 
		fat_get.DirIndex = 2; 
 
		for(i=0; i= sizeof(handles)/sizeof(_FILE)) 
		return -1; 
 
	fp = &handles[handle]; 
 
	fat_datetime(&tm); 
	fp->dir.LstAccDate = fp->dir.WrtDate = tm.Date; 
	fp->dir.WrtTime = tm.Time; 
 
	Cache = GetSectorData(fp->DirSectorNum); 
	if(Cache == NULL) 
		return -2; 
 
	dir = (DIRENTRY *)Cache; 
	dir += fp->DirIndex; 
 
	memcpy((BYTE *)dir, (BYTE *)&fp->dir, sizeof(DIRENTRY)); 
	Flush(); 
    FlushFAT(); 
	handles[handle].valid = 0; 
	return 0; 
} 
 
int fat_creat(const char* filename, BYTE attribute) 
{ 
	DIRENTRY dir; 
	char path[512]; 
	char name[11]; 
	char *p; 
	DWORD ParentDirSectorNum; 
	FatDateTime tm; 
	_FILE file; 
	DIRENTRY *pdir; 
	WORD NewCluster; 
	BYTE* Cache; 
 
	// is path format correct ? 
	p = get_valid_format(filename); 
	if(p == NULL) 
		return -2; 
 
	//if exist this file ? 
	if(fat_locate(filename, NULL) != 0xffffffff) 
		return -3; 
 
	//separate path into parent and name 
	strncpy(name, &p[strlen(p)-11], 11); 
 
	strcpy(path, filename); 
	p = strrchr(path, '\\'); 
	*p = '\0'; 
 
	//locate parent path 
	ParentDirSectorNum = fat_locate(path, NULL); 
	if(ParentDirSectorNum == 0xffffffff) 
		return -4; 
 
	//fill dir attributes 
	memset((BYTE *)&dir, 0, sizeof(dir)); 
	memcpy((BYTE *)(dir.deName), name, 11); 
	dir.deAttributes = attribute; 
	fat_datetime(&tm); 
	dir.CrtDate = dir.LstAccDate = dir.WrtDate = tm.Date; 
	dir.CrtTime = dir.WrtTime = tm.Time; 
	dir.CrtTimeTenth = tm.TimeTenth; 
	dir.deFileSize = 0; 
 
	//alloc one dir 
	if(AllocDir(ParentDirSectorNum, &dir, &file) != 0) 
		return -5; 
 
	//alloc a cluster 
	NewCluster = AllocCluster(0); 
	if(NewCluster == 0xffff) 
		return -6; 
 
	//flush to disk 
	Cache = GetSectorData(file.DirSectorNum); 
	if(Cache == NULL) 
		return -7; 
 
	pdir = (DIRENTRY *)Cache; 
	pdir += file.DirIndex; 
 
	pdir->deStartCluster= NewCluster; 
	Flush(); 
 
	return fat_open(filename); 
} 
 
long fat_lseek(int handle, long offset, int origin) 
{ 
	_FILE *fp; 
	WORD Cluster; 
	unsigned int len; 
	int i; 
 
	if(handle <0 || handle >= sizeof(handles)/sizeof(_FILE)) 
		return 0; 
 
	fp = &handles[handle]; 
 
	switch(origin) 
	{ 
	case SEEK_SET: 
		{ 
			if(offset < 0) 
				return (-1); 
 
			fp->offset = offset; 
		} 
		break; 
 
	case SEEK_CUR: 
		{ 
			if((fp->offset + offset) <0 ) 
				return (-1); 
 
			fp->offset += offset; 
		} 
		break; 
 
	case SEEK_END: 
		{ 
			if((fp->offset + offset) <0 ) 
				return (-1); 
 
			fp->offset = fp->dir.deFileSize + offset; 
		} 
		break; 
 
	default: 
		return (-2); 
	} 
 
	// re-locate CurrentSectorNum, SectorOffset 
	Cluster = fp->dir.deStartCluster; 
	fp->CurrentSectorNum = ClusterNum2SectorNum(Cluster); 
	len = 0; 
 
	while(Cluster != 0xffff) 
	{ 
		for(i=0; i< SectorsPerCluster; i++) 
		{ 
			len += BytesPerSector; 
 
			if(len >= fp->offset) 
			{ 
				fp->SectorOffset = fp->offset % BytesPerSector; 
				return fp->offset; 
			} 
			 
			fp->CurrentSectorNum ++; 
		} 
 
		Cluster = GetNextClusterNum(Cluster); 
		fp->CurrentSectorNum = ClusterNum2SectorNum(Cluster); 
	} 
 
	return handles[handle].offset; 
} 
 
int fat_open(const char* filename) 
{ 
	int i; 
	_FILE * fp = NULL; 
	DWORD FirstSectorNum; 
 
	for(i=0; i<16; i++) 
	{ 
		if(!handles[i].valid) 
		{ 
			fp = &handles[i]; 
			break; 
		} 
	} 
 
	if(fp == NULL) 
		return -1; 
 
	FirstSectorNum = fat_locate(filename, fp); 
	if(FirstSectorNum == 0xffffffff) 
		return -2; 
 
	fp->StartSectorNum = FirstSectorNum; 
	fp->CurrentSectorNum = fp->StartSectorNum; 
	fp->SectorOffset = 0; 
	fp->offset = 0; 
	fp->valid = 1; 
	return i; 
} 
 
unsigned int fat_read(int handle, void* buffer, unsigned int bytes) 
{ 
	BYTE* Cache; 
	unsigned int read_bytes =0; 
	unsigned int max_copy_bytes_in_sector; 
	_FILE *fp; 
	WORD Cluster; 
	int i; 
 
	if(handle <0 || handle >= sizeof(handles)/sizeof(_FILE)) 
		return 0; 
 
	fp = &handles[handle]; 
	bytes = (fp->dir.deFileSize - fp->offset) > bytes ? bytes : (fp->dir.deFileSize - fp->offset); 
 
	Cluster = SectorNum2ClusterNum(fp->CurrentSectorNum); 
 
	i = (fp->CurrentSectorNum - FirstDataSector) % SectorsPerCluster; 
 
	if(i != 0) 
	{ 
		for(; i< SectorsPerCluster; i++) 
		{ 
			Cache = GetSectorData(fp->CurrentSectorNum); 
			if(Cache == NULL) 
				return 0; 
 
			Cache += fp->SectorOffset; 
			max_copy_bytes_in_sector = (BytesPerSector - fp->SectorOffset) > (bytes - read_bytes) ? (bytes - read_bytes) : (BytesPerSector- fp->SectorOffset); 
			memcpy(buffer, Cache, max_copy_bytes_in_sector); 
 
			read_bytes += max_copy_bytes_in_sector; 
			fp->SectorOffset += max_copy_bytes_in_sector; 
			fp->offset += max_copy_bytes_in_sector; 
			buffer = (char*)buffer + max_copy_bytes_in_sector; 
 
			if(fp->SectorOffset == BytesPerSector) 
			{ 
				if(i == SectorsPerCluster -1) 
				{ 
					Cluster = GetNextClusterNum(Cluster); 
					if(Cluster != 0xffff) 
						fp->CurrentSectorNum = ClusterNum2SectorNum(Cluster); 
				} 
				else 
					fp->CurrentSectorNum ++; 
 
				fp->SectorOffset = 0; 
			} 
 
			if(read_bytes == bytes) 
			{ 
				return bytes; 
			} 
		} 
	} 
	 
	while(Cluster != 0xffff) 
	{ 
		for(i=0; i< SectorsPerCluster; i++) 
		{ 
			Cache = GetSectorData(fp->CurrentSectorNum); 
			if(Cache == NULL) 
				return 0; 
 
			Cache += fp->SectorOffset; 
			max_copy_bytes_in_sector = (BytesPerSector- fp->SectorOffset) > (bytes - read_bytes) ? (bytes - read_bytes) : (BytesPerSector- fp->SectorOffset); 
			memcpy(buffer, Cache, max_copy_bytes_in_sector); 
			 
			read_bytes += max_copy_bytes_in_sector; 
			fp->SectorOffset += max_copy_bytes_in_sector; 
			fp->offset += max_copy_bytes_in_sector; 
			buffer = (char*)buffer + max_copy_bytes_in_sector; 
 
			if(fp->SectorOffset == BytesPerSector) 
			{				 
				if(i == SectorsPerCluster -1) 
				{ 
					Cluster = GetNextClusterNum(Cluster); 
					if(Cluster != 0xffff) 
						fp->CurrentSectorNum = ClusterNum2SectorNum(Cluster); 
				} 
				else 
					fp->CurrentSectorNum ++; 
 
				fp->SectorOffset = 0; 
			} 
 
			if(read_bytes == bytes) 
			{ 
				return bytes; 
			} 
		}		 
	} 
 
	return 0; 
} 
 
unsigned int fat_write(int handle, const char* buffer, unsigned int bytes) 
{ 
	BYTE* Cache; 
	unsigned int write_bytes =0; 
	unsigned int max_write_bytes_in_sector; 
	_FILE *fp; 
	WORD Cluster; 
	WORD PrevCluster; 
	int i; 
 
	if(handle <0 || handle >= sizeof(handles)/sizeof(_FILE)) 
		return 0; 
 
	fp = &handles[handle]; 
 
	Cluster = SectorNum2ClusterNum(fp->CurrentSectorNum); 
	PrevCluster = Cluster; 
 
	i = (fp->CurrentSectorNum - FirstDataSector) % SectorsPerCluster; 
 
	if(i != 0) 
	{ 
		for(; i< SectorsPerCluster; i++) 
		{ 
			Cache = GetSectorData(fp->CurrentSectorNum); 
			if(Cache == NULL) 
				return 0; 
 
			Cache += fp->SectorOffset; 
			max_write_bytes_in_sector = (BytesPerSector- fp->SectorOffset) > (bytes - write_bytes) ? (bytes - write_bytes) : (BytesPerSector - fp->SectorOffset); 
			memcpy(Cache, buffer, max_write_bytes_in_sector); 
			Flush(); 
 
			write_bytes += max_write_bytes_in_sector; 
			fp->SectorOffset += max_write_bytes_in_sector; 
			fp->offset += max_write_bytes_in_sector; 
			buffer = (char*)buffer + max_write_bytes_in_sector; 
			fp->dir.deFileSize +=  max_write_bytes_in_sector; 
 
			if(fp->SectorOffset == BytesPerSector) 
			{ 
				if(i == SectorsPerCluster -1) 
				{ 
					PrevCluster = Cluster; 
					Cluster = GetNextClusterNum(Cluster); 
					if(Cluster != 0xffff) 
						fp->CurrentSectorNum = ClusterNum2SectorNum(Cluster); 
					else 
					{ 
						Cluster = AllocCluster(PrevCluster); 
						if(Cluster == 0xffff) 
							return 0; 
						 
						fp->CurrentSectorNum = ClusterNum2SectorNum(Cluster); 
					} 
				} 
				else 
					fp->CurrentSectorNum ++; 
 
				fp->SectorOffset = 0; 
			} 
 
			if(write_bytes == bytes) 
			{ 
				return bytes; 
			} 
		} 
	} 
 
	for(;;) 
	{ 
		for(i=0; i< SectorsPerCluster; i++) 
		{ 
			Cache = GetSectorData(fp->CurrentSectorNum); 
			if(Cache == NULL) 
				return 0; 
 
			Cache += fp->SectorOffset; 
			max_write_bytes_in_sector = (BytesPerSector - fp->SectorOffset) > (bytes - write_bytes) ? (bytes - write_bytes) : (BytesPerSector - fp->SectorOffset); 
			memcpy(Cache, buffer, max_write_bytes_in_sector); 
			Flush(); 
 
			write_bytes += max_write_bytes_in_sector; 
			fp->SectorOffset += max_write_bytes_in_sector; 
			fp->offset += max_write_bytes_in_sector; 
			buffer = (char*)buffer + max_write_bytes_in_sector; 
			fp->dir.deFileSize +=  max_write_bytes_in_sector; 
 
			if(fp->SectorOffset == BytesPerSector) 
			{ 
				if(i == SectorsPerCluster -1) 
				{ 
					PrevCluster = Cluster; 
					Cluster = GetNextClusterNum(Cluster); 
					if(Cluster != 0xffff) 
						fp->CurrentSectorNum = ClusterNum2SectorNum(Cluster); 
					else 
					{ 
						Cluster = AllocCluster(PrevCluster); 
						if(Cluster == 0xffff) 
							return 0; 
						 
						fp->CurrentSectorNum = ClusterNum2SectorNum(Cluster); 
					} 
				} 
				else 
					fp->CurrentSectorNum ++; 
 
				fp->SectorOffset = 0; 
			} 
 
			if(write_bytes == bytes) 
			{ 
				return bytes; 
			} 
		} 
	} 
 
	// we can not reach here. 
	return 0; 
} 
 
int fat_remove( const char *filename) 
{ 
	DWORD SectorNum; 
	_FILE file; 
 
	//locate 
	SectorNum = fat_locate(filename, &file); 
	if(SectorNum == 0xffffffff) 
		return 4; 
 
	// is it a dir ? 
	if(file.dir.deAttributes & ATTR_DIRECTORY) 
		return 6; 
 
	if(DeleteDir(&file) != 0) 
		return 5; 
 
	FreeCluster(file.dir.deStartCluster); 
 
	return 0; 
} 
 
int fat_get_stat( const char *filename, _STAT * stat) 
{ 
	DWORD SectorNum; 
	_FILE file; 
 
	//locate 
	SectorNum = fat_locate(filename, &file); 
	if(SectorNum == 0xffffffff) 
		return 1; 
 
	stat->Attr = file.dir.deAttributes; 
	stat->CrtDate = file.dir.CrtDate; 
	stat->CrtTime = file.dir.CrtTime; 
	stat->CrtTimeTenth = file.dir.CrtTimeTenth; 
	stat->FileSize = file.dir.deFileSize; 
	stat->LstAccDate = file.dir.LstAccDate; 
	stat->WrtDate = file.dir.WrtDate; 
	stat->WrtTime = file.dir.WrtTime; 
 
	return 0; 
} 
 
int fat_set_stat( const char *filename, _STAT * stat) 
{ 
	DWORD SectorNum; 
	_FILE file; 
	BYTE* Cache; 
	DIRENTRY *dir; 
 
	//locate 
	SectorNum = fat_locate(filename, &file); 
	if(SectorNum == 0xffffffff) 
		return 1; 
 
	file.dir.deAttributes = stat->Attr; 
	file.dir.CrtDate = stat->CrtDate; 
	file.dir.CrtTime = stat->CrtTime; 
	file.dir.CrtTimeTenth = stat->CrtTimeTenth; 
	file.dir.deFileSize = stat->FileSize; 
	file.dir.LstAccDate = stat->LstAccDate; 
	file.dir.WrtDate = stat->WrtDate; 
	file.dir.WrtTime = stat->WrtTime; 
 
	Cache = GetSectorData(file.DirSectorNum); 
	if(Cache == NULL) 
		return 2; 
 
	dir = (DIRENTRY *)Cache; 
	dir += file.DirIndex; 
 
	memcpy((BYTE *)dir, (BYTE *)&file.dir, sizeof(DIRENTRY)); 
	Flush(); 
 
	return 0; 
} 
 
 
int fat_rename( const char *oldname, const char *newname ) 
{ 
	DIRENTRY dir; 
	char path[512]; 
	char newpath[512]; 
	char name[11]; 
	char new_name[11]; 
	char *p; 
	DWORD ParentDirSectorNum; 
	_FILE old_file; 
 
	// 
	//check oldname file 
	// 
 
	// is path format correct ? 
	p = get_valid_format(oldname); 
	if(p == NULL) 
		return -2; 
 
	//if exist this file ? 
	if(fat_locate(oldname, &old_file) == 0xffffffff) 
		return -3; 
 
	//separate path into parent and name 
	strncpy(name, &p[strlen(p)-11], 11); 
 
	strcpy(path, oldname); 
	p = strrchr(path, '\\'); 
	*p = '\0'; 
 
 
	// 
	//check newname file 
	// 
 
	if(strchr(newname, '\\') != NULL) 
		return -2; 
 
	sprintf(newpath, "%s\\%s", path, newname); 
 
	// is path format correct ? 
	p = get_valid_format(newpath); 
	if(p == NULL) 
		return -2; 
 
	//if exist this file ? 
	if(fat_locate(newpath, NULL) != 0xffffffff) 
		return -3; 
 
	//separate path into parent and name 
	strncpy(new_name, &p[strlen(p)-11], 11); 
 
 
 
	//locate parent path 
	ParentDirSectorNum = fat_locate(path, NULL); 
	if(ParentDirSectorNum == 0xffffffff) 
		return -4; 
 
	//fill dir attributes 
	memcpy((BYTE *)&dir,(BYTE *)(&old_file.dir), sizeof(DIRENTRY)); 
	memcpy((BYTE *)dir.deName, new_name, 11); 
 
	//alloc one dir 
	if(AllocDir(ParentDirSectorNum, &dir, NULL) != 0) 
		return -5; 
 
	//delete old one 
	if(DeleteDir(&old_file) != 0) 
		return -6; 
 
	return 0; 
}