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

📄 fatfs.cpp

📁 一个朋友给我的FAT文件系统源代码,兼职FAT16/32,针对ARM挂硬盘开发的!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "fatFs.h"
#include <cbio.h>
#include <rtx.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

/* defines */
/* File System Information Sector number */
#define FSINFO_SEC_NUM	1

/* Offset of free clusters count field in the File System Information Sector */
#define FSINFO_SIGN			484
#define FSINFO_FREE_CLUSTS	488
#define FSINFO_NEXT_FREE	492

#define CLUST_TO_SEC(pVolDesc, clustNum) \
		(((clustNum) - DOS_MIN_CLUST) * (pVolDesc)->secPerClust + (pVolDesc)->dataStartSec)
#define SEC_TO_CLUST(pVolDesc, secNum)	(((secNum) - (pVolDesc)->dataStartSec) / (pVolDesc)->secPerClust + DOS_MIN_CLUST)
#define DOT								"."//本层目录
#define DOTDOT							".."//上一层目录
#define IS_DOT(s)						(strcmp(s, DOT) == 0)
#define IS_DOTDOT(s)					(strcmp(s, DOTDOT) == 0)

_VOL_DESC	volDesc[PART_MAX_ENTRIES];
_FS_DEV		fsDev = { 0 };

BOOL fsStart(void)//
{
	char	mbrSec[BYTES_PER_SEC];
	if (cbioRead(0, 0, 1, mbrSec) != NOERROR)
	{
		TRACE0("ERROR reading device MBR sector\r\n");
		return (ERROR);
	}

	if (mbrSec[510] != 0x55 || mbrSec[511] != 0xaa)/*偏移量为510和511的地方包含标记0XAA55 
	{
		TRACE0("ERROR no signature word at end of boot sector\r\n");
		return (ERROR);
	}

	int idVol = 0;
	for (int i = 0; i < 4; i++)
	{
		_FS_PART_TBL	fsPart;

		const int		nOffset = (i * 16) + DOS_BOOT_PART_TBL;

		fsPart.startHead = mbrSec[nOffset + 0x1];

		short	work = mbrSec[nOffset + 0x2];
		fsPart.startSector = work & 0x3f;
		fsPart.startCylinder = ((work & 0xC0) << 2) + mbrSec[nOffset + 0x3];

		fsPart.type = mbrSec[nOffset + 0x4];

		fsPart.endHead = mbrSec[nOffset + 0x5];
		work = mbrSec[nOffset + 0x6];
		fsPart.endSector = work & 0x3f;
		fsPart.endCylinder = ((work & 0xC0) << 2) + mbrSec[nOffset + 0x7];

		fsPart.absSector = DISK_TO_LONG(mbrSec + nOffset + 0x8);
		fsPart.totalSecs = DISK_TO_LONG(mbrSec + nOffset + 0xc);

		if (fsPart.type == 0xb || fsPart.type == 0xc)
			// FAT32
		{
			_VOL_DESC	*pVolDesc = &volDesc[idVol];
			if (volMount(&fsPart, pVolDesc))
			{
				pVolDesc->volOk = TRUE;
				idVol++;
			}
		}
	}

	if (HeapCreate(sizeof(_FIND_DESC), 8, &fsDev.hFind) != NOERROR)
	{
		TRACE0("ERROR alloc _FIND_DESC\r\n");
		return (ERROR);
	}

	if (HeapCreate(sizeof(_FILE_DESC), DOS_NFILES_DEFAULT, &fsDev.hFile) != NOERROR)
	{
		TRACE0("ERROR alloc _FILE_DESC\r\n");
		return (ERROR);
	}

	return (NOERROR);
}

BOOL volMount(_FS_PART_TBL *pFs, _VOL_DESC *pVolDesc)//挂载卷
{
	char	bootSec[BYTES_PER_SEC];
	long	work;

	pVolDesc->volOk = FALSE;
	if (cbioRead(0, pFs->absSector, 1, bootSec) != NOERROR)
	{
		TRACE0("ERROR reading device boot sector\r\n");
		return (FALSE);
	}

	if (bootSec[DOS_BOOT_JMP] != 0xe9 && bootSec[DOS_BOOT_JMP] != 0xeb)
	{
		TRACE0("ERROR check for both acceptable Intel 80x86 `jmp' opcodes\r\n");
		return (FALSE);
	}

	work = DISK_TO_SHORT(bootSec + DOS_BOOT_BYTES_PER_SEC);
	if (work == 0 || work != BYTES_PER_SEC)
	{
		TRACE0("ERROR bytesPerSec\r\n");
		return (FALSE);
	}

	pVolDesc->bytesPerSec = work;

	work = DISK_TO_SHORT(bootSec + DOS_BOOT_NSECTORS);
	if (work == 0)
	{
		work = DISK_TO_LONG(bootSec + DOS_BOOT_LONG_NSECTORS);
		if (work == 0)
		{
			TRACE0("ERROR totalSecs\r\n");
			return (FALSE);
		}
	}

	pVolDesc->totalSecs = work;

	pVolDesc->secPerClust = bootSec[DOS_BOOT_SEC_PER_CLUST];
	if (pVolDesc->secPerClust == 0)
	{
		TRACE0("ERROR secPerClust\r\n");
		return (FALSE);
	}

	pVolDesc->nFats = bootSec[DOS_BOOT_NFATS];
	if (pVolDesc->nFats == 0)
	{
		TRACE0("ERROR nFats\r\n");
		return (FALSE);
	}

	pVolDesc->nHiddenSecs = DISK_TO_SHORT(bootSec + DOS_BOOT_NHIDDEN_SECS);

	/* evaluate the number of reserved sectors */
	pVolDesc->nReservedSecs = DISK_TO_SHORT(bootSec + DOS_BOOT_NRESRVD_SECS);
	if (pVolDesc->nReservedSecs == 0)
	{
		TRACE0("ERROR nReservedSecs\r\n");
		return (FALSE);
	}

	/* evaluate the number of sectors alloted to FAT table */
	pVolDesc->secPerFat = DISK_TO_SHORT(bootSec + DOS_BOOT_SEC_PER_FAT);

	if (pVolDesc->secPerFat != 0)
	{
		TRACE0("ERROR secPerFat\r\n");
		return (FALSE);
	}

	pVolDesc->fatType = FAT32;
	pVolDesc->secPerFat = DISK_TO_LONG(bootSec + DOS32_BOOT_SEC_PER_FAT);
	if (pVolDesc->secPerFat == 0)
	{
		TRACE0("ERROR secPerFat32\r\n");
		return (FALSE);
	}

	pVolDesc->volIdOff = DOS32_BOOT_VOL_ID;
	pVolDesc->volLabOff = DOS32_BOOT_VOL_LABEL;

	pVolDesc->fatStartSec = pFs->absSector + pVolDesc->nReservedSecs;
	pVolDesc->dataStartSec = pFs->absSector + pVolDesc->nReservedSecs + pVolDesc->secPerFat * pVolDesc->nFats;
	pVolDesc->dirStartClust = DISK_TO_LONG(bootSec + DOS32_BOOT_ROOT_START_CLUST);

	pVolDesc->volId = DISK_TO_LONG(bootSec + pVolDesc->volIdOff);
	memcpy(pVolDesc->bootVolLab, bootSec + pVolDesc->volLabOff, DOS_VOL_LABEL_LEN);
	*(pVolDesc->bootVolLab + DOS_VOL_LABEL_LEN) = '\0';

	pVolDesc->bootSecNum = pFs->absSector;
	pVolDesc->volOk = TRUE;

	_FAT_DESC	*pFat = &pVolDesc->fatDesc;
	pFat->buffer = (ULONG *)malloc(BYTES_PER_SEC);
	pFat->sector = 0;

	return (TRUE);
}

ULONG fatGetNext(_VOL_DESC *pVolDesc, ULONG deNum)
{
	_FAT_DESC	*pFat = &pVolDesc->fatDesc;
	ULONG		startSec = pVolDesc->fatStartSec + (deNum * sizeof(ULONG) / BYTES_PER_SEC);
	if (startSec != pFat->sector)
	{
		if (ataRead(0, startSec, 1, pFat->buffer) != NOERROR)
		{
			TRACE1("ERROR reading fat sector %d\r\n", startSec);
			return (ULONG(-1));
		}

		pFat->sector = startSec;
	}

	return (pFat->buffer[deNum % (BYTES_PER_SEC / sizeof(ULONG))]);
}

void dirLongName(const char *dirEnt, char *pName)
{
}

void dirShortName(const char *dirEnt, char *pName)
{
	const char	chNULL = '\0';
	const char	chWs = ' ';

	char		szName[DOS_STDNAME_LEN + 1];
	char		*dst = szName;
	const char	*src = dirEnt + 0;

	for (int i = 0; i < DOS_STDNAME_LEN; i++)
	{
		char	ch = *src++;

		if (ch != chWs)
		{
			*dst++ = ch;
		}
		else
		{
			*dst = chNULL;
			break;
		}
	}

	*dst = chNULL;

	if (IS_DOT(szName) || IS_DOTDOT(szName))
	{
		strcpy(pName, szName);
		return;
	}

	char	szExt[DOS_STDEXT_LEN + 1];
	dst = szExt;
	src = dirEnt + DOS_STDNAME_LEN;

	for (int i = 0; i < DOS_STDEXT_LEN; i++)
	{
		char	ch = *src++;
		if (ch != chWs)
		{
			*dst++ = ch;
		}
		else
		{
			*dst = chNULL;
			break;
		}
	}

	*dst = chNULL;

	strcpy(pName, szName);
	if (*szExt != chNULL)
	{
		strcat(pName, DOT);
		strcat(pName, szExt);
	}
}

BOOL dirRead(_VOL_DESC *pVolDesc, _DIRENT *pDirEnt, _FILE_DESC *pFd)
{
	for (;;)
	{
		const char	chNULL = '\0';
		char		dirSec[BYTES_PER_SEC];
		char		shortName[DOS_STDNAME_LEN + DOS_STDEXT_LEN + 2] = { 0 };
		char		longName[_MAX_PATH] = { 0 };

		if (ataRead(0, CLUST_TO_SEC(pVolDesc, pDirEnt->deNum) + pDirEnt->sector, 1, dirSec) != NOERROR)
		{
			TRACE0("ERROR dirRead\r\n");
			return (FALSE);
		}

		while (pDirEnt->offset < BYTES_PER_SEC / DOS_DIRENT_STD_LEN)
		{
			char	*dirEnt = dirSec + (pDirEnt->offset * DOS_DIRENT_STD_LEN);
			pDirEnt->offset++;

			DWORD	attr = dirEnt[DOS_ATTRIB_OFF];
			if (attr == ATTR_VOLUME_ID)
			{
				TRACE1("ATTR_VOLUME_ID(%08s)\r\n", dirEnt);
				continue;
			}

			const int	dirName0 = dirEnt[0];
			if (dirName0 == 0)
			{
				return (FALSE);
			}

			if (dirName0 == 0xE5)
			{
				continue;
			}

			if ((attr & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME)
			{
				if (dirName0 & LAST_LONG_ENTRY)
				{
					longName[0] = chNULL;
				}

				dirLongName(dirEnt, longName);
			}
			else
			{
				dirShortName(dirEnt, shortName);
				if (!longName[0])
				{
					strcpy(longName, shortName);
				}

				if (pFd != NULL)
				{
					strcpy(pFd->cFileName, longName);
					strcpy(pFd->cAlternateName, shortName);
					pFd->attrib = attr;
					pFd->size = DISK_TO_LONG(dirEnt + DOS_FILE_SIZE_OFF);
					pFd->pos = 0;
					pFd->startClust = START_CLUST_DECODE(pVolDesc, dirEnt);
					pFd->nSecs = pVolDesc->secPerClust;
					pFd->curSec = CLUST_TO_SEC(pVolDesc, pFd->startClust);
				}

				shortName[0] = chNULL;
				longName[0] = chNULL;
				return (TRUE);
			}
		}

		pDirEnt->sector++;

⌨️ 快捷键说明

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