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

📄 fat.c

📁 一个小型的FAT文件系统,支持FAT12/16和目录
💻 C
📖 第 1 页 / 共 5 页
字号:
		return E_FILE_PATH;
	}
	if ((entry.attrib & FA_VOLUME) != 0) {
		return E_FILE_PATH;	/* not file/directory attribution */
	}

	if (finfo != NULL) {
		EntryToInfo(&entry, finfo);
	}
	return E_FILE_OK;
}

/*-----------------------------------------------------------------------------*/
int FATGetDriveInfo(UCHAR driveNum, DRIVE_INFO *drvInfo)
{
	FATDRIVE_RES	*drive;

	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 (drvInfo != NULL) {
		drvInfo->sectorSize = SECTOR_SIZE;
		drvInfo->sectorPerClu = drive->sectorPerClu;
		GetTotalFreeClu(driveNum, &(drvInfo->freeClu));
		drvInfo->totalClu = drive->totalSector;
	}
	return E_FILE_OK;
}

/*-----------------------------------------------------------------------------*/
int FATChdir(UCHAR driveNum, const UCHAR *path)
{
	FATDRIVE_RES	*drive;
	USHORT		cluster;

	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;
	}
	if (workPath[0] != '\\') {	/* relative path */
		if (strlen((char*)drive->currPath) + strlen((char*)workPath) > PATH_LEN_MAX-1) {	/* -1 for '\' */
			return E_FILE_PATH_LEN;
		}
	}

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

	if (drive->currClu != cluster) {
		drive->currClu = cluster;
		ChangePath(workPath, drive->currPath);
	}
	return E_FILE_OK;
}



/*-----------------------------------------------------------------------------*/
int FATCwd(UCHAR driveNum, UCHAR **path)
{
	FATDRIVE_RES	*drive;

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

	*path = drive->currPath;

	return E_FILE_OK;
}


/********************************************************************************
	LOCAL FUNCTIONS
 ********************************************************************************/
/*-----------------------------------------------------------------------------*/
int DriveInit(UCHAR driveNum)
{
	int			ret;
	FATDRIVE_RES	*drive;
	BOOT_INFO	*boot;
	ULONG		systemSector;

	drive = &fatDriveRes[driveNum];
	ret = driverAPI[driveNum].init();
	if (ret !=  0) {
		drive->ready_flag = 0;
		return E_FILE_NOT_READY;
	}
	ret = driverAPI[driveNum].read(0, 1, workBuffer);	/* read logical sector 0 */
	if (ret != 0) {
		drive->ready_flag = 0;
		return E_FILE_NOT_READY;
	}

	if (workBuffer[0x1FE] == 0x55 && workBuffer[0x1FF] == 0xAA) {
		/* Harddisk type */
		drive->bootSector = GET_ULONG(ulong(workBuffer[0x1C6]));
		driverAPI[driveNum].read(drive->bootSector, 1, workBuffer);
	}
	else {
		/* Floppy type */
		drive->bootSector = 0;
	}
	boot = (BOOT_INFO *)workBuffer;

	if (!(
		(boot->jumpcode[0] == 0xEB || boot->jumpcode[2] == 0x90) ||
		boot->jumpcode[0] == 0xE9
		))
	{
		return E_FILE_FORMAT;
	}
	if (GET_USHORT(boot->bytePerSector) != SECTOR_SIZE) {
		return E_FILE_FORMAT;
	}
	if (GET_USHORT(boot->rootDirEntry) == 0) {	/* FAT32 */
		return E_FILE_FORMAT;
	}

	drive->sectorPerClu = boot->sectorPerClu;
	drive->numFAT = boot->numFAT;
	drive->sectorPerFAT = GET_USHORT(boot->sectorPerFAT);

	if (boot->totalSector == 0) {
		drive->totalSector = GET_ULONG(boot->bigTotalSector);
	}
	else {
		drive->totalSector = GET_USHORT(boot->totalSector);
	}

	drive->numRootSector = (GET_USHORT(boot->rootDirEntry)*32)/SECTOR_SIZE;
	drive->fatSector = drive->bootSector + GET_USHORT(boot->reservedSector);
	drive->rootSector = drive->fatSector + (drive->sectorPerFAT * drive->numFAT);

	systemSector = (drive->rootSector - drive->bootSector) + drive->numRootSector;
	drive->maxClu = (USHORT)((drive->totalSector - systemSector)/drive->sectorPerClu+TOP_CLUSTER-1);
	drive->freeClu = TOP_CLUSTER-1;

	if (drive->maxClu > MAX_CLUSTER & 0xFFF) {
		drive->fileType = TYPE_FAT16;
	}
	else {
		drive->fileType = TYPE_FAT12;
	}

	strcpy((char*)drive->currPath, "\\");	// current path = root
	drive->currClu = 0;
	drive->ready_flag = 1;


	driverAPI[driveNum].read(drive->fatSector, 1, workBuffer);


	return E_FILE_OK;
}

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

	for(i = 0; i < FAT_FILE_MAX; i++) {
		fatFileRes[i].use_flag = 0;
	}
}

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

	for(i = 0; i < FAT_DRIVE_MAX; i++) {
		fatDriveRes[i].ready_flag = 0;
	}
}

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

	for(i = 0; i < CFG_CACHE_NUM; i++) {
		cacheRes[i].use_flag = 0;
	}
	useTopList = -1;	// empty
}

/*-----------------------------------------------------------------------------*/
static ULONG CluToSector(UCHAR driveNum, USHORT cluster)
{
	FATDRIVE_RES	*drive;

	drive = &fatDriveRes[driveNum];

	return (drive->rootSector+drive->numRootSector+(cluster-2)*drive->sectorPerClu);
}

/*-----------------------------------------------------------------------------*/
static int PosToCluster(UCHAR driveNum, ULONG pos, USHORT topClu, USHORT *cluster, USHORT *secOffset)
{
	FATDRIVE_RES	*drive;
	USHORT		cluSize, next;
	int			i, listNum;

	drive = &fatDriveRes[driveNum];

	cluSize = SECTOR_SIZE * drive->sectorPerClu;
	listNum = (int)(pos/cluSize);
	*cluster = topClu;

	for(i = 0; i < listNum; i++) {
		if (NextFATEntry(driveNum, *cluster, &next) != 1) {	/* error or end of cluster */
			return -1;
		}
		*cluster = next;
	}
	*secOffset = (USHORT)((pos % cluSize)/SECTOR_SIZE);
	return 0;
}

/*-----------------------------------------------------------------------------*/
static void EntryToInfo(DIR_ENT *entry, FILE_INFO *finfo)
{
	finfo->year = (entry->upDate >> 9) + 1980;
	finfo->month = (UCHAR)((entry->upDate >> 5) & 0x0F);
	finfo->day = (UCHAR)(entry->upDate & 0x1F);
	finfo->hour = (UCHAR)(entry->upTime >> 11);
	finfo->minute = (UCHAR)((entry->upTime >> 5) & 0x3F);
	finfo->second = (UCHAR)((entry->upTime & 0x1F)*2);
	finfo->attrib = entry->attrib;
	finfo->size = entry->size;
}


/*-----------------------------------------------------------------------------*/
static int ReadFATEntry(UCHAR driveNum, USHORT cluster, USHORT *value)
{
	int		ret;

	if (fatDriveRes[driveNum].fileType == TYPE_FAT12)
		ret = _ReadFATEntry12(driveNum, cluster, value);
	else	// TYPE_FAT16
		ret = _ReadFATEntry16(driveNum, cluster, value);
	return ret;
}

/*-----------------------------------------------------------------------------*/
static int _ReadFATEntry12(UCHAR driveNum, USHORT cluster, USHORT *value)
{
	FATDRIVE_RES	*drive= &fatDriveRes[driveNum];
	UCHAR		out[2];
	USHORT		offset, secOffset, byteOffset;
	int			ret;

	if (cluster < TOP_CLUSTER || cluster > drive->maxClu) {
		return -1;
	}

	offset = cluster*3/2;
	secOffset = offset/SECTOR_SIZE;
	byteOffset = offset%SECTOR_SIZE;

	if (byteOffset == SECTOR_SIZE-1) {	/* sector over ? */
		ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
		out[0] = workBuffer[byteOffset];
		ret = ReadSector(driveNum, drive->fatSector+secOffset+1, workBuffer);
		out[1] = workBuffer[0];
	}
	else {
		ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
		out[0] = workBuffer[byteOffset];
		out[1] = workBuffer[byteOffset+1];
	}

	if (cluster & 0x01) {	/* odd number */
		*value = ((USHORT)(out[1]) << 4) + (out[0] >> 4);
	}
	else {		/* even */
		*value = ((USHORT)(out[1] & 0x0f) << 8) + out[0];
	}
	return 0;
}

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

	if (cluster < TOP_CLUSTER || cluster > drive->maxClu) {
		return -1;
	}

	offset = cluster*2;
	secOffset = offset/SECTOR_SIZE;
	byteOffset = offset%SECTOR_SIZE;

	ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
	*value = GET_USHORT(ushort(workBuffer[byteOffset]));

	return 0;
}

/*-----------------------------------------------------------------------------*/
static int WriteFATEntry(UCHAR driveNum, USHORT cluster, USHORT value)
{
	int		ret;

	if (fatDriveRes[driveNum].fileType == TYPE_FAT12)
		ret = _WriteFATEntry12(driveNum, cluster, value & 0xFFF);
	else	// TYPE_FAT16
		ret = _WriteFATEntry16(driveNum, cluster, value);
	return ret;
}

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

	if (cluster < TOP_CLUSTER || cluster > drive->maxClu) {
		return -1;
	}
	offset = cluster*3/2;
	secOffset = offset/SECTOR_SIZE;
	byteOffset = offset%SECTOR_SIZE;

	if (byteOffset == SECTOR_SIZE-1) {	/* sector over ? */
		ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
		if (cluster & 0x01) { /* odd number */
			workBuffer[byteOffset] = (workBuffer[byteOffset] & 0x0F) + ((UCHAR)value << 4);
		}
		else {	/* even */
			workBuffer[byteOffset] = (UCHAR)value;
		}
		WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
		CopyFATSector(driveNum, secOffset, workBuffer);

		secOffset ++;
		ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
		if (cluster & 0x01) { /* odd number */
			workBuffer[0] = (UCHAR)(value >> 4);
		}
		else {	/* even */
			workBuffer[0] = (workBuffer[byteOffset+1] & 0xF0) + (UCHAR)(value >> 8);
		}
		WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
		CopyFATSector(driveNum, secOffset, workBuffer);
	}
	else {
		ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
		if (cluster & 0x01) { /* odd number */
			workBuffer[byteOffset] = (workBuffer[byteOffset] & 0x0F) + ((UCHAR)value << 4);
			workBuffer[byteOffset+1] = (UCHAR)(value >> 4);
		}
		else {	/* even */
			workBuffer[byteOffset] = (UCHAR)value;
			workBuffer[byteOffset+1] = (workBuffer[byteOffset+1] & 0xF0) + (UCHAR)(value >> 8);
		}
		WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
		CopyFATSector(driveNum, secOffset, workBuffer);
	}
	return 0;
}

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

	if (cluster < TOP_CLUSTER || cluster > drive->maxClu) {
		return -1;
	}
	offset = cluster*2;
	secOffset = offset/SECTOR_SIZE;
	byteOffset = offset%SECTOR_SIZE;

	ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
	workBuffer[byteOffset] = (UCHAR)(value & 0xFF);
	workBuffer[byteOffset+1] = (UCHAR)(value >> 8);
	WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
	CopyFATSector(driveNum, secOffset, workBuffer);

	return 0;
}

/*-----------------------------------------------------------------------------*/
/*
Return value
	0	: last cluster
	1	: exist next cluster
*/

static int NextFATEntry(UCHAR driveNum, USHORT cluster, USHORT *next)
{
	FATDRIVE_RES	*drive= &fatDriveRes[driveNum];

	if (ReadFATEntry(driveNum, cluster, next) < 0) {
		return -1;
	}

	if (drive->fileType == TYPE_FAT12) {
		if ((*next & (END_CLUSTER & 0xFFF)) == END_CLUSTER) {
			return 0;
		}
	}
	else {	/* TYPE_FAT16 */
		if ((*next & END_CLUSTER) == END_CLUSTER) {
			return 0;
		}
	}
	if (*next >= TOP_CLUSTER || *next <= drive->maxClu) {
		return 1;
	}
	return -1;
}


/*-----------------------------------------------------------------------------*/
static int CopyFATSector(UCHAR driveNum, USHORT secOffset, UCHAR *buf)
{
	FATDRIVE_RES	*drive= &fatDriveRes[driveNum];
	int			i;
	ULONG		sector;

	sector = drive->fatSector+drive->sectorPerFAT+secOffset;
	for(i = 1; i < drive->numFAT; i++) {
		driverAPI[driveNum].write(sector, 1, buf);
		sector += drive->sectorPerFAT;
	}
	return 0;
}

/*-----------------------------------------------------------------------------*/
static int ReadSector(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);
				cache->write_flag = 0;
			}
			cacheRes[prev].next = -1;	// set end-mark
		}
		driverAPI[driveNum].read(sector, 1, cache->buffer);
		cache->drive = driveNum;
		cache->sector = sector;
	}
	memcpy(buf, cache->buffer, SECTOR_SIZE);
	cache->next = useTopList;

⌨️ 快捷键说明

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