📄 hfatfile.c
字号:
//---------------------------------------------------------------------------------
// Copyright jinhailiao 2008-2010
// E-mail: jinhailiao@163.com
// Project: HFAT16/32
// File: hfatfile.c
// Description:
//-------------------------------------------------------------
// Reversion Histroy:
//-------------------------------------------------------------
// Version date operations by who
// 1.0.0 2008-06-26 create Kingsea
//---------------------------------------------------------------------------------
#include "hfstype.h"
#include "hfileapi.h"
#include "hfilesys.h"
#include "hfatfile.h"
#include "hfatsys.h"
#include "haiclib.h"
#include "hfatstr.h"
#include "hfatdent.h"
const struct FILECONST fileconst[] =
{
{"a" , _H_O_WRONLY|_H_O_CREAT|_H_O_APPEND|_H_O_TEXT},
{"r" , _H_O_RDONLY|_H_O_TEXT},
{"w" , _H_O_WRONLY|_H_O_CREAT|_H_O_TRUNC|_H_O_TEXT},
{"ab" , _H_O_WRONLY|_H_O_CREAT|_H_O_APPEND|_H_O_BINARY},
{"rb" , _H_O_RDONLY|_H_O_BINARY},
{"wb" , _H_O_WRONLY|_H_O_CREAT|_H_O_TRUNC|_H_O_BINARY},
{"a+" , _H_O_RDWR|_H_O_CREAT|_H_O_APPEND|_H_O_TEXT},
{"r+" , _H_O_RDWR|_H_O_TEXT},
{"w+" , _H_O_RDWR|_H_O_CREAT|_H_O_TRUNC|_H_O_TEXT},
{"a+b", _H_O_RDWR|_H_O_CREAT|_H_O_APPEND|_H_O_BINARY},
{"r+b", _H_O_RDWR|_H_O_BINARY},
{"w+b", _H_O_RDWR|_H_O_CREAT|_H_O_TRUNC|_H_O_BINARY},
{"ab+", _H_O_RDWR|_H_O_CREAT|_H_O_APPEND|_H_O_BINARY},
{"rb+", _H_O_RDWR|_H_O_BINARY},
{"wb+", _H_O_RDWR|_H_O_CREAT|_H_O_TRUNC|_H_O_BINARY}
};
void _hai_GetFileInfo(SP_FATFILEINF pfileinf, S_BYTE *DentBuf)
{
S_WORD ClustHi = HAI_MAKEWORD(pDIR_FstClusHI(DentBuf));
S_WORD ClustLo = HAI_MAKEWORD(pDIR_FstClusLO(DentBuf));
hai_memcpy(pfileinf->DirName, DentBuf, sDIR_Name);
pfileinf->CrtTimeTenth = *pDIR_CrtTimeTenth(DentBuf);
pfileinf->CrtTime = HAI_MAKEWORD(pDIR_CrtTime(DentBuf));
pfileinf->CrtDate = HAI_MAKEWORD(pDIR_CrtDate(DentBuf));
pfileinf->LastAccDate = HAI_MAKEWORD(pDIR_LastAccDate(DentBuf));
pfileinf->WrtTime = HAI_MAKEWORD(pDIR_WrtTime(DentBuf));
pfileinf->WrtDate = HAI_MAKEWORD(pDIR_WrtDate(DentBuf));
pfileinf->FirstClust = HAI_COMBDWORD(ClustHi, ClustLo);
pfileinf->FileSize = HAI_MAKEDWORD(pDIR_FileSize(DentBuf));
}
int _hai_CheckFileOpenOnFat(int dev, void *fileop, S_DWORD DentSec, S_WORD DentNum, S_BYTE *DentBuf)
{
SH_FATFILEOP hFileOp = (SH_FATFILEOP)fileop;
SP_FATFILEINF pfileinf = hFileOp->pfileinf;
S_WORD ClustHi = HAI_MAKEWORD(pDIR_FstClusHI(DentBuf));
S_WORD ClustLo = HAI_MAKEWORD(pDIR_FstClusLO(DentBuf));
if (pfileinf->dev == dev && pfileinf->DentSec == DentSec && pfileinf->DentNum == DentNum
&& pfileinf->attrib == *pDIR_Attr(DentBuf) && pfileinf->FirstClust == HAI_COMBDWORD(ClustHi, ClustLo))
return 1;
return 0;
}
int _hai_FlushFileBuf(int dev, SP_FILEBUF pFileBuf)
{
int err;
S_DWORD SecNum;
if (pFileBuf->flush == 0)
return 0;
SecNum = DevInf_FirstDatSec(dev) + (pFileBuf->Clust-2)*DevInf_SecPerClust(dev) + pFileBuf->SecNum;
if ((err = _hai_FatDevWrite(dev, SecNum, pFileBuf->SecBuf)) == 0)
pFileBuf->flush = 0;
return err;
}
int _hai_Flush2ReadFileBuf(int dev, S_DWORD Clust, S_BYTE SecNum, SP_FILEBUF pFileBuf)
{
int err;
S_DWORD Secuter;
if (Clust==pFileBuf->Clust && SecNum==pFileBuf->SecNum)
return 0;
if (err = _hai_FlushFileBuf(dev, pFileBuf))
return err;
Secuter = DevInf_FirstDatSec(dev) + (Clust-2)*DevInf_SecPerClust(dev) + SecNum;
if (err = _hai_FatDevRead(dev, Secuter, pFileBuf->SecBuf))
{
hai_memset(pFileBuf, 0x00, sizeof(*pFileBuf));
}
else
{
pFileBuf->flush = 0;
pFileBuf->Clust = Clust;
pFileBuf->SecNum = SecNum;
}
return err;
}
SP_FATFILEINF _hai_OpenFileOnFat(int dev, const S_BYTE *file, S_WORD mode)
{
int err;
S_BYTE ShareOpen = 0;
S_WORD DentNum, LDentNum;
S_DWORD DSecNum = 0, LDSecNum = 0;
S_DWORD clust;
S_BYTE DentBuf[FAT_DIRENT_SIZE];
SP_FATFILEINF pfileinf;
SH_FATFILEOP hfileop;
if ((pfileinf = hai_FatMemAlloc(sizeof(*pfileinf))) == S_NULL)
return S_NULL;
hai_memset(pfileinf, 0x00, sizeof(*pfileinf));
clust = _hai_CwdOperate(CWDOPERATE_GETCLUS, S_NULL);
err = hai_LocationDent(dev, clust, file, &DSecNum, &DentNum, &LDSecNum, &LDentNum, DentBuf);
if (err == FATERR_INVALID_FILENAME)
{
if (mode&_H_O_CREAT)
{
DSecNum = hai_CreateFileDent(dev, clust, file, &DentNum, DentBuf);
err = hai_LocationDent(dev, clust, file, &DSecNum, &DentNum, &LDSecNum, &LDentNum, DentBuf);
}
if (err)
{
hai_FatMemFree(pfileinf);
pfileinf = S_NULL;
}
}
else if (err == FATERR_NO_ERROR)
{
if (IS_FILE_ATTR(DentBuf, FILE_ATTR_DIRECTORY))
{
hai_FatMemFree(pfileinf);
pfileinf = S_NULL;
}
else if (hfileop = (SH_FATFILEOP)_hai_CheckFileIsOpened(dev, DSecNum, DentNum, DentBuf))
{
hai_FatMemFree(pfileinf);
pfileinf = S_NULL;
if (!(mode&_H_O_WRONLY))
{
pfileinf = hfileop->pfileinf;
pfileinf->OpenCnt += 1;
ShareOpen = 1;
}
}
else if ((mode&_H_O_WRONLY)&&(IS_FILE_ATTR(DentBuf, FILE_ATTR_READ_ONLY)))
{
hai_FatMemFree(pfileinf);
pfileinf = S_NULL;
}
else if (mode&_H_O_TRUNC)
{
if (_hai_TruncateFile(dev, DSecNum, DentNum))
{
hai_FatMemFree(pfileinf);
pfileinf = S_NULL;
}
else
{
HAI_WRITEWORD(pDIR_FstClusHI(DentBuf), 0x00);
HAI_WRITEWORD(pDIR_FstClusLO(DentBuf), 0x00);
HAI_WRITEDWORD(pDIR_FileSize(DentBuf), 0x00);
}
}
}
else
{
hai_FatMemFree(pfileinf);
pfileinf = S_NULL;
}
if(pfileinf && !ShareOpen)
{
pfileinf->dev = dev;
pfileinf->DentNum = DentNum;
pfileinf->DentSec = DSecNum;
pfileinf->OpenCnt = 1;
_hai_GetFileInfo(pfileinf, DentBuf);
pfileinf->pSecbuf = hai_FatMemAlloc(sizeof(S_FILEBUF));
if (pfileinf->pSecbuf)
hai_memset(pfileinf->pSecbuf, 0x00, sizeof(S_FILEBUF));
}
return pfileinf;
}
SH_FATFILEOP _hai_fopenOnFat(S_BYTE disk, const S_BYTE *file, const char *mode)
{
int i;
SH_FATFILEOP hfile;
if ((hfile = hai_FatMemAlloc(sizeof(*hfile))) == S_NULL)
return S_NULL;
hai_memset(hfile, 0x00, sizeof(*hfile));
hfile->dev = hai_GetDeviceNum(disk);
for (i = 0; i < sizeof(fileconst)/sizeof(fileconst[0]); i++)
{
if (!hai_strcmp(fileconst[i].mode, mode))
{
hfile->mode = fileconst[i].val;
break;
}
}
if (hfile->mode == 0)
{
hai_FatMemFree(hfile);
return S_NULL;
}
hai_DiskOperateLock(hfile->dev);
hfile->pfileinf = _hai_OpenFileOnFat(hfile->dev, file, hfile->mode);
hai_DiskOperateUnlock(hfile->dev);
if (hfile->pfileinf == S_NULL)
{
hai_FatMemFree(hfile);
hfile = S_NULL;
}
return hfile;
}
int _hai_fcloseOnFat(S_BYTE disk, SH_FATFILEOP hFileOp)
{
int err = FATERR_INVALID_DISK;
S_BYTE *pSecBuf, SecBuf[FAT_SEC_BUF_MAX];
SP_FATFILEINF pFileInf;
if (hFileOp->dev != hai_GetDeviceNum(disk) || hFileOp->pfileinf == S_NULL)
goto FCLOSE_ERR;
if (!hai_FatDevExist(hFileOp->dev))
goto FCLOSE_ERR;
err = FATERR_NO_ERROR;
pFileInf = hFileOp->pfileinf;
if (--pFileInf->OpenCnt == 0)
{
hai_DiskOperateLock(hFileOp->dev);
if (err = _hai_FatDevRead(hFileOp->dev, pFileInf->DentSec, SecBuf))
goto FCLOSE_ERR;
pSecBuf = SecBuf + pFileInf->DentNum*FAT_DIRENT_SIZE;
if (hai_memcmp(pSecBuf, pFileInf->DirName, sDIR_Name))
{
err = FATERR_FILE_NOFIND;
goto FCLOSE_ERR;
}
hai_UpdateDent(pSecBuf, (S_BYTE)((hFileOp->mode&_H_O_WRONLY)==_H_O_WRONLY));
HAI_WRITEWORD(pDIR_FstClusHI(pSecBuf), pFileInf->FirstClust>>16);
HAI_WRITEWORD(pDIR_FstClusLO(pSecBuf), pFileInf->FirstClust);
HAI_WRITEDWORD(pDIR_FileSize(pSecBuf), pFileInf->FileSize);
if (err = _hai_FatDevWrite(hFileOp->dev, pFileInf->DentSec, SecBuf))
goto FCLOSE_ERR;
if (pFileInf->pSecbuf)
{
if (err = _hai_FlushFileBuf(pFileInf->dev, pFileInf->pSecbuf))
goto FCLOSE_ERR;
hai_FatMemFree(pFileInf->pSecbuf);
}
hai_DiskOperateUnlock(hFileOp->dev);
hai_FatMemFree(pFileInf);
}
hai_FatMemFree(hFileOp);
FCLOSE_ERR:
hFileOp->err = err;
return err;
}
S_DWORD _hai_FindFileLastClust(SP_FATFILEINF pFileInf)
{
int dev = pFileInf->dev;
S_BYTE SecBuf[FAT_SEC_BUF_MAX];
S_DWORD Sec, BakSec = 0x00;
S_DWORD Offset, CurClust, NxtClust;
if (pFileInf->FirstClust == 0)//still not alloc clust
return 0;
CurClust = pFileInf->FirstClust;
while (DevInf_FatType(dev)==FAT_TYPE_16?IS_FAT16_INUSE_CLUST(CurClust):IS_FAT32_INUSE_CLUST(CurClust))
{
if (DevInf_FatType(dev) == FAT_TYPE_32)
{
Sec = (CurClust<<2)/DevInf_BytsPerSec(dev) + DevInf_RsvdSec(dev);
if (Sec != BakSec)
{
BakSec = Sec;
if (_hai_FatDevRead(dev, Sec, SecBuf))
return 0xFFFFFFFF;
}
Offset = (CurClust<<2)%DevInf_BytsPerSec(dev);
NxtClust = HAI_MAKEDWORD(SecBuf+Offset)&FAT32_CLUST_VALIDBIT_MASK;
if (IS_FAT32_INUSE_CLUST(NxtClust))
CurClust = NxtClust;
else
break;
}
else
{
Sec = (CurClust<<1)/DevInf_BytsPerSec(dev) + DevInf_RsvdSec(dev);
if (Sec != BakSec)
{
BakSec = Sec;
if (_hai_FatDevRead(dev, Sec, SecBuf))
return 0xFFFFFFFF;
}
Offset = (CurClust<<1)%DevInf_BytsPerSec(dev);
NxtClust = HAI_MAKEWORD(SecBuf+Offset);
if (IS_FAT16_INUSE_CLUST(NxtClust))
CurClust = NxtClust;
else
break;
}
}
return CurClust;
}
int _hai_AllocDiskSpace4File(SP_FATFILEINF pFileInf, S_DWORD total)
{
int dev = pFileInf->dev;
int ClustCnt, NeedClust;
S_DWORD CurClust, num = DevInf_BytsPerSec(dev)*DevInf_SecPerClust(dev);
ClustCnt = (pFileInf->FileSize + (num-1))/num;
NeedClust = (total + (num-1))/num;
if (NeedClust <= ClustCnt)
return 0;
if (pFileInf->LastClust == 0)
pFileInf->LastClust = _hai_FindFileLastClust(pFileInf);
if (pFileInf->LastClust == 0xFFFFFFFF)
{
pFileInf->LastClust = 0x00;
return FATERR_DEV_OPERATE_ERR;
}
CurClust = pFileInf->LastClust;
while (ClustCnt++ < NeedClust)
{
num = hai_AllocIdleClust(dev);
if (num == 0)
return FATERR_NO_DISK_SPACE;
if (pFileInf->FirstClust == 0x00)
{
pFileInf->FirstClust = num;
CurClust = num;
}
else
{
if (hai_LinkClust(dev, CurClust, num))
return FATERR_DEV_OPERATE_ERR;
CurClust = num;
}
}
pFileInf->LastClust = num;
return 0;
}
S_DWORD hai_FindSpecifyClust(int dev, S_DWORD StartClust, S_DWORD NoClust)
{
S_BYTE SecBuf[FAT_SEC_BUF_MAX];
S_DWORD Sec, BakSec = 0x00;
S_DWORD Offset, NxtClust, ClustCnt = 0;
if (NoClust < 1)
return StartClust;
while ((ClustCnt++<NoClust)&&(DevInf_FatType(dev)==FAT_TYPE_16?IS_FAT16_INUSE_CLUST(StartClust):IS_FAT32_INUSE_CLUST(StartClust)))
{
if (DevInf_FatType(dev) == FAT_TYPE_32)
{
Sec = (StartClust<<2)/DevInf_BytsPerSec(dev) + DevInf_RsvdSec(dev);
if (Sec != BakSec)
{
BakSec = Sec;
if (_hai_FatDevRead(dev, Sec, SecBuf))
return 0xFFFFFFFF;
}
Offset = (StartClust<<2)%DevInf_BytsPerSec(dev);
NxtClust = HAI_MAKEDWORD(SecBuf+Offset)&FAT32_CLUST_VALIDBIT_MASK;
if (IS_FAT32_INUSE_CLUST(NxtClust))
StartClust = NxtClust;
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -