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;i bsBPB); 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;i deName[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; }