📄 fat.cpp
字号:
#include "stdafx.h"
#include "fs.h"
/*----------------------------------------------------------------------*/
typedef enum{
eFILE_MODE_NULL = 0,
eFILE_MODE_R,
eFILE_MODE_R_ADD,
eFILE_MODE_W,
eFILE_MODE_W_ADD,
eFILE_MODE_A,
eFILE_MODE_A_ADD,
eFILE_MODE_END
}FILE_MODE_E;
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
/*----------------------------------------------------------------------*/
#define FILENAME_MIN_LEN 4
#define FILENAME_MAX_LEN 11
#define PATH_MAX_LEN 15
#define DEV_BLOCK_SIZE (16*1024) //块大小
#define DEV_BLOCK_TOTAL 4096 //总块数
#define DEV_FIRST_BLOCK 10 //起始块
#define FS_FCB_NUM 16
#define FS_FAT_NUM (DEV_BLOCK_SIZE/2)
#define FS_FAT_FLAG 0XFFF8
#define FS_FAT_END 0XFFFF
#define FS_FAT_BAD 0XFFF7
#define FS_FAT_NULL 0
#define FILE_MODE_TOTAL 6
#define INVALID_FCB 0XFFFF
#define FIRST_FILE_FAT 6
#define BLOCK_INFO_LEN 8
/*----------------------------------------------------------------------*/
LOCAL void FS_InitFCB(char DevName);
LOCAL void FS_InitDev(char DevName);
LOCAL void ParseFileNameTo83(const char *Name, char *Buf);
LOCAL int IsOpened(char *Name);
LOCAL BYTE* GetRootEntryAddr(char *Name);
LOCAL int IsInRoot(char *Name);
LOCAL int GetFileMode(char *Mode);
LOCAL FCB_T* AlocalFCB(void);
LOCAL void FreeFCB(int i);
LOCAL int Open_ReadOnly(BYTE *pD);
LOCAL int Open_WriteOnly(BYTE *pDir);
LOCAL BYTE *GetRootNullDir(char *Name);
LOCAL void SetNextFat(uint16 No,uint16 value);
LOCAL uint16 GetNextFat(uint16 No);
LOCAL GetNULLFatNo(void);
LOCAL bool FS_ReadBlock(uint16 Fat,BYTE *Buf,BYTE *Info);
LOCAL void FS_FileFlush(FCB_T* pFCB);
LOCAL void FS_RootFlush(void);
LOCAL void FS_RootRead(void);
LOCAL FCB_T* GetFileFCB(int hFile);
LOCAL int FS_Del(char *Name);
LOCAL int FS_Seek(int hFile,int offset,int set);
LOCAL uint32 FS_Ftell(int hFile);
LOCAL int FS_Format(char DevName);
LOCAL int FS_IsFormat(void);
LOCAL int FS_feof( int hFile);
/*----------------------------------------------------------------------*/
LOCAL DEVICE_T gFS_Device; //硬盘描述
LOCAL FAT_ROOT_T gFS_FATParam; //FAT_ROOT描述
LOCAL uint16 gFS_FATBuf[FS_FAT_NUM];//FAT_ROOT块
LOCAL FCB_T gFS_FCB[FS_FCB_NUM];
LOCAL BYTE gFS_BlockBuf[FS_FCB_NUM][DEV_BLOCK_SIZE];
LOCAL char kFileMode[FILE_MODE_TOTAL][3]={"R","R+","W","W+","A","A+"};
/*----------------------------------------------------------------------*/
/**/
bool NF_ReadBlock(uint32 addr,BYTE *buf,BYTE*info);
bool NF_WriteBlock(uint32 addr,BYTE *buf,BYTE*info);
LOCAL int gFS_FileNo = 0;
PUBLIC int GetFileNo(void)
{
gFS_FileNo++;
return(gFS_FileNo);
}
/*----------------------------------------------------------------------*/
/* FS_Init */
/*----------------------------------------------------------------------*/
/**
* LOCAL int (*mFInit)(char DevName)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL int FS_Init(char DevName)
{
char c = toupper(DevName);
FS_InitDev(c);
FS_InitFCB(c);
return(0);
}
/**
* LOCAL int (*mFInit)(char DevName)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL void FS_InitDev(char DevName)
{
//硬盘描述
gFS_Device.mDeviceName = DevName; //盘名:cdefg..z
gFS_Device.mFirstBockNo = DEV_FIRST_BLOCK; //盘上第一块,可以用做FAT_ROOT
gFS_Device.mBlockSize = DEV_BLOCK_SIZE; //盘上块大小
gFS_Device.mBlockTotal = DEV_BLOCK_TOTAL; //盘上总块数
//FAT_ROOT描述
gFS_FATParam.mDevName = DevName;
gFS_FATParam.mFatNum = gFS_Device.mBlockTotal-gFS_Device.mFirstBockNo;//有用的FAT块数
gFS_FATParam.mFatBuf = gFS_FATBuf;//FAT块起始地址
gFS_FATParam.mRootEntryNum = (gFS_Device.mBlockSize-gFS_FATParam.mFatNum*2)/FS_ROOT_ENTRY_SIZE;//根目录条数
gFS_FATParam.mRootBuf = (BYTE*)gFS_FATBuf;//根目录起始地址
gFS_FATParam.mRootBuf+= gFS_FATParam.mFatNum*2;
gFS_FATParam.mUpdate = 0;
//FAT_ROOT块
FS_RootRead();
}
/**
* LOCAL void FS_InitFCB(char DevName)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL void FS_InitFCB(char DevName)
{
int i;
for(i=0; i<FS_FCB_NUM; i++){
//FCB
gFS_FCB[i].mDevName = DevName; //盘名:cdefg..z
gFS_FCB[i].mFileName[0]=0; //文件名
gFS_FCB[i].mFileLen=0; //文件长度
gFS_FCB[i].mSequenceNum=0; //块顺序号
gFS_FCB[i].mOffset=0; //偏移量
gFS_FCB[i].mStartFatNo=0; //文件起始块FAT号
gFS_FCB[i].mCurFatNo=0; //文件当前块FAT号
gFS_FCB[i].mBlockSize=0; //块大小
gFS_FCB[i].mBlockBuf = (BYTE*)&gFS_BlockBuf[i]; //块缓冲
gFS_FCB[i].mState = 0; //使用状态
gFS_FCB[i].mUpdate = 0; //更改标志
gFS_FCB[i].mMode = eFILE_MODE_NULL; //打开模式
gFS_FCB[i].mHandle = GetFileNo(); //文件句柄
}
}
/**
* LOCAL int GetNULLFatNo(void)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL int GetNULLFatNo(void)
{
int i;
uint16 FatNo = 0;
for(i=FIRST_FILE_FAT; i<gFS_FATParam.mFatNum; i++){
if(0 == gFS_FATBuf[i]){
FatNo = i;
break;
}
}
return( FatNo );
}
/**
* LOCAL void SetNextFat(uint16 No,uint16 value)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL void SetNextFat(uint16 No,uint16 value)
{
if( (gFS_FATParam.mFatNum > No) &&
(No >= FIRST_FILE_FAT) ){
gFS_FATBuf[No] = value;
gFS_FATParam.mUpdate = 1;
}
}
/**
* LOCAL uint16 GetNextFat(uint16 No)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL uint16 GetNextFat(uint16 No)
{
uint16 FAT = 0;
if(No < FS_FAT_NUM){
FAT = gFS_FATBuf[No];
}
else{
FAT = 0xffff;
}
return( FAT );
}
/**
* LOCAL uint16 GetPrevFat(FCB_T *pFcb)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL uint16 GetPrevFat(FCB_T *pFcb)
{
uint16 Fat = 0;
uint16 Next;
if( pFcb->mSequenceNum ){
Fat = pFcb->mStartFatNo;
while(1){
Next = GetNextFat(Fat);
if(Next == pFcb->mCurFatNo){
break;
}
Fat = Next;
}
}
return( Fat );
}
/*----------------------------------------------------------------------*/
/* FS_Format */
/*----------------------------------------------------------------------*/
/**
* LOCAL int FS_Format(char DevName)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL int FS_Format(char DevName)
{
int ReturnCode = 0;
int i;
DevName = toupper( DevName );
if(DevName == gFS_Device.mDeviceName){
memset(gFS_FATBuf,0,sizeof(gFS_FATBuf));
gFS_FATBuf[0] = FS_FAT_FLAG;
for(i=1; i<FIRST_FILE_FAT; i++){
gFS_FATBuf[i] = FS_FAT_END;
}
//标记坏块
gFS_FATParam.mUpdate = 1;
FS_RootFlush();
ReturnCode = 1;
}
return( ReturnCode );
}
/**
* LOCAL int FS_IsIn(int hFile)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL int FS_IsIn(int hFile)
{
int ReturnCode = 0;
if( (hFile >= gFS_FCB[0].mHandle) &&
(hFile <= gFS_FCB[FS_FCB_NUM-1].mHandle) ){
ReturnCode = 1;
}
return( ReturnCode );
}
/**
* LOCAL int FS_Close(int hFile)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL int FS_Close(int hFile)
{
int ReturnCode = 0;
DIR_ENTRY_T *pRootEntry;
FCB_T *pFCB;
//不在
if(!FS_IsIn(hFile)){
return( ReturnCode );
}
//文件已关
pFCB = GetFileFCB(hFile);
if(!pFCB->mState){
return( ReturnCode );
}
pFCB->mState = 0;
if(0 != pFCB->mUpdate){
//写文件
FS_FileFlush(pFCB);
//写目录
pRootEntry = (DIR_ENTRY_T*)GetRootEntryAddr(pFCB->mFileName);
if(pRootEntry->size != pFCB->mFileLen){
pRootEntry->size = pFCB->mFileLen;
gFS_FATParam.mUpdate = 1;
}
//有坏块
if(pRootEntry->start != pFCB->mStartFatNo){
pRootEntry->start = pFCB->mStartFatNo;
gFS_FATParam.mUpdate = 1;
}
FS_RootFlush();
}
ReturnCode = 1;
return( ReturnCode );
}
/*----------------------------------------------------------------------*/
/* fopen */
/*----------------------------------------------------------------------*/
/**
* LOCAL int FS_Open(char *Name, char*mode)
*
* "r"
* Opens for reading. If the file does not exist or cannot be found, the fopen call fails.
* "w"
* Opens an empty file for writing. If the given file exists, its contents are destroyed.
* "a"
* Opens for writing at the end of the file (appending) without removing the EOF marker before writing new data to the file;
* creates the file first if it doesn't exist.
* "r+"
* Opens for both reading and writing. (The file must exist.)
* "w+"
* Opens an empty file for both reading and writing. If the given file exists, its contents are destroyed.
* "a+"
* Opens for reading and appending; the appending operation includes the removal of the EOF marker before new data is written to
* the file and the EOF marker is restored after writing is complete; creates the file first if it doesn't exist.
*
*/
LOCAL int FS_Open(char *Name, char*mode)
{
int hFile = 0;
char c = toupper(Name[0]);
char File83Name[FILENAME_MAX_LEN];
int FileMode;
BYTE *pDir;
FCB_T *pFCB;
//解析文件名
ParseFileNameTo83(Name,File83Name);
//盘名
if(c != gFS_Device.mDeviceName){
return( hFile );
}
//没文件名 c:
if(0 == File83Name[0]){
return( hFile );
}
//已打开
if(IsOpened(File83Name)){
return( hFile );
}
//打开模式
FileMode = GetFileMode(mode);
pDir = GetRootEntryAddr(File83Name);
//文件存在根目录
if( NULL != pDir ){
switch( FileMode ){
case eFILE_MODE_NULL:
break;
case eFILE_MODE_R:
hFile = Open_ReadOnly( pDir );
break;
case eFILE_MODE_R_ADD:
hFile = Open_ReadOnly( pDir );
if( hFile ){
pFCB = GetFileFCB( hFile );
pFCB->mMode = eFILE_MODE_R_ADD;
}
break;
case eFILE_MODE_W:
FS_Del(Name);
pDir = GetRootNullDir(File83Name);
if(NULL != pDir){
hFile = Open_WriteOnly( pDir );
}
break;
case eFILE_MODE_W_ADD:
FS_Del(Name);
pDir = GetRootNullDir(File83Name);
if(NULL != pDir){
hFile = Open_WriteOnly( pDir );
if( hFile ){
pFCB = GetFileFCB( hFile );
pFCB->mMode = eFILE_MODE_W_ADD;
}
}
break;
case eFILE_MODE_A:
hFile = Open_ReadOnly( pDir );
if( hFile ){
FS_Seek(hFile,0,SEEK_END);
pFCB = GetFileFCB( hFile );
pFCB->mMode = eFILE_MODE_A;
}
break;
case eFILE_MODE_A_ADD:
hFile = Open_ReadOnly( pDir );
if( hFile ){
FS_Seek(hFile,0,SEEK_END);
pFCB = GetFileFCB( hFile );
pFCB->mMode = eFILE_MODE_A_ADD;
}
break;
};
}
else{
pDir = GetRootNullDir(File83Name);
if(pDir != NULL){
switch( FileMode ){
case eFILE_MODE_NULL:
break;
case eFILE_MODE_R:
break;
case eFILE_MODE_R_ADD:
break;
case eFILE_MODE_W:
hFile = Open_WriteOnly( pDir );
break;
case eFILE_MODE_W_ADD:
hFile = Open_WriteOnly( pDir );
if( hFile ){
pFCB = GetFileFCB( hFile );
pFCB->mMode = eFILE_MODE_W_ADD;
}
break;
case eFILE_MODE_A:
hFile = Open_WriteOnly( pDir );
if( hFile ){
pFCB = GetFileFCB( hFile );
pFCB->mMode = eFILE_MODE_A;
}
break;
case eFILE_MODE_A_ADD:
hFile = Open_WriteOnly( pDir );
if( hFile ){
pFCB = GetFileFCB( hFile );
pFCB->mMode = eFILE_MODE_A_ADD;
}
break;
};
}
}
return( hFile );
}
/**
* LOCAL void ParseFileNameTo83(const char *Name, char *Buf)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL void ParseFileNameTo83(const char *Name, char *Buf)
{
int Len;
int i;
int Index;
int j;
Buf[0] = 0;
if(NULL != Name){
Len = strlen(Name);
if(Len >= FILENAME_MIN_LEN && Len <= PATH_MAX_LEN){
if( ((Name[0]>='A' && Name[0]<='Z')|(Name[0]>='a' && Name[0]<='z') ) &&
(Name[1]==':')&&
(Name[2]=='\\') )
{
memset(Buf,0x20,11);
//找.
for(Index=Len-1; Index>=3; Index--){
if(Name[Index] == '.'){
break;
}
}
// .abc
if(Index == 3){
return;
}// abc.abc
else if(Index > 3){
for(i=3,j=0; j<8; j++){
Buf[j] = Name[i];
i++;
if(i >= Index){
break;
}
}
for(i=Index+1,j=8; j<11; j++){
if(i >= Len){
break;
}
Buf[j] = Name[i];
i++;
}
}// abc
else{
for(i=3,j=0;j<8;j++){
if(i >= Len){
break;
}
Buf[j] = Name[i];
i++;
}
}
}
}
}
}
/**
* LOCAL int IsOpened(char *Name)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL int IsOpened(char *Name)
{
int ReturnCode = 0;
int Result;
int i;
for(i=0; i<FS_FCB_NUM; i++){
if(0 == gFS_FCB[i].mState){
continue;
}
Result = strncmp(Name,gFS_FCB[i].mFileName,FILENAME_MAX_LEN);
if(Result == 0){
ReturnCode = 1;
break;
}
}
return( ReturnCode );
}
/**
* LOCAL BYTE* GetRootEntryAddr(char *Name)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL BYTE* GetRootEntryAddr(char *Name)
{
BYTE *p = NULL;
int Result;
int i;
BYTE *s;
s = gFS_FATParam.mRootBuf;
for(i=0; i<gFS_FATParam.mRootEntryNum; i++){
Result = memcmp(s,Name,FILENAME_MAX_LEN);
if(Result == 0){
p = s;
break;
}
s += FILENAME_MAX_LEN;
}
return( p );
}
/**
* LOCAL BYTE *GetRootNullDir(char *Name)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL BYTE *GetRootNullDir(char *Name)
{
BYTE *p = NULL;
int i;
BYTE *s;
s = gFS_FATParam.mRootBuf;
for(i=0; i<gFS_FATParam.mRootEntryNum; i++){
if(*s == 0){
p = s;
memcpy(s,Name,11);
break;
}
s += FILENAME_MAX_LEN;
}
return( p );
}
/**
* LOCAL int GetFileMode(char *Mode)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL int GetFileMode(char *Mode)
{
int n = eFILE_MODE_NULL;
int i;
int Result;
char Buf[4];
Buf[0] = toupper(Mode[0]);
Buf[1] = toupper(Mode[1]);
Buf[2] = 0;
for(i=0; i<FILE_MODE_TOTAL; i++){
Result = strcmp(Buf,kFileMode[i]);
if(0 == Result){
n = i+1;
}
}
return( n );
}
/**
* LOCAL FCB_T* GetFileFCB(int hFile)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL FCB_T* GetFileFCB(int hFile)
{
FCB_T *pPCB;
int Index;
Index = hFile-gFS_FCB[0].mHandle;
pPCB = &gFS_FCB[Index];
return( pPCB );
}
/**
* LOCAL FCB_T* AlocalFCB(void)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL FCB_T* AlocalFCB(void)
{
int i;
FCB_T *pPCB = NULL;
for(i=0; i<FS_FCB_NUM; i++){
if(0 == gFS_FCB[i].mState){
pPCB = &gFS_FCB[i];
break;
}
}
return ( pPCB );
}
/**
* LOCAL FCB_T* AlocalFCB(void)
*
* update 2008/12/1
*
* ycdbox@126.com 1
*/
LOCAL void FreeFCB(FCB_T *p)
{
if(NULL != p){
p->mState = 0;
}
}
/**
* LOCAL int Open_ReadOnly(BYTE *pDir)
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -