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

📄 fat.c

📁 一个小型的FAT文件系统,支持FAT12/16和目录
💻 C
📖 第 1 页 / 共 5 页
字号:
	useTopList = curr;
	return 0;
}


/*-----------------------------------------------------------------------------*/
static int WriteSector(UCHAR driveNum, ULONG sector, UCHAR *buf)
{
	char		curr, prev;
	int			i, flag;
	CACHE_RES	*cache;

	i = 0;
	flag = 0;
	if (useTopList != -1) {
		curr = prev = useTopList;
		for(i = 0; i < CFG_CACHE_NUM; i++) {
			cache = &cacheRes[curr];
			if (cache->drive == driveNum && cache->sector == sector) {
				flag = 1;
				break;
			}
			if (cache->next == -1) {	// list end ?
				break;
			}
			prev = curr;
			curr = cache->next;
		}
	}

	if (flag == 0) {	/* not found */
		if (i < CFG_CACHE_NUM-1) {	// exist blank cache
			curr = (char)GetBlankCache();
			cache = &cacheRes[curr];
		}
		else {		// cache full
			if (cache->write_flag == 1) {
				driverAPI[cache->drive].write(cache->sector, 1, cache->buffer);
			}
			cacheRes[prev].next = -1;	// set end-mark
		}
		cache->drive = driveNum;
		cache->sector = sector;
	}
	memcpy(cache->buffer, buf, SECTOR_SIZE);
	cache->write_flag = 1;
	cache->next = useTopList;
	useTopList = curr;
	return 0;
}

/*-----------------------------------------------------------------------------*/
static int GetBlankCache(void)
{
	int		i;

	for(i = 0; i < CFG_CACHE_NUM; i++) {
		if (cacheRes[i].use_flag == 0) {
			cacheRes[i].use_flag = 1;
			return i;
		}
	}
	return -1;
}

/*-----------------------------------------------------------------------------*/
static int FlushCache(void)
{
	char		curr;
	CACHE_RES	*cache;
	int			i;

	if (useTopList != -1) {
		curr = useTopList;
		for(i = 0; i < CFG_CACHE_NUM; i++) {
			cache = &cacheRes[curr];
			if (cache->write_flag == 1) {
				driverAPI[cache->drive].write(cache->sector, 1, cache->buffer);
				cache->write_flag = 0;
			}
			if (cache->next == -1) {	// list end ?
				break;
			}
			curr = cache->next;
		}
	}
	return 0;
}

/*-----------------------------------------------------------------------------*/
static int GetTotalFreeClu(UCHAR driveNum, ULONG *freeCnt)
{
	int			ret;

	FlushCache();
	if (fatDriveRes[driveNum].fileType == TYPE_FAT12) {
		ret = _GetTotalFreeClu12(driveNum, freeCnt);
	}
	else {	// TYPE_FAT16
		ret = _GetTotalFreeClu16(driveNum, freeCnt);
	}
	return ret;
}

/*-----------------------------------------------------------------------------*/
static int _GetTotalFreeClu12(UCHAR driveNum, ULONG *freeCnt)
{
	FATDRIVE_RES	*drive= &fatDriveRes[driveNum];
	USHORT		secOffset, byteOffset;
	ULONG		total;
	int			i, j;
	UCHAR		buf[3];

	total = 0;
	secOffset = 0;
	byteOffset = TOP_CLUSTER*3/2;
	driverAPI[driveNum].read(drive->fatSector, 1, workBuffer);
	for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
		for(j = 0; j < 3; j++) {
			buf[j] = workBuffer[byteOffset++];
			if (byteOffset >= SECTOR_SIZE) {
				byteOffset = 0;
				secOffset ++;
				driverAPI[driveNum].read(drive->fatSector+secOffset, 1, workBuffer);
			}
		}

		if (buf[0] == 0 && (buf[1] & 0x0F) == 0) {
			total ++;
		}
		i++;
		if (i > drive->maxClu) {
			break;
		}
		if ((buf[1] & 0xF0) == 0 && buf[2] == 0) {
			total ++;
		}
	}
	*freeCnt = total;
	return 0;
}

/*-----------------------------------------------------------------------------*/
static int _GetTotalFreeClu16(UCHAR driveNum, ULONG *freeCnt)
{
	FATDRIVE_RES	*drive= &fatDriveRes[driveNum];
	USHORT		secOffset, byteOffset;
	ULONG		total;
	int			i;

	total = 0;
	secOffset = 0;
	byteOffset = TOP_CLUSTER*2;
	driverAPI[driveNum].read(drive->fatSector, 1, workBuffer);
	for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
		if (ushort(workBuffer[byteOffset]) == 0) {
			total++;
		}
		byteOffset +=2;
		if (byteOffset >= SECTOR_SIZE) {
			byteOffset = 0;
			secOffset ++;
			driverAPI[driveNum].read(drive->fatSector+secOffset, 1, workBuffer);
		}
	}
	*freeCnt = total;
	return 0;
}

/*-----------------------------------------------------------------------------*/
static int GetFreeClu(UCHAR driveNum, USHORT *freeClu)
{
	int			ret;

	if (fatDriveRes[driveNum].fileType == TYPE_FAT12) {
		ret = _GetFreeClu12(driveNum, freeClu);
	}
	else {	// TYPE_FAT16
		ret = _GetFreeClu16(driveNum, freeClu);
	}
	return ret;
}

/*-----------------------------------------------------------------------------*/
static int _GetFreeClu12(UCHAR driveNum, USHORT *freeClu)
{
	FATDRIVE_RES	*drive= &fatDriveRes[driveNum];
	USHORT		offset, secOffset, byteOffset, cluster;
	int			i, j;
	UCHAR		buf[3];

	cluster = drive->freeClu +1;
	if (cluster > drive->maxClu) {
		cluster = TOP_CLUSTER;
	}
	if (cluster & 0x01) {	/* odd number */
		offset = (cluster-1)*3/2;
	}
	else {
		offset = cluster*3/2;
	}
	secOffset = offset/SECTOR_SIZE;
	byteOffset = offset%SECTOR_SIZE;
	ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);

	for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
		for(j = 0; j < 3; j++) {
			buf[j] = workBuffer[byteOffset++];
			if (byteOffset >= SECTOR_SIZE) {
				byteOffset = 0;
				secOffset ++;
				ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
			}
		}

		if ((cluster & 0x01) == 0) {	/* even number */
			if (buf[0] == 0 && (buf[1] & 0x0F) == 0) {
				*freeClu = cluster;
				drive->freeClu = cluster;
/*
	buf[0]=[SECTOR_SIZE-1], buf[1]=[0], buf[2]=[1], byteOffset = 2
*/
				if (byteOffset == 2) {	/* sector over */
					workBuffer[0] = (workBuffer[0] & 0x0F0) + (UCHAR)((END_CLUSTER >> 8) & 0x0F);
					WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
					CopyFATSector(driveNum, secOffset, workBuffer);
					secOffset --;
					ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
					workBuffer[SECTOR_SIZE-1] = (UCHAR)END_CLUSTER;
					WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
					CopyFATSector(driveNum, secOffset, workBuffer);
				}
				else {
					if (byteOffset < 2) {
						secOffset --;
						ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
						byteOffset += SECTOR_SIZE;
					}
					byteOffset -= 3;	/* 1st byte */
					workBuffer[byteOffset] = (UCHAR)END_CLUSTER;
					workBuffer[byteOffset+1] = (workBuffer[byteOffset+1] & 0x0F0) + (UCHAR)((END_CLUSTER >> 8) & 0x0F);
					WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
					CopyFATSector(driveNum, secOffset, workBuffer);
				}
				return 0;
			}
			cluster ++;
			if (cluster > drive->maxClu) {
				cluster = TOP_CLUSTER;
				byteOffset = TOP_CLUSTER*3/2;
				secOffset = 0;
				ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
				continue;
			}
		}
		if ((buf[1] & 0xF0) == 0 && buf[2] == 0) {
			*freeClu = cluster;
			drive->freeClu = cluster;
/*
	buf[0]=[SECTOR_SIZE-2], buf[1]=[SECTOR_SIZE-1], buf[2]=[0], byteOffset = 1
*/
			if (byteOffset == 1) {		/* sector over */
				workBuffer[0] = (UCHAR)(END_CLUSTER >> 4);
				WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
				CopyFATSector(driveNum, secOffset, workBuffer);
				secOffset --;
				ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
				workBuffer[SECTOR_SIZE-1] = (workBuffer[SECTOR_SIZE-1] & 0x0F) + (UCHAR)(END_CLUSTER << 4);
				WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
				CopyFATSector(driveNum, secOffset, workBuffer);
			}
			else {
				if (byteOffset < 1) {
					secOffset --;
					ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
					byteOffset += SECTOR_SIZE;
				}
				byteOffset -= 2;	/* 2nd byte */
				workBuffer[byteOffset] = (workBuffer[byteOffset] & 0x0F) + (UCHAR)(END_CLUSTER << 4);
				workBuffer[byteOffset+1] = (UCHAR)(END_CLUSTER >> 4);
				WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
				CopyFATSector(driveNum, secOffset, workBuffer);
			}
			return 0;
		}
		i ++;
		cluster ++;
		if (cluster > drive->maxClu) {
			cluster = TOP_CLUSTER;
			byteOffset = TOP_CLUSTER*3/2;
			secOffset = 0;
			ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
		}
	}
	return -1;
}

/*-----------------------------------------------------------------------------*/
static int _GetFreeClu16(UCHAR driveNum, USHORT *freeClu)
{
	FATDRIVE_RES	*drive= &fatDriveRes[driveNum];
	USHORT		offset, secOffset, byteOffset, cluster;
	int			i;

	cluster = drive->freeClu +1;
	if (cluster > drive->maxClu) {
		cluster = TOP_CLUSTER;
	}
	offset = cluster*2;
	secOffset = offset/SECTOR_SIZE;
	byteOffset = offset%SECTOR_SIZE;
	ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);

	for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
		if (ushort(workBuffer[byteOffset]) == 0) {
			*freeClu = cluster;
			drive->freeClu = cluster;
			workBuffer[byteOffset] = (UCHAR)END_CLUSTER;
			workBuffer[byteOffset+1] = (UCHAR)(END_CLUSTER >> 8);
			WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
			CopyFATSector(driveNum, secOffset, workBuffer);
			return 0;
		}
		byteOffset +=2;
		if (byteOffset >= SECTOR_SIZE) {
			byteOffset = 0;
			secOffset ++;
			ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
		}

		cluster ++;
		if (cluster > drive->maxClu) {
			cluster = TOP_CLUSTER;
			byteOffset = TOP_CLUSTER*2;
			secOffset = 0;
			ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
		}
	}
	return -1;
}

/*-----------------------------------------------------------------------------*/
static int GetDirEntry(UCHAR driveNum, USHORT cluster, DIR_ENT *entry, ULONG *sector, USHORT *offset)
{
	FATDRIVE_RES	*drive= &fatDriveRes[driveNum];
	int			i, ret;
	USHORT		next;

	if (cluster == 0) {		/* root directory */
		if (_GetDirEntry(driveNum, cluster, entry, sector, offset) == 0) {
			return 0;
		}
		else {
			return -1;
		}
	}
	else {
		for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
			if (_GetDirEntry(driveNum, cluster, entry, sector, offset) == 0) {
				return 0;		/* found */
			}
			ret = NextFATEntry(driveNum, cluster, &next);
			if (ret != 1) {		/* cluster error/cluster end */
				break;
			}
			cluster = next;
		}
		return -1;	/* not found */
	}
}

/*-----------------------------------------------------------------------------*/
static int _GetDirEntry(UCHAR driveNum, USHORT cluster, DIR_ENT *entry, ULONG *secNum, USHORT *offset)
{
	FATDRIVE_RES	*drive= &fatDriveRes[driveNum];
	int			i, j, numSector;
	ULONG		sector;
	DIR_ENT		*readEntry;

	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);

			/* compair filename + extension */
			if (strncmp((char*)entry->filename, (char*)readEntry->filename, 11) == 0) {
				*entry = *readEntry;
				if (secNum != NULL) {
					*secNum = sector;
				}
				if (offset != NULL) {
					*offset = j;
				}
				return 0;
			}
		}
		sector ++;
	}
	return -1;
}

/*-----------------------------------------------------------------------------*/
static int AddDirEntry(UCHAR driveNum, USHORT cluster, DIR_ENT *entry)
{
	FATDRIVE_RES	*drive= &fatDriveRes[driveNum];
	int			i, ret;
	USHORT		newClu, next;
	ULONG		sector;

	if (cluster == 0) {		/* root directory */
		if (_AddDirEntry(driveNum, cluster, entry) == 0) {
			return 0;
		}
		else {
			return -1;
		}
	}
	else {
		for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
			if (_AddDirEntry(driveNum, cluster, entry) == 0) {
				return 0;
			}
			ret = NextFATEntry(driveNum, cluster, &next);
			if (ret < 0) {		/* cluster error */
				return -1;
			}
			if (ret == 0) {		/* cluster end */
				break;
			}
			cluster = next;
		}
		if (i > drive->maxClu) {	/* cluster chain error */
			return -1;
		}

		if (GetFreeClu(driveNum,&newClu) == 0) {
			sector = CluToSector(driveNum, newClu);
			memset(workBuffer, 0, SECTOR_SIZE);
			for(i = 1; i < drive->sectorPerClu; i++) {
				driverAPI[driveNum].write(sector+i, 1, workBuffer);
			}
			*(DIR_ENT *)(workBuffer) = *entry;
			WriteSector(driveNum, sector, workBuffer);
			WriteFATEntry(driveNum, cluster, newClu);
			return 0;
		}
		return -1;	/* disk full */
	}
}

/*-----------------------------------------------------------------------------*/
static int _AddDirEntry(UCHAR driveNum, USHORT cluster, DIR_ENT *entry)
{

	FATDRIVE_RES	*drive= &fatDriveRes[driveNum];
	int			i, j, numSector;
	ULONG		sector;
	DIR_ENT		*readEntry;


	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);
			if (readEntry->filename[0] == DELETE_MARK ||
				readEntry->filename[0] == 0) 	/* deleted or blank */
			{
				*readEntry = *entry;
				WriteSector(driveNum, sector, workBuffer);
				return 0;
			}
		}
		sector ++;
	}
	return -1;
}

/*-----------------------------------------------------------------------------*/
static int CheckDirEmpty(UCHAR driveNum, USHORT cluster)
{
	FATDRIVE_RES	*drive= &fatDriveRes[driveNum];
	int			i, ret;

⌨️ 快捷键说明

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