📄 fat12.c
字号:
if(dir_len_count > 11) //文件名称长度不能大于11
return NULL;
pstatic++;
ppath++;
}
return static_path; //该语句不会被执行
}
/************ 函数 void unformat_name(char * filename, const unsigned char dirname[11]) *************/
/* 功能: 将dirname[11]中的8-3存储格式的文件名转换成不带空格的打印格式文件名存到filename中 */
/* 入口参数:char * filename---准备存放转换后的打印格式的文件名缓冲区 */
/* const unsigned char dirname[11]---待转换的存储格式文件名 */
/* 出口参数:无 */
/* 说明: 非用户使用函数 */
/****************************************************************************************************/
void unformat_name(char * filename, const unsigned char *dirname)//OK
{
int i;
int j;
memset(filename, 0, 13); //文件名缓冲区清0
for(i=0; i<8; i++)
{
if(dirname[i] != 0x20)
filename[i] = dirname[i]; //dirname[]中的文件名送filename[]缓冲区
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];//dirname[]中的文件扩展名送缓冲区
else
break;
}
}
}
/**** 函数 DWORD DirSectorFileNameSearch(DWORD LgSector, const char dirname[11], _FILE *file) ******/
/*功能:在所给的sector内寻找与dirname(存储格式)名称相同的目录项,找到之后返回该逻辑扇区号本身,否则返回*/
/* 0xffffffff */
/*入口参数:DWORD LgSector----扇区号 */
/* const char dirname[11]---存储格式的目录或文件名,存储格式[aaaaaaaabbb] */
/* _FILE *file---准备存放找到的文件信息的文件缓冲区 */
/*出口参数:找到之后返回目录/文件所在镞的起始扇区号,否则返回0xFFFFFFFF,同时更新file中的文件信息 */
/*说明: 该函数仅由FileSearchByName函数调用 */
/* 非用户使用函数 */
/****************************************************************************************************/
DWORD DirSectorFileNameSearch(DWORD LgSector, const char dirname[11], _FILE *file)//OK
{
BYTE* Cache;
DIRENTRY *dir;
unsigned int j;
BYTE tempbuffer[512];
Cache = ReadLgSector(LgSector,tempbuffer);
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)))//如果目录名/文件名相同,且不是卷标项目
{
if(file != NULL) //如果文件不空才进行更新
{
memset((BYTE *)file, 0, sizeof(_FILE));
file->DirSectorNum = LgSector; //更新文件中的扇区信息
file->DirIndex = j; //更新文件中的目录项索引
memcpy((BYTE *)(&file->dir), (BYTE *)dir, sizeof(DIRENTRY)); //更新文件中的目录项信息
}
return ClusterNumToSectorNum(dir->deStartCluster); //返回该目录/文件所在镞的起始扇区号
}
dir++;
}
return 0xffffffff;
}
//该函数涉及到文件目录项的长度更改问题
/********************** 函数 int ValidDirSearch(DWORD LgSector, FatGet *fat_get) ********************/
/* 功能:在所给Lgsector内寻找第一个未被删除且不是卷标项的目录(文件)项,记录项目名称等信息到fat_get中 */
/* 入口参数:DWORD LgSector----扇区号 */
/* FatGet *fat_get---记录文件信息的缓冲区 */
/* 出口参数:如果存在这样的目录项则返回0,否则如果该扇区空返回1,找不到返回2 */
/* 说明: 非用户使用函数 */
/****************************************************************************************************/
int ValidDirSearch(DWORD LgSector, FatGet *fat_get)//OK
{
BYTE* Cache;
DIRENTRY *dir;
unsigned int j;
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};
BYTE tempbuffer[512];
Cache = ReadLgSector(LgSector,tempbuffer);
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))) //如果目录名/文件未删除,且不是卷标项目则记录在fat_get中
{
if((memcmp((const char*)dir->deName, dot, 11) == 0) || (memcmp((const char*)dir->deName, dotdot, 11) == 0))
{ continue; }
else
{
fat_get->DirSectorNum = LgSector;
fat_get->DirIndex = j;//+ 1 原来加1是考虑到windows操作系统在创建文件时即使对于短文件名,目录项也会占用64个字节,而不是32
unformat_name(fat_get->filename, dir->deName);
return 0;
}
}
dir++;
}
return 2;
}
/********* 函数 DWORD FileSearchByName(DWORD LgSector, const char dirname[11], _FILE *file) *********/
/* 功能: 根据文件名(存储格式)在根目录区或者数据区寻找是否有与dirname名称相同的目录或文件,找到之 */
/* 后返回该文件的起始扇区号,同时将文件信息存储在输入存储区file中。注意寻找时的策略是按照文 */
/* 件链接的顺序 */
/* 入口参数:DWORD LgSector----扇区号,应该为FirstDirSector(33)或大于等于64 */
/* const char dirname[11]----要查找的目录或文件名,存储格式[aaaaaaaabbb] */
/* _FILE *file----存储文件信息的缓冲区 */
/* 出口参数:如果存在这样的目录项则返回该文件目录项所在的扇区号,否则如果找不到返回0xffffffff */
/* 说明: 该函数仅由FileLocateByPath函数调用 */
/* 非用户使用函数 */
/****************************************************************************************************/
DWORD FileSearchByName(DWORD LgSector, const char dirname[11], _FILE *file)//OK
{
DWORD sectornum;
WORD Cluster;
DWORD FirstSectorOfFile;
if(LgSector == FirstDirSector) //先找根目录区
{
for(sectornum=0; sectornum<RootDirSectors; sectornum++) //在整个根目录区的所有扇区中寻找
{
FirstSectorOfFile = DirSectorFileNameSearch(LgSector++, dirname, file); //寻找与dirname名称相同的目录/文件,得到该文件目录项所在的扇区号
if(FirstSectorOfFile != 0xffffffff) //返回目录/文件的扇区号
{ return FirstSectorOfFile; }
}
}
else
{
Cluster = SectorNumToClusterNum(LgSector); //在非根目录区寻找
while(Cluster != 0x0fff) //不是最后一簇
{
for(sectornum=0; sectornum< SectorsPerCluster; sectornum++)
{
FirstSectorOfFile = DirSectorFileNameSearch(LgSector++, dirname, file);//寻找名称相同的目录/文件项
if(FirstSectorOfFile != 0xffffffff)
{ return FirstSectorOfFile; }
}
Cluster = GetNextLgClusterNum(Cluster); //寻找时按照文件链接的顺序
LgSector = ClusterNumToSectorNum(Cluster);
}
}
return 0xffffffff; //找不到
}
/******************** 函数 DWORD FileLocateByPath(const char *path, _FILE *file) ********************/
/* 功能:根据输入的路径名定位文件,即在根目录区查找到它的第一级目录,在下一个簇查找到它的第二级目录, */
/* 直到最终定位文件,将找到的文件信息保存在输入缓冲区file中 */
/* 入口参数:const char *path-----路径,打印格式[\aaaaaa\aaaa\aaaaa.bbb] */
/* _FILE *file----保存文件信息的缓冲区 */
/* 出口参数:如果存在这样的目录项则返回该文件最后目录项所在的扇区号,或者当路径只有[\]而没有其他路径 */
/* 名时将返回根目录扇区号,否则如果找不到则返回0xffffffff */
/*说明: 该函数仅由其他函数调用 */
/* 非用户使用函数 */
/****************************************************************************************************/
DWORD FileLocateByPath(const char *path, _FILE *file)//OK
{
DWORD Sector = FirstDirSector;
char *p;
p = get_valid_format(path); //将文件路径转换成存储格式便于在根目录区寻找
if(p == NULL)
{ return 0xffffffff; }
p++; //在第一级目录中忽略第一个‘\’
for(;;)
{
if(*p == NULL)
{ return Sector; } //找到之后返回该文件最后一级目录项所在扇区号
Sector = FileSearchByName(Sector, p, file); //在根目录区寻找是否有与路径每一小段同名的目录/文件项
if(Sector == 0xffffffff)
{ return 0xffffffff; }
p+=12; //指向下一级目录并跳过'\'
}
return 0xffffffff; //该语句事实上不会被执行
}
//获得当前的系统时间,该文件需要根据芯片本身的实时时钟寄存器来修改,程序其他部分正确
/************************** 函数 void fat_datetime(FatDateTime *fatdatetime) ************************/
/* 功能:从系统的实时时钟获得当前的系统时间,并将时间写到fatdatetime中 */
/* 入口参数:FatDateTime *fatdatetime----准备更新的时间变量 */
/* 出口参数:无 */
/* 说明: 非用户使用函数 */
/****************************************************************************************************/
void fat_datetime(FatDateTime *fatdatetime)//OK
{
int year,month,day,hour,min,sec;
// TimeGet();
/*RTCYear=year;
RTCMonth= month;
RTCDay=day;
RTCHour=hour;
RTCMinute=min;
RTCSecond=sec;*/
year = RTCYear;
month = RTCMonth;
day = RTCDay;
//weekday = RTCDate;
hour = RTCHour;
min = RTCMinute;
sec = RTCSecond;
fatdatetime->Date = ((day << DD_DAY_SHIFT)&DD_DAY_MASK)|((month <<DD_MONTH_SHIFT)&DD_MONTH_MASK)
|(((year-1980) <<DD_YEAR_SHIFT)&DD_YEAR_MASK);
fatdatetime->Time = ((hour<<DT_HOURS_SHIFT)&DT_HOURS_MASK)|((min<<DT_MINUTES_SHIFT)&DT_MINUTES_MASK)
|(((sec>>1)<<DT_2SECONDS_SHIFT)&DT_2SECONDS_MASK);
//fatdatetime->TimeTenth = (sec % 2) * 100; //系统的毫秒数/ 10;
}
/******************************* 函数 int fat_mkdir( const char *dirname) ***************************/
/* 功能:在已经存在的父目录下创建一个子目录,仅1级目录: \父目录\新子目录 */
/* 入口参数: const char *dirname----准备创建的目录名(打印格式),应该为[\aaaa\bbbbbbbbbbb],其中aaaa */
/* 是已经存在的父目录,bbbbbbbbbbb是即将建立的目录名(各级目录名长度都要小于11个字符);如果 */
/* 只有[\bbbbbbbbbbb],即只有新目录名,则在根目录下创建新目录 */
/* 出口参数:创建成功返回0 */
/* 说明: 用户使用函数 */
/****************************************************************************************************/
int fat_mkdir( const char *dirname)//OK
{
BYTE i;
DIRENTRY dir;
DWORD SectorNum;
char path[512];
char name[11];
char *p;
FatDateTime datatime;
_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};
BYTE tempbuffer[512];
p = get_valid_format(dirname); //首先将目录格式转换成存储格式
if(p == NULL) //如果目录名输入非法,则返回1
{ return 1; }
if(FileLocateByPath(dirname, NULL) != 0xffffffff) //再判断该目录是否已经存在,如果存在则返回4
{ return 4; }
/******** 将目录分为父目录和新目录两级来处理 *********/
strncpy(name, &p[strlen(p)-11], 11); //拷贝新的子目录名到name暂存
strcpy(path, dirname);
p = strrchr(path, '\\'); //查找path中最后出现‘\'的位置,返回该位置的指针
if(p == path)
{ *(p+1) = '\0'; } //此时只有新目录名.在第1个'\'之后赋结束符,即将在根目录下创建一个新子目录
else
{ *p = '\0'; } //否则存在父目录时path中最后一次出现‘\'的位置赋'\0',此时说明有上一级目录
/********* 定位父目录 *********/
SectorNum = FileLocateByPath(path, NULL); //获取父目录目录项所在的扇区号
if(SectorNum == 0xffffffff) //判断该路径是否不存在
{ return 2; }
/*********** 以下填充新目录中的属性时间等信息 *****************/
memset((BYTE *)&dir, 0, sizeof(dir)); //dir首先清0
memcpy((BYTE *)(dir.deName), na
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -