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

📄 fat.c

📁 一个小型的FAT文件系统,支持FAT12/16和目录
💻 C
📖 第 1 页 / 共 5 页
字号:
		return E_FILE_DESCRIPTOR;
	}
	file = &fatFileRes[fd];

	if (file->use_flag == 0) {
		return E_FILE_CLOSED;
	}

	if (file->openmode == OPEN_WR) {
		WriteSector(file->drive, file->topSector+file->secOffset, file->buffer);
		// FAT乮僼傽僀儖僒僀僘乯傕峏怴偡傞昁梫偁傞丠
	}
	return E_FILE_OK;
}

/*-----------------------------------------------------------------------------*/
int FATRemove(UCHAR driveNum, const UCHAR *path)
{
	FATDRIVE_RES	*drive;
	DIR_ENT		entry;
	ULONG		sector;
	USHORT		offset;
	int			i;
	FATFILE_RES	*file;

	if (driveNum >= FAT_DRIVE_MAX) {
		return E_FILE_DRIVE;
	}
	drive= &fatDriveRes[driveNum];
	if (drive->ready_flag == 0) {	/* drive not ready */
		return E_FILE_NOT_READY;
	}

	if (PathUpper(path, workPath, PATH_LEN_MAX) < 0) {
		return E_FILE_PATH_LEN;
	}
	/* Check path */
	if (SearchFile(driveNum, workPath, &entry, &sector, &offset, NULL) < 0) {
		return E_FILE_PATH;
	}
	if (!((entry.attrib & FA_DIRECTORY) == 0 &&
		(entry.attrib & FA_VOLUME) == 0))
	{
		return E_FILE_PATH;	/* not file attribution */
	}

	if ((entry.attrib & FA_READ_ONLY) != 0) {
		return E_FILE_ATTRIB;
	}

	/* Check on use */
	for(i = 0; i < FAT_FILE_MAX; i++) {
		file = &fatFileRes[i];
		if (file->use_flag == 1) {
			if (file->drive == driveNum && file->entrySector == sector &&
				file->entryOffset == offset) {
				return E_FILE_LOCKED;
			}
		}
	}

	/* release cluster */
	RelCluster(driveNum, entry.cluster);

	/* Update directory entry */
	ReadSector(driveNum, sector, workBuffer);
	entry.filename[0] = DELETE_MARK;
	*(DIR_ENT*)(workBuffer+offset) = entry;
	WriteSector(driveNum, sector, workBuffer);
	FlushCache();

	return E_FILE_OK;
}

/*-----------------------------------------------------------------------------*/
int FATRename(UCHAR driveNum, const UCHAR *oldname, const UCHAR *newname)
{
	FATDRIVE_RES	*drive;
	DIR_ENT		entry;
	ULONG		sector;
	USHORT		offset, cluster;
	int			i;
	FATFILE_RES	*file;
	UCHAR		newName[FILE_LEN_MAX+1];

	if (driveNum >= FAT_DRIVE_MAX) {
		return E_FILE_DRIVE;
	}
	drive= &fatDriveRes[driveNum];
	if (drive->ready_flag == 0) {	/* drive not ready */
		return E_FILE_NOT_READY;
	}

	if (PathUpper(oldname, workPath, PATH_LEN_MAX) < 0) {
		return E_FILE_PATH_LEN;
	}
	if (PathUpper(newname, newName, FILE_LEN_MAX) < 0) {
		return E_FILE_PATH_LEN;
	}

	/* Check path */
	if (SearchFile(driveNum, workPath, &entry, &sector, &offset, &cluster) < 0) {
		return E_FILE_PATH;
	}
	if ((entry.attrib & FA_VOLUME) != 0){
		return E_FILE_PATH;	/* not file/directory attribution */
	}
	if (entry.filename[0] == '.') {	/* own directory or parent directory */
		return E_FILE_PATH;
	}

	if ((entry.attrib & FA_DIRECTORY) == 0) {	/* file attribution */
	/* Check on use */
		for(i = 0; i < FAT_FILE_MAX; i++) {
			file = &fatFileRes[i];
			if (file->use_flag == 1) {
				if (file->drive == driveNum && file->entrySector == sector &&
					file->entryOffset == offset) {
					return E_FILE_LOCKED;
				}
			}
		}
	}
	else if ((entry.attrib & FA_DIRECTORY) != 0) {	/* directory attribution */
	/* Check current path */
		if (strncmp((char*)drive->currPath, (char*)workPath, strlen((char*)workPath)) == 0) {
			return E_FILE_LOCKED;
		}
	}

	/* Check same name */
	if (NameToEntry(newName, entry.filename) < 0) {
		return E_FILE_NAME_LEN;
	}
	if (GetDirEntry(driveNum, cluster, &entry, NULL, NULL) == 0) {
		return E_FILE_EXIST;
	}

	/* Update directory entry */
	ReadSector(driveNum, sector, workBuffer);
	memcpy(((DIR_ENT*)(workBuffer+offset))->filename, entry.filename, 11);
	WriteSector(driveNum, sector, workBuffer);
	FlushCache();

	return E_FILE_OK;
}

/*-----------------------------------------------------------------------------*/
int FATSeek(int fd, long offset, int origin, long *position)
{
	FATFILE_RES	*file;
	long		pos;


	if (fd >= FAT_FILE_MAX) {
		return E_FILE_DESCRIPTOR;
	}
	file = &fatFileRes[fd];

	if (file->use_flag == 0) {
		return E_FILE_CLOSED;
	}

	switch(origin) {
		case SEEK_SET:
			pos = offset;
			break;

		case SEEK_CUR:
			pos = (long)file->filepos + offset;
			break;

		case SEEK_END:
			pos = (long)file->dirEntry.size + offset;
			break;

		default:
			return E_FILE_PARAMETER;
	}

	if (pos < 0) {
		pos = 0;
	}
	else if (pos > file->dirEntry.size) {
		pos = file->dirEntry.size;
	}
	if (pos != file->filepos) {
/*
 曄峏偑側偔偰傕嵞儕乕僪偟偨傎偆偑偄偄丠
 儕乕僪僶僢僼傽傪峏怴偟偨偄応崌偵偙偺娭悢傪巊梡偱偒傞乮儔僀僩僨乕僞傪偡偖偵儕乕僪偵斀塮偟偨応崌乯丅
*/

		file->filepos = pos;
		PosToCluster(file->drive, pos, file->dirEntry.cluster, &(file->currClu), &(file->secOffset));
		file->topSector = CluToSector(file->drive, file->currClu);
		ReadSector(file->drive, file->topSector+file->secOffset, file->buffer);
	}
	if (position != NULL) {
		*position = pos;
	}
	return E_FILE_OK;
}

/*-----------------------------------------------------------------------------*/
int FATSetAttr(UCHAR driveNum, const UCHAR *path, UCHAR attr)
{
	FATDRIVE_RES	*drive;
	DIR_ENT		entry;
	ULONG		sector;
	USHORT		offset;
	int			i;
	FATFILE_RES	*file;

	if (driveNum >= FAT_DRIVE_MAX) {
		return E_FILE_DRIVE;
	}
	drive= &fatDriveRes[driveNum];
	if (drive->ready_flag == 0) {	/* drive not ready */
		return E_FILE_NOT_READY;
	}

	if (PathUpper(path, workPath, PATH_LEN_MAX) < 0) {
		return E_FILE_PATH_LEN;
	}
	/* Check path */
	if (SearchFile(driveNum, workPath, &entry, &sector, &offset, NULL) < 0) {
		return E_FILE_PATH;
	}
	if ((entry.attrib & FA_VOLUME) != 0) {
		return E_FILE_PATH;		/* not file/directory attribution */
	}

	/* Check on use */
	if ((entry.attrib & FA_DIRECTORY) == 0) {	/* file attribution */
		for(i = 0; i < FAT_FILE_MAX; i++) {
			file = &fatFileRes[i];
			if (file->use_flag == 1) {
				if (file->drive == driveNum && file->entrySector == sector &&
					file->entryOffset == offset) {
					return E_FILE_LOCKED;
				}
			}
		}
	}


	if ((attr & FA_READ_ONLY) != 0) {
		entry.attrib |= FA_READ_ONLY;
	}
	else {
		entry.attrib &= (UCHAR)(~FA_READ_ONLY);
	}
	if ((attr & FA_HIDDEN) != 0) {
		entry.attrib |= FA_HIDDEN;
	}
	else {
		entry.attrib &= (UCHAR)(~FA_HIDDEN);
	}
	if ((attr & FA_ARCHIVE) != 0) {
		entry.attrib |= FA_ARCHIVE;
	}
	else {
		entry.attrib &= (UCHAR)(~FA_ARCHIVE);
	}
	ReadSector(driveNum, sector, workBuffer);
	*(DIR_ENT*)(workBuffer+offset) = entry;
	WriteSector(driveNum, sector, workBuffer);
	FlushCache();

	return E_FILE_OK;
}

/*-----------------------------------------------------------------------------*/
int FATGetFirstEntry(UCHAR driveNum, const UCHAR *path, UCHAR *name, FILE_INFO *finfo)
{
	FATDRIVE_RES	*drive;
	USHORT		cluster;
	DIR_ENT		entry;

	if (driveNum >= FAT_DRIVE_MAX) {
		return E_FILE_DRIVE;
	}
	drive= &fatDriveRes[driveNum];
	if (drive->ready_flag == 0) {	/* drive not ready */
		return E_FILE_NOT_READY;
	}

	if (PathUpper(path, workPath, PATH_LEN_MAX) < 0) {
		return E_FILE_PATH_LEN;
	}
	/* Check path */
	if (SearchPath(driveNum, workPath, &cluster) < 0) {
		return E_FILE_PATH;
	}

	dirRes.cluster = cluster;
	dirRes.drive = driveNum;
	dirRes.topSector = CluToSector(driveNum, cluster);
	dirRes.secOffset = 0;
	dirRes.byteOffset = 0;
	ReadSector(driveNum, dirRes.topSector, dirRes.buffer);

	if (GetNextEntry(&entry) == 0) {
		return 0;	/* end of entry */
	}

	EntryToName(entry.filename, name);
	if (finfo != NULL) {
		EntryToInfo(&entry, finfo);
	}

	return 1;	/* exist next entry */
}

/*-----------------------------------------------------------------------------*/
int FATGetNextEntry(UCHAR *name, FILE_INFO *finfo)
{
	DIR_ENT		entry;

	if (GetNextEntry(&entry) == 0) {
		return 0;	/* end of entry */
	}

	EntryToName(entry.filename, name);
	if (finfo != NULL) {
		EntryToInfo(&entry, finfo);
	}

	return 1;	/* exist next entry */
}

/*-----------------------------------------------------------------------------*/
int FATMkdir(UCHAR driveNum, const UCHAR *path)
{
	FATDRIVE_RES	*drive;
	UCHAR		filename[FILE_LEN_MAX+1];
	DIR_ENT		entry, *dirEntry;
	USHORT		newClu, cluster, upDate, upTime;
	int			i, ret;
	ULONG		sector;

	if (driveNum >= FAT_DRIVE_MAX) {
		return E_FILE_DRIVE;
	}
	drive= &fatDriveRes[driveNum];
	if (drive->ready_flag == 0) {	/* drive not ready */
		return E_FILE_NOT_READY;
	}

	if (PathUpper(path, workPath, PATH_LEN_MAX) < 0) {
		return E_FILE_PATH_LEN;
	}

	ret = ParseDirFile(workPath, filename);
	if (ret < 0) {
		return E_FILE_NAME_LEN;
	}

	if (SearchPath(driveNum, workPath, &cluster) < 0) {
		return E_FILE_PATH;
	}

	if (strcmp((char*)filename, ".") == 0 || strcmp((char*)filename, "..") == 0) {
		return E_FILE_NAME;
	}
	if (NameToEntry(filename, entry.filename) < 0) {
		return E_FILE_NAME_LEN;
	}
	if (GetDirEntry(driveNum, cluster, &entry, NULL, NULL) == 0) {
		return E_FILE_EXIST;
	}

	if (GetFreeClu(driveNum, &newClu) < 0) {		/* for new file contents */
		return E_FILE_DISK_FULL;
	}
	entry.attrib = FA_DIRECTORY;
	memset(entry.reserved, 0, 10);
	SetEntryTime(&upDate, &upTime);
	entry.upTime = upTime;
	entry.upDate = upDate;
	entry.cluster = newClu;
	entry.size = 0;

	if (AddDirEntry(driveNum, cluster, &entry) < 0) {
		WriteFATEntry(driveNum, newClu, FREE_CLUSTER);	/* release new cluster */
		FlushCache();
		return E_FILE_DISK_FULL;
	}

	/* clear sectors(except top sector) on new cluster */
	sector = CluToSector(driveNum, newClu);
	memset(workBuffer, 0, SECTOR_SIZE);
	for(i = 1; i < drive->sectorPerClu; i++) {
		driverAPI[driveNum].write(sector+i, 1, workBuffer);		/* no cache */
	}

	/* own directory */
	dirEntry = (DIR_ENT*)workBuffer;
	dirEntry->filename[0] = '.';
	memset(dirEntry->filename+1, 0x20, 10);	/* full SPACE */
	dirEntry->upTime = upTime;
	dirEntry->upDate = upDate;
	dirEntry->attrib = FA_DIRECTORY;
	dirEntry->cluster = newClu;

	/* parent directory */
	dirEntry ++;
	dirEntry->filename[0] = '.';
	dirEntry->filename[1] = '.';
	memset(dirEntry->filename+2, 0x20, 9);	/* full SPACE */
	dirEntry->upTime = upTime;
	dirEntry->upDate = upDate;
	dirEntry->attrib = FA_DIRECTORY;
	dirEntry->cluster = cluster;

	WriteSector(driveNum, sector, workBuffer);
	FlushCache();
	return E_FILE_OK;
}

/*-----------------------------------------------------------------------------*/
int FATRmdir(UCHAR driveNum, const UCHAR *path)
{
	FATDRIVE_RES	*drive;
	DIR_ENT		entry;
	ULONG		sector;
	USHORT		offset;
	FATFILE_RES	*file;

	if (driveNum >= FAT_DRIVE_MAX) {
		return E_FILE_DRIVE;
	}
	drive= &fatDriveRes[driveNum];
	if (drive->ready_flag == 0) {	/* drive not ready */
		return E_FILE_NOT_READY;
	}

	if (PathUpper(path, workPath, PATH_LEN_MAX) < 0) {
		return E_FILE_PATH_LEN;
	}

	/* Check current path */
	if (strncmp((char*)drive->currPath, (char*)workPath, strlen((char*)workPath)) == 0) {
		return E_FILE_LOCKED;
	}

	/* Check path */
	if (SearchFile(driveNum, workPath, &entry, &sector, &offset, NULL) < 0) {
		return E_FILE_PATH;
	}
	if (!((entry.attrib & FA_DIRECTORY) != 0 &&
		(entry.attrib & FA_VOLUME) == 0))
	{
		return E_FILE_PATH;	/* not directory attribution */
	}
	if (entry.filename[0] == '.') {	/* own directory or parent directory */
		return E_FILE_PATH;
	}

	if ((entry.attrib & FA_READ_ONLY) != 0) {
		return E_FILE_ATTRIB;
	}

	/* Check empty directory  */
	if (CheckDirEmpty(driveNum, entry.cluster) < 0) {
		return E_FILE_EXIST;
	}

	/* release cluster */
	RelCluster(driveNum, entry.cluster);

	/* Update directory entry */
	ReadSector(driveNum, sector, workBuffer);
	entry.filename[0] = DELETE_MARK;
	*(DIR_ENT*)(workBuffer+offset) = entry;
	WriteSector(driveNum, sector, workBuffer);
	FlushCache();

	return E_FILE_OK;
}

/*-----------------------------------------------------------------------------*/
int FATGetFileInfo(UCHAR driveNum, const UCHAR *path, FILE_INFO *finfo)
{
	FATDRIVE_RES	*drive;
	DIR_ENT		entry;

	if (driveNum >= FAT_DRIVE_MAX) {
		return E_FILE_DRIVE;
	}
	drive= &fatDriveRes[driveNum];
	if (drive->ready_flag == 0) {	/* drive not ready */
		return E_FILE_NOT_READY;
	}

	if (PathUpper(path, workPath, PATH_LEN_MAX) < 0) {
		return E_FILE_PATH_LEN;
	}
	/* Check path */
	if (SearchFile(driveNum, workPath, &entry, NULL, NULL, NULL) < 0) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -