📄 fat16.c
字号:
{
SectorBuffer[j*2]=(FatCache[i*256+j])%256;
SectorBuffer[j*2+1]=(FatCache[i*256+j])>>8;
}
memcpy(ClusterBuffer[i+FirstFATSector+FATsectors],SectorBuffer,BytesPerSector);
}
NFEraseBlock(0); //写入之前,擦除当前簇;
for(i=0;i<SectorsPerCluster;i++) //一扇区接一扇区写入
{
for(j=0;j<255;j++); //延时
WritePage(0,i,ClusterBuffer[i]);
}
}
//The sector number of the first sector of that cluster.
//FirstSectorofCluster = ((N – 2) * BPB_SecPerClus) + FirstDataSector;
//Because No MBR,so: clust-1!
unsigned long FirstSectorofCluster(unsigned long clust) //数据存放的cluster转为sector
{
return ((clust-1) * SectorsPerCluster + FirstDataSector);
}
// alloc a free cluster. policy is searching from prev cluster number, if no free cluster till end of fat, then search from head of fat.
// return a cluster number. 0xffff indicate NULLd, disk overflow.
// argument 0 : no prev cluster.
WORD AllocCluster(WORD PrevClusterNum)
{
static WORD LastAllocClusterNum=0;
WORD i;
if(LastAllocClusterNum == 0)
LastAllocClusterNum = PrevClusterNum;
for(i = LastAllocClusterNum; i < BytesPerSector * FATsectors / sizeof(WORD); i++)
{
if(FatCache[i] == 0) //此簇为空簇
{
FatCache[i] = 0xffff; // flag with 0xffff, this is the last cluster.
LastAllocClusterNum = i;
//chain this cluster to prev one.
if(PrevClusterNum != 0)
FatCache[PrevClusterNum] = LastAllocClusterNum;
return LastAllocClusterNum;//返回簇号
}
}
// we have to search from head of fat
for(i = 2; i < BytesPerSector * FATsectors / sizeof(WORD); i++)
{
if(FatCache[i] == 0)
{
FatCache[i] = 0xffff; // flag with 0xffff, this is the last cluster.
LastAllocClusterNum = i;
//chain this cluster to prev one.
if(PrevClusterNum != 0)
FatCache[PrevClusterNum] = LastAllocClusterNum;
return LastAllocClusterNum;
}
}
return 0xffff;
}
//return next cluster num,
//0xffff indicate no next cluster.
//Note! : this function will dirty cache!
WORD GetNextClusterNum(WORD ClusterNum)
{
return FatCache[ClusterNum];
}
// free cluster chain.此函数应当是用于依次释放fat链时
// argument 0 : no prev cluster.
void FreeCluster(WORD StartClusterNum) //何时更新disk中的FAT表?
{
WORD Cluster;
WORD NextCluster;
Cluster = StartClusterNum;
while(Cluster != 0xffff)
{
NextCluster = FatCache[Cluster];
FatCache[Cluster] = 0x0000;
Cluster = NextCluster;
}
}
DWORD CurrentCacheSector;
//Read a special sector into disk cache.
//NULL indicate NULLed.
BYTE* GetSectorData(DWORD StartSector)//LBA
{
unsigned int block;
unsigned int page;
if((CurrentCacheSector == StartSector) && (StartSector != 0))
return SectorBuffer;
block=StartSector/0x20;
page=StartSector%0x20;
NFReadPage(block,page,SectorBuffer);
CurrentCacheSector = StartSector;
return SectorBuffer;
}
void Flush(void)
{
int i,j;
unsigned int block;
unsigned int page;
block=CurrentCacheSector/0x20;
page =CurrentCacheSector%0x20;
memcpy(ClusterBuffer[page],SectorBuffer, BytesPerSector);
if(page==0)
{
for(i=1;i<SectorsPerCluster;i++)
{
NFReadPage(block,i,SectorBuffer);
memcpy(ClusterBuffer[i], SectorBuffer, BytesPerSector);
}
}
else
{
for(i=0;i<page-1;i++)
{
NFReadPage(block,i,SectorBuffer);
memcpy(ClusterBuffer[i], SectorBuffer, BytesPerSector);
}
for(i=page+1;i< SectorsPerCluster;i++)
{
NFReadPage(block,i,SectorBuffer);
memcpy(ClusterBuffer[i], SectorBuffer, BytesPerSector);
}
}
memcpy(SectorBuffer,ClusterBuffer[page],BytesPerSector); //保持Sectorbuffer作为cache内容保持不变!!
NFEraseBlock(block); //写入之前,擦除当前簇;
for(i=0;i<SectorsPerCluster;i++) //一扇区接一扇区写入
{
for(j=0;j<255;j++);//延时
WritePage(block,i,ClusterBuffer[i]);
}
//没有检验
}
WORD SectorNum2ClusterNum(DWORD SectorNum)
{
return (WORD)((SectorNum - FirstDataSector) / SectorsPerCluster + 1);//NOTE:NO MBR!!!
}
DWORD ClusterNum2SectorNum(WORD ClusterNum)
{
return FirstDataSector + (ClusterNum - 1) * SectorsPerCluster;//NOTE:NO MBR!!!
}
// return the first sector number of dir content .
// 0xffffffff indicate NULLed.//从目录区中取得一个目录项
int AllocDir(DWORD ParentDirSectorNum, DIRENTRY* new_dir, _FILE * fp)
{
BYTE* Cache;
DIRENTRY *dir;
DWORD i;
WORD PrevCluster;
WORD Cluster;
DWORD DirSectorNum = ParentDirSectorNum;
if(ParentDirSectorNum == FirstDirSector)//在根目录区
{
for(i=0; i<RootDirCount * sizeof(DIRENTRY) / BytesPerSector; 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();//更新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 NULLed.
// 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++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -