📄 fat.c
字号:
USHORT next;
if (cluster == 0) { /* root directory */
if (_CheckDirEmpty(driveNum, cluster) == 0) {
return 0;
}
else {
return -1;
}
}
else {
for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
ret = _CheckDirEmpty(driveNum, cluster);
if (ret == 0) {
return 0; /* empty */
}
else if (ret < 0) {
return -1; /* exist entry */
}
ret = NextFATEntry(driveNum, cluster, &next);
if (ret == 0) { /* end of cluster */
return 0; /* empty */
}
else if (ret < 0) {
return -1; /* cluster error */
}
cluster = next;
}
return -1; /* cluster error */
}
}
/*-----------------------------------------------------------------------------*/
static int _CheckDirEmpty(UCHAR driveNum, USHORT cluster)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
int i, j, numSector;
ULONG sector;
DIR_ENT *readEntry;
UCHAR c;
if (cluster == 0) { /* root */
sector = drive->rootSector;
numSector = drive->numRootSector;
}
else {
sector = CluToSector(driveNum, cluster);
numSector = drive->sectorPerClu;
}
for(i = 0; i < numSector; i++) {
ReadSector(driveNum, sector, workBuffer);
for(j = 0; j < SECTOR_SIZE; j+=32) {
readEntry = (DIR_ENT*)(workBuffer+j);
c = readEntry->filename[0];
if (c == 0) {
return 0; /* end of entry */
}
if (!(c == DELETE_MARK || c == '.' ||
(readEntry->attrib & FA_VOLUME) != 0))
{
return -1; /* exist entry */
}
}
sector ++;
}
return 1;
}
/*-----------------------------------------------------------------------------*/
static int GetNextEntry(DIR_ENT *dirEntry)
{
DIR_ENT *entry;
UCHAR c;
int ret;
FATDRIVE_RES *drive;
USHORT next;
if (dirRes.cluster == END_CLUSTER) {
return 0; /* end of entry */
}
entry = (DIR_ENT*)(dirRes.buffer+dirRes.byteOffset);
ret = 0;
do {
c = entry->filename[0];
if (c == 0) {
return 0; /* end of entry */
}
if (!(c == DELETE_MARK || (entry->attrib & FA_VOLUME) != 0)) {
*dirEntry = *entry;
ret = 1;
}
dirRes.byteOffset += 32;
if (dirRes.byteOffset >= SECTOR_SIZE) {
dirRes.byteOffset = 0;
drive = &fatDriveRes[dirRes.drive];
entry = (DIR_ENT*)(dirRes.buffer);
dirRes.secOffset ++;
if (dirRes.cluster == 0) { /* root */
if (dirRes.secOffset >= drive->numRootSector) {
dirRes.cluster = END_CLUSTER;
return 0;
}
else {
ReadSector(dirRes.drive, drive->rootSector+dirRes.secOffset, dirRes.buffer);
}
}
else {
if (dirRes.secOffset >= drive->sectorPerClu) {
if (NextFATEntry(dirRes.drive, dirRes.cluster, &next) != 1) { /* error or end of cluster */
dirRes.cluster = END_CLUSTER;
return 0;
}
dirRes.secOffset = 0;
dirRes.cluster = next;
dirRes.topSector = CluToSector(dirRes.drive, next);
ReadSector(dirRes.drive, dirRes.topSector+dirRes.secOffset, dirRes.buffer);
}
else {
ReadSector(dirRes.drive, dirRes.topSector+dirRes.secOffset, dirRes.buffer);
}
}
}
else {
entry ++;
}
} while(ret == 0);
return 1; /* exist next entry */
}
/*-----------------------------------------------------------------------------*/
static int RelCluster(UCHAR driveNum, USHORT cluster)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
int i, ret;
USHORT next;
for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
ret = NextFATEntry(driveNum, cluster, &next);
WriteFATEntry(driveNum, cluster, FREE_CLUSTER);
if (ret != 1) { /* cluster error/cluster end */
break;
}
cluster = next;
}
return 0;
}
/*-----------------------------------------------------------------------------*/
static int PathUpper(const UCHAR *path, UCHAR *path2, int len)
{
int i;
for(i = 0; i < len; i++) {
if (*path == '\0') {
break;
}
if (*path >= 'a' && *path <= 'z') {
*path2 = *path - 0x20;
}
else if (*path == '/') {
*path2 = '\\';
}
else {
*path2 = *path;
}
path ++;
path2 ++;
}
if (i == len && *path != '\0') {
return -1; /* path length over */
}
*path2 = '\0';
return 0;
}
/*-----------------------------------------------------------------------------*/
static void EntryToName(UCHAR *name, UCHAR *name2)
{
int i;
for(i = 0; i < 8; i++) {
if (*name != 0x20) { /* not SPACE */
*name2 = *name;
name2 ++;
}
name ++;
}
if (*name != 0x20) { /* with Extension */
*name2 = '.';
name2 ++;
for(i = 0; i < 3; i++) {
if (*name != 0x20) {
*name2 = *name;
name2 ++;
}
name ++;
}
}
*name2 = '\0';
}
/*-----------------------------------------------------------------------------*/
static int NameToEntry(UCHAR *name, UCHAR *name2)
{
int i;
/* name part */
if (strcmp((char*)name, ".") == 0 || strcmp((char*)name, "..") == 0) {
for(i = 0; *name != '\0'; i++) {
*name2 = *name;
name ++;
name2 ++;
}
}
else {
if (*name == '.') {
return -1; /* length error */
}
for(i = 0; i < 9; i ++) { /* name(=max.8) + '.' = 9 chars */
if (*name == '.' || *name == '\0') {
break;
}
*name2 = *name;
name ++;
name2 ++;
}
if (i == 9) {
return -1; /* length error */
}
}
for( ; i < 8; i++) {
*name2 = 0x20; /* full SPACE */
name2 ++;
}
/* extension part */
if (*name == '.') {
name ++;
for(i = 0; i < 4; i ++) {
if (*name == '\0') {
break;
}
*name2 = *name;
name ++;
name2 ++;
}
if (i == 4) {
return -1; /* length error */
}
}
else {
i = 0;
}
for( ; i < 3; i++) {
*name2 = 0x20; /* full SPACE */
name2 ++;
}
return 0;
}
/*-----------------------------------------------------------------------------*/
/*
嵟廔柤埲奜偼僨傿儗僋僩儕
*/
static int SearchFile(UCHAR driveNum, UCHAR *path, DIR_ENT *entry, ULONG *sector, USHORT *offset, USHORT *clu)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
UCHAR name[FILE_LEN_MAX+1], *next;
int ret;
USHORT cluster;
if (*path == '\\') {
cluster = 0;
}
else {
cluster = drive->currClu;
}
do {
ret = ParsePath(path, name, &next);
if (ret >= 0) {
if (*name == 0) {
return -1;
}
if (NameToEntry(name, entry->filename) < 0) {
return -1;
}
if (GetDirEntry(driveNum, cluster, entry, sector, offset) < 0) {
return -1;
}
if (ret == 1) {
if (!((entry->attrib & FA_DIRECTORY) != 0 &&
(entry->attrib & FA_VOLUME) == 0))
{
return -1; /* attribution error */
}
cluster = entry->cluster;
path = next;
}
}
} while(ret == 1); /* exist next name */
if (clu != NULL) {
*clu = cluster;
}
return ret;
}
/*-----------------------------------------------------------------------------*/
/*
cluster
path偱帵偟偨僨傿儗僋僩儕偺僐儞僥儞僣偑奿擺偝傟偨僋儔僗僞傪僙僢僩
儖乕僩偺応崌0
*/
static int SearchPath(UCHAR driveNum, UCHAR *path, USHORT *cluster)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
DIR_ENT entry;
if (*path == '\0') { /* no path(= current path */
if (drive->currClu == 0) { /* root */
*cluster = 0;
}
else {
*cluster = drive->currClu;
}
}
else {
if (*path == '\\' && *(path+1) == '\0') {
*cluster = 0;
}
else {
if (SearchFile(driveNum, path, &entry, NULL, NULL, NULL) == 0) {
if ((entry.attrib & FA_DIRECTORY) != 0 &&
(entry.attrib & FA_VOLUME) == 0)
{
*cluster = entry.cluster;
}
else {
return -1; /* not directory */
}
}
else {
return -1; /* not found */
}
}
}
return 0; /* found */
}
/*-----------------------------------------------------------------------------*/
static int ParsePath(UCHAR *path, UCHAR *name, UCHAR **path2)
{
int i, ret;
if (*path == '\\') {
path ++;
}
for(i = 0; i < FILE_LEN_MAX+1; i++) { /* +1 for null code */
if (*path == '\\'){
path ++;
ret = 1; /* exist next name */
break;
}
if (*path == '\0') {
ret = 0; /* last name */
break;
}
*name = *path;
name ++;
path ++;
}
if (i == FILE_LEN_MAX+1) {
return -1; /* lenght error */
}
*name = '\0';
*path2 = path;
return ret;
}
/*-----------------------------------------------------------------------------*/
static int ParseDirFile(UCHAR *path, UCHAR *file)
{
int i, pause;
pause = -1;
for(i = 0; path[i] != '\0'; i++) {
if (path[i] == '\\') {
pause = i; /* save last directory token */
}
}
if (i == 0) {
return -1; /* no path */
}
if (pause == -1) { /* no directory token (e.g. abc.txt)*/
if (i > FILE_LEN_MAX) {
return -1; /* length over */
}
strcpy((char*)file, (char*)path);
path[0] = '\0';
return 1; /* file only(no directory) */
}
else if (pause == 0) { /* root directory (e.g. \abc.txt) */
if (i > FILE_LEN_MAX+1) {
return -1; /* length over */
}
strcpy((char*)file, (char*)(path+1));
path[1] = '\0';
return 2; /* directory(root), filename */
}
else { /* pause > 0 (e.g. xx\abc.txt) */
if (i > pause+FILE_LEN_MAX+1) {
return -1; /* length over */
}
strcpy((char*)file, (char*)(path+pause+1));
path[pause] = '\0';
return 2; /* directory, filename */
}
}
/*-----------------------------------------------------------------------------*/
/*
path : input path
path2 : current path
*/
static void ChangePath(UCHAR *path, UCHAR *path2)
{
UCHAR name[FILE_LEN_MAX+1], *path3;
int ret;
if (*path == '\\') { /* absolute path */
strcpy((char*)path2, (char*)path);
}
else { /* relative path */
do {
ret = ParsePath(path, name, &path3);
if (*name == '.') {
if (*(name+1) == '.') { /* parent directory */
ParseDirFile(path2, name); /* remove last directory */
}
}
else {
if (strcmp((char*)path2, "\\") != 0) { /* not root directory */
strcat((char*)path2, "\\");
}
strcat((char*)path2, (char*)name);
}
path = path3;
}while(ret == 1);
}
}
/*-----------------------------------------------------------------------------*/
static void SetEntryTime(USHORT *date, USHORT *time)
{
USHORT year, month, day;
USHORT hour, minute, second;
#if (OS_SUPPORT == 1)
TimeStruct dateTime;
GetSysTime(&dateTime);
year = dateTime.yr;
month = dateTime.mo;
day = dateTime.day;
hour = dateTime.hr;
minute = dateTime.min;
second = dateTime.sec;
#else
year = CFG_DEFAULT_YEAR;
month = CFG_DEFAULT_MONTH;
day = CFG_DEFAULT_DAY;
hour = CFG_DEFAULT_HOUR;
minute = CFG_DEFAULT_MINUTE;
second = CFG_DEFAULT_SECOND;
#endif
year -= 1980;
second /= 2;
*date = (year << 9) + (month << 5) + day;
*time = (hour << 11) + (minute << 5) + second;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -