⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 一个小型的FAT文件系统,支持FAT12/16和目录
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 + -