📄 fatfs.cpp
字号:
pDirEnt->offset = 0;
if (pDirEnt->sector >= pVolDesc->secPerClust)
{
pDirEnt->deNum = fatGetNext(pVolDesc, pDirEnt->deNum);
pDirEnt->sector = 0;
}
}
}
_VOL_DESC *dirGetVol(const char *path)
{
char drive[_MAX_DRIVE];
splitpath(path, drive, NULL, NULL, NULL);
if (drive[0])
{
int drv = tolower(drive[0]) - 'c';
if (drv >= 0 && drv < _countof(volDesc))
{
return (&volDesc[drv]);
}
}
return (&volDesc[0]);
}
BOOL dirMatch(_VOL_DESC *pVolDesc, _FILE_DESC *pFd, const char *name)
{
_DIRENT dirEnt;
dirEnt.deNum = pFd->startClust;
dirEnt.sector = 0;
dirEnt.offset = 0;
while (dirRead(pVolDesc, &dirEnt, pFd))
{
if (wildCompare(name, pFd->cAlternateName) || wildCompare(name, pFd->cFileName))
{
return (TRUE);
}
}
return (FALSE);
}
ULONG dirOpen(_VOL_DESC *pVolDesc, const char *path)
{
char dir[_MAX_DIR];
splitpath(path, NULL, dir, NULL, NULL);
char *dirName = dir;
ULONG deNum = pVolDesc->dirStartClust;
if (strlen(dirName) > 0)
{
char szName[_MAX_DIR];
const char chSep = '\\';
const char chNULL = '\0';
if (*dirName == chSep)
{
dirName++;
}
while (dirName && *dirName)
{
char *lpsz = strchr(dirName, chSep);
if (lpsz)
{
const int len = lpsz - dirName;
strncpy(szName, dirName, len + 1);
szName[len] = chNULL;
dirName = lpsz + 1;
}
else
{
strcpy(szName, dirName);
dirName = NULL;
}
_FILE_DESC Fd = { 0 };
Fd.startClust = deNum;
if (!dirMatch(pVolDesc, &Fd, szName))
{
return (-1);
}
deNum = Fd.startClust;
}
}
return (deNum);
}
HANDLE FindFirstFile(const char *lpFileName, _FIND_DATA *lpFindFileData)
{
_FIND_DESC *pFd;
if (HeapAlloc(fsDev.hFind, (void **) &pFd) == NOERROR)
{
pFd->pVolDesc = dirGetVol(lpFileName);
_DIRENT *dirEnt = &pFd->dirEnt;
dirEnt->deNum = dirOpen(pFd->pVolDesc, lpFileName);
dirEnt->offset = 0;
dirEnt->sector = 0;
if (dirEnt->deNum == -1)
{
HeapFree(fsDev.hFind, pFd);
return (NULL);
}
char szFName[_MAX_FNAME];
char szExt[_MAX_EXT];
splitpath(lpFileName, NULL, NULL, szFName, szExt);
makepath(pFd->cFileName, NULL, NULL, szFName, szExt);
_FILE_DESC Fd = { 0 };
while (dirRead(pFd->pVolDesc, dirEnt, &Fd))
{
if (wildCompare(pFd->cFileName, Fd.cFileName) || wildCompare(pFd->cFileName, Fd.cAlternateName))
{
strcpy(lpFindFileData->cFileName, Fd.cFileName);
strcpy(lpFindFileData->cAlternateName, Fd.cAlternateName);
lpFindFileData->dwAttributes = Fd.attrib;
return (pFd);
}
}
}
return (NULL);
}
BOOL FindNextFile(HANDLE hFind, _FIND_DATA *lpFindFileData)
{
_FIND_DESC *pFd = (_FIND_DESC *) (hFind);
_DIRENT *dirEnt = &pFd->dirEnt;
_FILE_DESC Fd = { 0 };
while (dirRead(pFd->pVolDesc, dirEnt, &Fd))
{
if (wildCompare(pFd->cFileName, Fd.cFileName) || wildCompare(pFd->cFileName, Fd.cAlternateName))
{
strcpy(lpFindFileData->cFileName, Fd.cFileName);
strcpy(lpFindFileData->cAlternateName, Fd.cAlternateName);
lpFindFileData->dwAttributes = Fd.attrib;
return (TRUE);
}
}
return (FALSE);
}
void FindClose(HANDLE hFind)
{
HeapFree(fsDev.hFind, hFind);
}
HANDLE CreateFile(const char *lpFileName)
{
_FILE_DESC *pFd;
if (HeapAlloc(fsDev.hFile, (void **)(&pFd)) == NOERROR)
{
pFd->pVolDesc = dirGetVol(lpFileName);
_DIRENT dirEnt;
dirEnt.deNum = dirOpen(pFd->pVolDesc, lpFileName);
dirEnt.sector = 0;
dirEnt.offset = 0;
char szFName[_MAX_FNAME];
char szExt[_MAX_EXT];
char szName[_MAX_PATH];
splitpath(lpFileName, NULL, NULL, szFName, szExt);
makepath(szName, NULL, NULL, szFName, szExt);
while (dirRead(pFd->pVolDesc, &dirEnt, pFd))
{
if (stricmp(szName, pFd->cFileName) == 0 || stricmp(szName, pFd->cAlternateName) == 0)
{
// pFd->buffer.buffer = (char *)malloc(BYTES_PER_SEC * pFd->pVolDesc->secPerClust);
return (pFd);
}
}
HeapFree(fsDev.hFile, pFd);
}
return (NULL);
}
void CloseFile(HANDLE hFile)
{
HeapFree(fsDev.hFile, hFile);
}
BOOL ReadFile(HANDLE hFile, void *lpBuffer, ULONG dwBytesToRead, ULONG *lpBytesReaded)
{
_FILE_DESC *pFd = (_FILE_DESC *) (hFile);
_VOL_DESC *pVolDesc = pFd->pVolDesc;
char *buffer = (char *)lpBuffer;
if (pFd->attrib & ATTR_DIRECTORY)
{
return (FALSE);
}
if (dwBytesToRead == 0)
{
return (TRUE);
}
if (pFd->pos >= pFd->size)
{
*lpBytesReaded = 0;
return (FALSE);
}
ULONG maxBytes = __min(dwBytesToRead, pFd->size - pFd->pos);
if (pFd->nSecs == 0)
{
ULONG Next = fatGetNext(pVolDesc, SEC_TO_CLUST(pVolDesc, pFd->curSec - 1));
if (Next != -1)
{
pFd->curSec = CLUST_TO_SEC(pVolDesc, Next);
pFd->nSecs = pVolDesc->secPerClust;
}
else
{
TRACE0("ERROR seekTo next cluster\r\n");
return (FALSE);
}
}
ULONG remainBytes = maxBytes;
*lpBytesReaded = 0;
/* for the beginning, process remain part of current sector */
ULONG work = OFFSET_IN_SEC(pVolDesc, pFd->pos); /* offset in sector */
ULONG numRW;
if (work != 0)
{
numRW = __min(remainBytes, pVolDesc->bytesPerSec - work);
if (cbioBytesRead(0, pFd->curSec, work, lpBuffer, numRW) != NOERROR)
{
TRACE0("ERROR ReadFile\r\n");
return (FALSE);
}
remainBytes -= numRW;
buffer += numRW;
pFd->pos += numRW;
*lpBytesReaded += numRW;
/* it may be current sector exhausted */
if (OFFSET_IN_SEC(pVolDesc, pFd->pos) == 0)
{
pFd->curSec++;
pFd->nSecs--;
}
}/* if( offset != 0 ) */
/* main loop: read entire sectors */
while (remainBytes >= pVolDesc->bytesPerSec)
{
/* get next contiguous block, if current already finished */
if (pFd->nSecs == 0)
{
ULONG Next = fatGetNext(pVolDesc, SEC_TO_CLUST(pVolDesc, pFd->curSec - 1));
if (Next != -1)
{
pFd->curSec = CLUST_TO_SEC(pVolDesc, Next);
pFd->nSecs = pVolDesc->secPerClust;
}
else
{
TRACE0("ERROR seek to next clust\r\n");
return (FALSE);
}
}
/* number of sectors to R/W */
numRW = __min(remainBytes / BYTES_PER_SEC, pFd->nSecs);
if (cbioRead(0, pFd->curSec, numRW, buffer) != NOERROR)
{
TRACE0("ERROR reading file\r\n");
return (FALSE);
}
/* correct position */
work = numRW * BYTES_PER_SEC;
remainBytes -= work;
buffer += work;
pFd->pos += work;
pFd->curSec += numRW;
pFd->nSecs -= numRW;
*lpBytesReaded += work;
}/* while ... */
/* now process remain part of data, that is shorter, than sector */
numRW = remainBytes;
if (numRW > 0)
{
/* get next contiguous block, if current already finished */
if (pFd->nSecs == 0)
{
ULONG Next = fatGetNext(pVolDesc, SEC_TO_CLUST(pVolDesc, pFd->curSec - 1));
if (Next != -1)
{
pFd->curSec = CLUST_TO_SEC(pVolDesc, Next);
pFd->nSecs = pVolDesc->secPerClust;
}
else
{
TRACE0("ERROR seek to next clust\r\n");
return (FALSE);
}
}
if (cbioBytesRead(0, pFd->curSec, 0, buffer, numRW) != NOERROR)
{
TRACE0("ERROR reading file\r\n");
return (FALSE);
}
remainBytes -= numRW;
buffer += numRW;
pFd->pos += numRW;
*lpBytesReaded += numRW;
}
return (TRUE);
}
void volTest(void)
{
HANDLE hFile = CreateFile("驼铃.mp3");
if (hFile)
{
CloseFile(hFile);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -