?? fat16.c
字號(hào):
// NULL indicate failed.
// Valid format is full path: \[8.3\]*DIR_Name檢驗(yàn)文件路徑字符串是否合法
// 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 != '\\')//第一個(gè)字符是‘\’
return NULL;
if(strlen(fullpath) > 1 && fullpath[strlen(fullpath)-1] =='\\')//最后一個(gè)字符是‘\’
return NULL;
strcpy(path, fullpath);
//strupr(path);
memset(p, 0, 512);
for(;;)
{
switch(*ppath)
{
case 0x00://結(jié)束符
{
if(dir_len_count != 0) // prev is not '\\'
{
for(i=0; i<(11 - dir_len_count); i++)//未滿11字節(jié),用blank填滿
{
*p = 0x20;
p++;
}
}
}
return static_path;//返回整個(gè)字符串
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個(gè)字符,其中8個(gè)字符為文件名,3個(gè)字符為文件后綴
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內(nèi)尋找與dirname名稱相同的項(xiàng)目
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++)//不是空的目錄項(xiàng),在整個(gè)扇區(qū)搜索
{
if(memcmp((const char*)dir->deName, dirname, 11) == 0 && (!(dir->deAttributes & ATTR_VOLUME)))// not volumn id or long name entry.
//如果目錄名/文件名相同,且不是卷標(biāo)項(xiàng)目
{
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);//返回該目錄/文件的起始簇號(hào)
}
dir++;
}
return 0xffffffff;
}
//在所給sector內(nèi)尋找未被刪除且不是卷標(biāo)項(xiàng)的目錄項(xiàng),記錄項(xiàng)目名稱
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;
}
//在根目錄區(qū)或者數(shù)據(jù)區(qū)尋找是否有與dirname名稱相同的項(xiàng)目
// 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++)//在整個(gè)根目錄區(qū)尋找
{
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);//尋找名稱相同的目錄/文件項(xiàng)
if(FirstSectorOfFile != 0xffffffff)
return FirstSectorOfFile;
}
Cluster = GetNextClusterNum(Cluster);
Sector = ClusterNum2SectorNum(Cluster);
}
}
return 0xffffffff;//找不到
}
//定位文件,即在根目錄區(qū)查找到它的第一級(jí)目錄,在下一個(gè)簇查找到它的第二級(jí)目錄……,直到最終定位文件。
// 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++;//忽略第一個(gè)‘\’
// locate next sub dir(s).
for(;;)
{
if(*p == NULL)
return Sector;
Sector = fat_search(Sector, p, file);//在根目錄區(qū)尋找是否有與P同名的目錄/文件項(xiàng)
if(Sector == 0xffffffff)
return 0xffffffff;
p+=12;
}
// we never go here.
return 0xffffffff;
}
//獲得當(dāng)前的系統(tǒng)時(shí)間
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 <<DD_MONTH_SHIFT)&DD_MONTH_MASK)
+(((year-1980) <<DD_YEAR_SHIFT)&DD_YEAR_MASK);
ptm = ((hour<<DT_HOURS_SHIFT)&DT_HOURS_MASK)+((min<<DT_MINUTES_SHIFT)&DT_MINUTES_MASK)
+(((sec/2)<<DT_2SECONDS_SHIFT)&DT_2SECONDS_MASK);
fatdatetime->TimeTenth = (sec % 2) * 100; //+ systm.wMilliseconds / 10;
}
///////////////////////////////////////////////////////////////////
// fat apis
///////////////////////////////////////////////////////////////////
//創(chuàng)建目錄
int fat_mkdir( const char *dirname)//僅1級(jí)目錄: 父目錄\新目錄
{
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
//獲得了文件的第一級(jí)目錄(parent path)名稱
strcpy(path, dirname);
p = strrchr(path, '\\');//返回path中‘\’第一次出現(xiàn)的指針
if(p == path) // it is root dir.
*(p+1) = '\0';
else
*p = '\0';
//locate parent path
SectorNum = fat_locate(path, NULL);//獲取第一級(jí)目錄指向第一個(gè)扇區(qū)的地址
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在父目錄所指的扇區(qū)下獲得一個(gè)新的目錄項(xiàng)
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);//將新的目錄項(xiàng)所在扇區(qū)讀入
if(Cache == NULL)
return 6;
pdir = (DIRENTRY *)Cache;
pdir += file.DirIndex;
pdir->deStartCluster = NewCluster;//指向新的一簇
Flush();
//create . and .. dir items.
Cache = GetSectorData(ClusterNum2SectorNum(NewCluster));//將新簇的第一個(gè)扇區(qū)讀入
if(Cache == NULL)
return 6;
pdir = (DIRENTRY *)Cache;//獲得一個(gè)目錄項(xiàng)本地目錄:.?
memset((BYTE *)pdir, 0, sizeof(DIRENTRY));
memcpy((BYTE *)(pdir->deName), dot, 11);
pdir->deAttributes = ATTR_DIRECTORY;
fat_datetime(&tm);//獲得當(dāng)前系統(tǒng)的時(shí)間,填寫當(dāng)前目錄項(xiàng)的屬性
pdir->CrtDate = pdir->LstAccDate = pdir->WrtDate = tm.Date;
pdir->CrtTime = pdir->WrtTime = tm.Time;
pdir->CrtTimeTenth = tm.TimeTenth;
pdir->deStartCluster = NewCluster;//指向本地
pdir++;//獲得一個(gè)目錄項(xiàng)父目錄:..
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();
ReadPage(0,9,ClusterBuffer[9]);
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所指目錄下是否有子目錄或文件,獲得第一個(gè)子目錄/文件名
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<RootDirCount * sizeof(DIRENTRY) / BytesPerSector; i++)
{
if(SectorGet(Sector++, &fat_get) == 0)
{
strcpy(filename, fat_get.filename);
return 0;
}
}
}
else
{
fat_get.IsRootDir = 0;
fat_get.DirIndex = 2;
Cluster = SectorNum2ClusterNum(Sector);
// because the sector is the first sector of parent dir,
// so it is the first sector of cluster.
/*
i = (Sector - FirstDataSector) % Bpb.SecPerClus;
if(i != 0)
{
for(; i< Bpb.SecPerClus; i++)
{
if(SectorGet(Sector++, &fat_get) == 0)
{
strcpy(filename, fat_get.filename);
return 0;
}
}
Cluster = GetNextClusterNum(Cluster);
Sector = ClusterNum2SectorNum(Cluster);
}*/
while(Cluster != 0xffff)
{
for(i=0; i< SectorsPerCluster; i++)
{
if(SectorGet(Sector++, &fat_get) == 0)
{
strcpy(filename, fat_get.filename);
return 0;
}
}
Cluster = GetNextClusterNum(Cluster);
Sector = ClusterNum2SectorNum(Cluster);
}
}
return 2;
}
int fat_getnext(char* filename)
{
DWORD Sector;
unsigned int i;
WORD Cluster;
Sector = fat_get.DirSectorNum;
if(fat_get.IsRootDir)
{
i=(Sector - RootDirSectors) * BytesPerSector/ sizeof(DIRENTRY) + fat_get.DirIndex +1;
for(; i<RootDirCount * sizeof(DIRENTRY) / BytesPerSector; i++)
{
if(SectorGet(Sector++, &fat_get) == 0)
{
strcpy(filename, fat_get.filename);
return 0;
}
}
}
else
{
Cluster = SectorNum2ClusterNum(Sector);
i = (Sector - FirstDataSector) % SectorsPerCluster;
if(i != 0)
{
for(; i< SectorsPerCluster; i++)
{
if(SectorGet(Sector++, &fat_get) == 0)
{
strcpy(filename, fat_get.filename);
return 0;
}
}
Cluster = GetNextClusterNum(Cluster);
Sector = ClusterNum2SectorNum(Cluster);
}
while(Cluster != 0xffff)
{
for(i=0; i< SectorsPerCluster; i++)
{
if(SectorGet(Sector++, &fat_get) == 0)
{
strcpy(filename, fat_get.filename);
return 0;
}
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -