📄 fat12.c
字号:
lgToph[newlogicClusternum] = newphBlocknum; //更新逻辑映射表
tempSectorSpare[6] = (BYTE)(newlogicClusternum & 0xff); //准备写入新块的逻辑号
tempSectorSpare[7] = (BYTE)(newlogicClusternum>>8);
tempSectorSpare[11] = tempSectorSpare[6];
tempSectorSpare[12] = tempSectorSpare[7];
NAND_SpareProgram((newphBlocknum<<14) | 6, &tempSectorSpare[6], 2); //在FLASH中将该新块的0扇区的逻辑号写入新物理块
NAND_SpareProgram((newphBlocknum<<14) | 11, &tempSectorSpare[11], 2);//在FLASH中将该新块的0扇区的逻辑号写入新物理块
if(PrevLgClusterNum >= 2)
{
Write_FAT(PrevLgClusterNum,newlogicClusternum); //在FAT表中原逻辑号对应位置写入新逻辑号(链接到原逻辑号后)
}
Write_FAT(newlogicClusternum,0x0fff); //在FAT表中新逻辑号对应位置写入0x0fff(文件的最后一簇)
return newlogicClusternum; //返回簇号
}
/*************************** 函数GetNextLgClusterNum(WORD LgClusterNum) ****************************/
/* 功能:根据输入的逻辑镞号得到与它链接的下一个逻辑镞号 */
/* 入口参数:逻辑镞号,不能小于2 */
/* 出口参数:与输入逻辑镞号链接的下一个逻辑镞号,如果为0xffff表示没有下一个镞号 */
/* 说明:非用户使用函数 */
/****************************************************************************************************/
WORD GetNextLgClusterNum(WORD LgClusterNum)//OK
{
return(Read_FAT(LgClusterNum));
}
/****************************** 函数 FreeCluster(WORD StartLgClusterNum) ****************************/
/* 功能:根据输入的逻辑镞号依次释放fat链,更新FAT表和逻辑映射表,同时擦除被释放的逻辑簇号所对应的物理块*/
/* 入口参数:逻辑镞号,不能小于2 */
/* 出口参数:无 */
/* 说明:非用户使用函数 */
/****************************************************************************************************/
void FreeCluster(WORD StartLgClusterNum)//OK
{
WORD nextclusternum, startclusternum;
nextclusternum = StartLgClusterNum;
startclusternum = StartLgClusterNum;
while(nextclusternum != 0x0fff)
{
nextclusternum = Read_FAT(startclusternum); //读FAT表中对应起始逻辑号的对应扇区内容
Write_FAT(startclusternum,0);
NAND_BlockErase(lgToph[startclusternum]); //擦除被释放的物理块
lgToph[startclusternum] = 0xffff; //更新逻辑表
startclusternum = nextclusternum;
}
}
/*********** 函数 int AllocDir(DWORD LgParentDirSectorNum, DIRENTRY* new_dir, _FILE * fp) ***********/
/* 功能: 从目录区中寻找一个空目录项并将已经存放在new_dir中的目录(或文件)信息写入,同时将找到的目 */
/* 录扇区号和在该扇区中的目录偏移号写到文件指针fp中 */
/*入口参数:DWORD LgParentDirSectorNum,父目录扇区。准备从该扇区开始创建目录项,取值为>33表示从根目录区*/
/* 创建,或>=64表示从指定的扇区创建目录,其它值无效。但该扇区对应的簇事先应该在文件链表中 */
/* DIRENTRY* new_dir-- 除了其始簇外已经赋好值的目录项,即将被写入目录区 */
/* _FILE * fp-- 准备更新目录扇区号和偏移号的文件 */
/* 出口参数: 0--成功; 1--根目录区已满; 4--没有空镞 */
/* 说明:非用户使用函数 */
/****************************************************************************************************/
/*******************************************************************************
* 修改时间: 2007/09/11 14:12 by shenwf
* 修改原因: 申请新的一组文件的时候没有清零剩下的数据;
*******************************************************************************/
int AllocDir(DWORD LgParentDirSectorNum, DIRENTRY* new_dir, _FILE * fp)//OK
{
DIRENTRY *dir;
BYTE* Cache;
BYTE sectornumber;
WORD PrevCluster;
WORD LgCluster;
DWORD DirSectorNum = LgParentDirSectorNum;
BYTE tempbuffer[512];
if((DirSectorNum >= FirstDirSector) && (DirSectorNum < (FirstDirSector + RootDirSectors))) //在根目录区
{
for(sectornumber = FirstDirSector; sectornumber < (FirstDirSector + RootDirSectors); sectornumber++)
{
Cache = ReadLgSector(sectornumber,tempbuffer); //读取该扇区的512个字节数据到tempbuffer中
for(dir = (DIRENTRY *)Cache; (BYTE*)dir < (Cache + BytesPerSector); dir++)//在一个扇区内循环寻找空目录项
{//中间部分Cache指针指向tempbuffer的起始位置,加512后即为dir的右边界
if((dir->deName[0] == 0) || (dir->deName[0] == 0xe5)) //本项未用或文件被删除,也就是该目录项空,可以使用
{
memcpy((BYTE *)dir, (BYTE *)new_dir, sizeof(DIRENTRY)); //将新的目录信息写入tempbuffer中
WriteLgSector(sectornumber,tempbuffer); //更新根目录区
if(fp) //更新文件信息
{
fp->DirSectorNum = sectornumber; //当前目录项所在的扇区地址
fp->DirIndex = ((BYTE*)dir - Cache) / sizeof(DIRENTRY); //目录索引,即该扇区中第x个目录项
memcpy((BYTE *)(&fp->dir), (BYTE *)new_dir, sizeof(DIRENTRY));//新的目录信息写到文件结构中
}
return 0; //操作成功,退出
}
}
}
return 1; //根目录区已满.
}
else //不在根目录区,此时ParentDirSectorNum应该大于等于64,进入数据区
{
LgCluster = SectorNumToClusterNum(LgParentDirSectorNum); //计算LgParentDirSectorNum所在逻辑镞号
while(LgCluster != 0x0fff)
{
for(sectornumber=0; sectornumber< SectorsPerCluster; sectornumber++)//在整个簇中搜索
{
Cache = ReadLgSector((LgCluster<<5)|sectornumber,tempbuffer); //读取该扇区的512个字节数据到tempbuffer中
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)); //将新的目录信息写入tempbuffer中
WriteLgSector((LgCluster<<5)|sectornumber,tempbuffer); //更新FLASH中该扇区
if(fp) //更新文件信息
{
fp->DirSectorNum = (LgCluster<<5)|sectornumber;//DirSectorNum; by LJC //当前目录项所在的扇区地址
fp->DirIndex = ((BYTE*)dir - Cache) / sizeof(DIRENTRY);//目录索引,即该扇区中第x个目录项
memcpy((BYTE *)(&fp->dir), (BYTE *)new_dir, sizeof(DIRENTRY));//新的目录信息写到文件结构中
}
return 0; //操作成功,退出
}
}
}
// 搜索完当前簇,没有空的目录项
PrevCluster = LgCluster;
LgCluster = GetNextLgClusterNum(LgCluster); //从FAT表中找出下一簇
}
//以上已经是文件链表中最后一个簇,需要一个空镞来创建一个新的目录扇区
LgCluster = AllocCluster(PrevCluster); //利用FAT表获得一个空簇
if(LgCluster == 0xffff) //没有空簇则返回
{ return 4; }
//Cache = ReadLgSector(LgCluster<<5,tempbuffer); //读取空簇0扇区的512个字节数据到tempbuffer中
memset(tempbuffer,0,BytesPerSector);
Cache = tempbuffer;
dir = (DIRENTRY *)Cache;
memcpy((BYTE *)dir, (BYTE *)new_dir, sizeof(DIRENTRY));
WriteLgSector(LgCluster<<5,tempbuffer); //更新FLASH中该扇区
// 清理剩下的扇区的文件 by shenwf
memset(tempbuffer,0,BytesPerSector);
for( sectornumber = 1; sectornumber < SectorsPerCluster; sectornumber++)
{
WriteLgSector((LgCluster<<5)|sectornumber,tempbuffer);// 清零剩下的扇区中的数据;
}
/////////////
if(fp)
{
fp->DirSectorNum = LgCluster<<5;
fp->DirIndex = ((BYTE*)dir - Cache) / sizeof(DIRENTRY);
memcpy((BYTE *)(&fp->dir), (BYTE *)new_dir, sizeof(DIRENTRY));
}
return 0;
}
}
/************************************** 函数 int DeleteDir(_FILE *file) *****************************/
/* 功能: 删除一个目录(文件),只将该文件的目录项标记为删除 */
/*入口参数: _FILE *file,指向一个待删除的目录(文件)的指针 */
/* 出口参数:无 */
/* 说明:非用户使用函数 */
/****************************************************************************************************/
int DeleteDir(_FILE *file)//OK
{
BYTE* Cache;
DIRENTRY *dir;
DWORD secnum;
BYTE tempbuffer[512];
secnum = file->DirSectorNum;
Cache = ReadLgSector(secnum,tempbuffer); //获得文件目录区的扇区内容
if(Cache == NULL)
{ return 1; }
dir = (DIRENTRY *)Cache;
dir += file->DirIndex; //找到该文件的目录项位置
dir->deName[0] = 0xe5; //做删除标记
WriteLgSector(secnum,tempbuffer); //更新该文件的目录项
return 0;
}
/*************************** 函数 char* get_valid_format(const char *fullpath) **********************/
/* 功能: 将输入的非存储格式的路径标准化成存储格式的路径,输入的路径名格式应为[\aaaa\aaa.bb],标准 */
/* 化后的存储格式为[\aaaa_ _ _ _ _ _ _\aaa_ _ _ _ _ bb _] */
/* 入口参数:文件的路径名。要求路径名的第一个字符必须是[\],最后一个字符不能为[\] */
/* 同时文件名称不能用中文,名称用8个英文字符,扩展名3个字符,总的路径字符小于80个 */
/* 出口参数:static_path[512]中存放整个标准化后的路径,各层路径中不满11个字符时用空格填充;如果输入非法*/
/* 则返回空 */
/* 说明: 非用户使用函数 */
/****************************************************************************************************/
char* get_valid_format(const char *fullpath)//OK
{
static char static_path[512];
char* pstatic=static_path;
char path[80];
char* ppath = path;
int dir_len_count = 0; //路径长度.
int i;
if(fullpath == NULL || strlen(fullpath) >=80 || *fullpath != '\\') //第一个字符必须是‘\’,路径长度不能大于80个字符
{ return NULL; }
if(strlen(fullpath) > 1 && fullpath[strlen(fullpath)-1] =='\\') //最后一个字符是‘\’不允许
{ return NULL; }
strcpy(path, fullpath); //将路径拷贝到path[80]数组
memset(pstatic, 0, 512); //将static_path[512]数组清零
for(;;)
{
switch(*ppath)
{
case 0x00: //结束符
{
if(dir_len_count != 0) // 前导字符不是'\\',说明确实到了路径的结束位置
{
for(i=0; i<(11 - dir_len_count); i++) //此时如果文件名长度未满11字节,用blank填充未满11个的static_path[]位置
{
*pstatic = 0x20;
pstatic++;
}
}
}
return static_path; //返回整个字符串
case '\\':
{
if(pstatic != static_path) //此时检验的已不是第一个字符,
{
if(dir_len_count == 0) //但文件长度为0,说明开始检验第二个字符。但又出现 '\\',
return NULL; //说明输入的文件路径出现了不只一个'\\",此时无效
for(i=0; i<(11 - dir_len_count); i++)
{
*pstatic = 0x20; //如果检验的不是第1和第2个字符,说明一小段路径名已到结尾,要到下一段,
pstatic++; //则将后续的不满11个的static_path[]位置填充空格
}
}
*pstatic = '\\'; //如果此时检验的是一小段路径的起始位置,则将static_path[]="\"
pstatic++;
ppath++;
dir_len_count =0; //在检测到’\\'之后,开始新的文件名计数,字符"\"不计长度
continue;
}
//break;
case '.':
{
if(dir_len_count > 8 || dir_len_count ==0) // 文件名长度不能超过8个字符,并且在"\"之后不能马上出现"."
return NULL;
if(ppath[1] == '.' || ppath[1] == '\\') // 不能出现两个以上的 '.'或 '.\'
return NULL;
for(i=0; i<(8 - dir_len_count); i++) //出现'.'之后 static_path[]中用空格添充未满8个字符的位置
{
*pstatic = 0x20;
pstatic++;
}
dir_len_count = 8; //此时'.'之前的文件名有效,长度计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) //如果输入的字符都是ASCII表中空格以前的字符,都无效
return NULL;
}
break;
}
*pstatic = *ppath; //如果输入的字符都不是以上的各种情况,说明字符有效,则将该字符送入static_path[]中
dir_len_count ++; //文件名称长度加1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -