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

📄 fat.cpp

📁 Nand flash FAT16 文件系统源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#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 + -