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

📄 fsmvfs.c

📁 norflash的文件系统。 用于中低端手机开发的参考
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
 
  FILE NAME: FsmVfs.c

  DESCRIPTION:

    virtual file system, provide all fs APIs..

 Copyright (c) 2002, VIA Technologies, Inc.
*****************************************************************************/


#include "fsmdefs.h"
#include "string.h"
#include "ostype.h"
#include "FsmApi.h"
#include "FsmDfs.h"
#include "FsmVfs.h"


#define MAX_VOLUME_NUM		3

#define MAX_VFS_FD			16


/* local variables */
static FsmVolumeT		FsmVolumes[MAX_VOLUME_NUM];

static HMSEM	FsmVolumeMtxSem;

static FsmVfsFileDescriptorT	FsmVfsFds[MAX_VFS_FD];
 
static HMSEM	FsmVfsMtxSem;


static uint32		FsmGetMatchedVolume(char ** path);
static uint32		FsmAllocVfd(void);
static uint32		FsmFreeVfd(uint32 vfd);

/* global variables. */
extern FsmDevObjHdrT * FsmDataItemDevObjP;

extern uint32		FsmDataItemExit(void);



/*#############################################################################
  ### FsmVfsStartup
  ###
  ### DESCRIPTION:
  ###   initialize all variable used internally.
  ###
  ### PARAMETERS:
  ###    IN:  
  ###         
  ###    OUT: 
  ###
  ### RETURNS:
  ###    Returns the following errors codes:
  ###         ERR_NONE
  ###         ERR_SYSTEM
  ###
 */

uint32 FsmVfsStartup()
{
	uint32		i;

	/* initialize the Volume structure */
	for (i = 0; i < MAX_VOLUME_NUM; i++)
	{
		FsmVolumes[i].DevObjP = NULL;
		FsmVolumes[i].FsDrvP  = NULL;
		FsmVolumes[i].RefCnt  = 0;
		FsmVolumes[i].VolName[0] = 0;
	}

	/* initialize the VFD structure */
	for (i = 0; i < MAX_VFS_FD; i++)
	{
	    FsmVfsFds[i].ErrorCode = 0;
        FsmVfsFds[i].LowerFd = -1;
        FsmVfsFds[i].VolumeP = NULL;
        FsmVfsFds[i].Flag = VFD_FLAG_FREE;
		FsmVfsFds[i].MutexSem = 0;
	}

	FsmVolumeMtxSem = FsmCreateMtxSem(1);

	if(FsmVolumeMtxSem == NULL)
	{
		return ERR_SYSTEM;
	}

	FsmVfsMtxSem = FsmCreateMtxSem(1);

	if(FsmVfsMtxSem == NULL)
	{
		FsmDeleteMtxSem(FsmVolumeMtxSem);

		return ERR_SYSTEM;
	}

	for (i = 0; i < MAX_VFS_FD; i++)
	{
		FsmVfsFds[i].MutexSem = FsmCreateMtxSem(1);

		if(FsmVfsFds[i].MutexSem == NULL)
			break;
	}

	if(i < MAX_VFS_FD)
	{
		while(i > 0)
		{
			FsmDeleteMtxSem(FsmVfsFds[i - 1].MutexSem);
			FsmVfsFds[i - 1].MutexSem = NULL;
			i--;
		}

		FsmDeleteMtxSem(FsmVfsMtxSem);

		FsmDeleteMtxSem(FsmVolumeMtxSem);

		return ERR_SYSTEM;
	}

	return ERR_NONE;
}

/*#############################################################################
  ### FsmVfsExit
  ###
  ### DESCRIPTION:
  ###   release resources allocated when vfs startup.
  ###
  ### PARAMETERS:
  ###    IN:  
  ###         
  ###    OUT: 
  ###
  ### RETURNS:
  ###    Returns the following errors codes:
  ###         ERR_NONE
  ###
 */

uint32 FsmVfsExit()
{
	uint32	i;

	i = MAX_VFS_FD;

	while(i > 0)
	{
		FsmDeleteMtxSem(FsmVfsFds[i - 1].MutexSem);
		FsmVfsFds[i - 1].MutexSem = NULL;
		i--;
	}

	FsmDeleteMtxSem(FsmVfsMtxSem);

	FsmDeleteMtxSem(FsmVolumeMtxSem);

	return ERR_NONE;
}

/***********************************************************************
 * Function Name: FsmOpen
 * Description  : Open a file, return the file descriptor
 * Arguments    : path      : file path
 *              : mode      : open mode
 * First Edit 2003.8.13 wsm
 * note: a path end with slash is illegal! 
 */
 
uint32 FsmOpen(const char * filename, uint32 mode)
{
	uint32		status;
	uint32      VolIndex;
	FsmFsDrvT *	FsP;
	uint32		vfd;
	uint32		lfd;
	char *		path;

#ifdef FSM_DEBUG
	MonPrintf("Interface FsmOpen in %s,%d :Open file|dir %s \n", __FILE__, __LINE__, filename);
#endif

	if(strlen(filename) > MAX_PATH_LENGTH)
	{
		return INVALID_FILE_HANDLE;
	}

	status = mode & FSM_OPEN_MODE_MASK;

	if((status != FSM_OPEN_ALWAYS)
		&& (status != FSM_OPEN_EXISTING)
		&& (status != FSM_CREATE_NEW)
		&& (status != FSM_CREATE_ALWAYS))
	{
		return INVALID_FILE_HANDLE;
	}

	path = (char *)filename;

    if ((status = FsmGetMtxSem(FsmVolumeMtxSem)) != ERR_NONE )
	{
		return INVALID_FILE_HANDLE;
	}

	VolIndex = FsmGetMatchedVolume(&path);

	if (VolIndex == MAX_VOLUME_NUM)
	{
		FsmReleaseMtxSem(FsmVolumeMtxSem);

		return INVALID_FILE_HANDLE;
	}

	FsmVolumes[VolIndex].RefCnt++; /* prevent volume from being unmounted. */

	FsP = FsmVolumes[VolIndex].FsDrvP; /* it can be moved out of the lock protecting. */

	FsmReleaseMtxSem(FsmVolumeMtxSem);

	/*
	if (FsP == NULL)
	{
		goto Open_Exit;
	}
	*/

	vfd = FsmAllocVfd();

	if (vfd == INVALID_FILE_HANDLE)
	{
		goto Open_Exit;
	}

	status = FsmGetMtxSem(FsmVfsFds[vfd].MutexSem);

	if(status != ERR_NONE)
	{
		FsmFreeVfd(vfd);

		goto Open_Exit;
	}

	FsmVfsFds[vfd].LowerFd = (uint32)(-1);
	FsmVfsFds[vfd].VolumeP    = &FsmVolumes[VolIndex];
	FsmVfsFds[vfd].ErrorCode  = ERR_NONE;

	lfd = FsP->FsmOpen( FsmVolumes[VolIndex].DevObjP,
						path, 
						(mode & FSM_ACCESS_MODE_MASK) | FSM_OPEN_EXISTING | FSM_OPEN_FILE,
						&status
						);

	if (lfd != INVALID_FILE_HANDLE)
	{
		switch(mode & FSM_OPEN_MODE_MASK)
		{
		case FSM_OPEN_ALWAYS:
			/* pass through. */
		case FSM_OPEN_EXISTING:
			FsmVfsFds[vfd].LowerFd = lfd;
			FsmReleaseMtxSem(FsmVfsFds[vfd].MutexSem);
			return vfd;

			break;

		case FSM_CREATE_NEW:
			FsP->FsmClose(lfd);
			FsmReleaseMtxSem(FsmVfsFds[vfd].MutexSem);
			FsmFreeVfd(vfd);
			goto Open_Exit;

			break;

		case FSM_CREATE_ALWAYS:
			FsmVfsFds[vfd].LowerFd = lfd;
			FsmTruncate(vfd, 0);
			FsmReleaseMtxSem(FsmVfsFds[vfd].MutexSem);
			return vfd;
			break;

		default:
			FsP->FsmClose(lfd);
			FsmReleaseMtxSem(FsmVfsFds[vfd].MutexSem);
			FsmFreeVfd(vfd);
			MonPrintf("\nOops, a bug is here! Invalid open mode in FsmOpen()");
			goto Open_Exit;
			break;
		}
	}
	else
	{
		switch(mode & FSM_OPEN_MODE_MASK)
		{
		case FSM_OPEN_EXISTING:
			FsmReleaseMtxSem(FsmVfsFds[vfd].MutexSem);
			FsmFreeVfd(vfd);
			goto Open_Exit;
			break;

		case FSM_OPEN_ALWAYS:
		case FSM_CREATE_NEW:
		case FSM_CREATE_ALWAYS:
			if(status == ERR_NOTEXIST)
			{
				lfd = FsP->FsmCreate( FsmVolumes[VolIndex].DevObjP,
									  path,
									  mode | FSM_OPEN_FILE,
									  &status
									  );

				if(lfd != INVALID_FILE_HANDLE)
				{
					FsmVfsFds[vfd].LowerFd = lfd;
					FsmReleaseMtxSem(FsmVfsFds[vfd].MutexSem);
					return vfd;
				}
			}

			FsmReleaseMtxSem(FsmVfsFds[vfd].MutexSem);
			FsmFreeVfd(vfd);
			goto Open_Exit;

			break;

		default:
			FsmReleaseMtxSem(FsmVfsFds[vfd].MutexSem);
			FsmFreeVfd(vfd);
			MonPrintf("\nOops, a bug is here! Invalid open mode in FsmOpen()");
			goto Open_Exit;
			break;
		}
	}

Open_Exit:

	FsmGetMtxSem(FsmVolumeMtxSem);

	FsmVolumes[VolIndex].RefCnt--;

	FsmReleaseMtxSem(FsmVolumeMtxSem);

	return INVALID_FILE_HANDLE;
}

/*
* Function Name: FsmClose
* Description  : Close a file, return the error code
* Arguments    : path      : file path
*              : mode      : open mode
* First Edit 2003.8.13 wsm
*/
uint32 FsmClose(uint32 fd)
{
	uint32		status;

#ifdef FSM_DEBUG
	MonPrintf("Interface FsmClose in %s,%d \n", __FILE__, __LINE__);
#endif

	if(fd >= MAX_VFS_FD)
	{
		return ERR_PARAM;
	}

	if ((status = FsmGetMtxSem(FsmVfsFds[fd].MutexSem)) != ERR_NONE)
	{
		return status;
	}

	if((FsmVfsFds[fd].Flag == VFD_FLAG_FREE)
		|| (FsmVfsFds[fd].LowerFd == (uint32)(-1))
		|| (FsmVfsFds[fd].VolumeP == NULL))
	{
		FsmReleaseMtxSem(FsmVfsFds[fd].MutexSem);
		return ERR_PARAM;
	}

	status = FsmVfsFds[fd].VolumeP->FsDrvP->FsmClose(FsmVfsFds[fd].LowerFd);

	if(status == ERR_NONE)
	{
		FsmVfsFds[fd].LowerFd = (uint32)(-1);
	}

	FsmReleaseMtxSem(FsmVfsFds[fd].MutexSem);

	if(status == ERR_NONE)
	{
		FsmVolumeT *	VolumeP;

		VolumeP = FsmVfsFds[fd].VolumeP;

		FsmFreeVfd(fd);

		FsmGetMtxSem(FsmVolumeMtxSem);

		VolumeP->RefCnt--;

		FsmReleaseMtxSem(FsmVolumeMtxSem);
	}

	return status;
}

/*
* Function Name: FsmCloseAll
* Description  : Close all files, return the error code
* Arguments    :
* First Edit 2003.8.13 wsm
*/
uint32 FsmCloseAll()
{
/*	uint32		status; */
	uint32		fd;

#ifdef FSM_DEBUG
	MonPrintf("Interface FsmClose in %s,%d \n", __FILE__, __LINE__);
#endif
/*
	// prevent FsmOpen from being called.
	if ((status = FsmGetMtxSem(FsmVolumeMtxSem)) != ERR_NONE )
	{
		return status;
	}*/

	for (fd = 0; fd < MAX_VFS_FD; fd++)
	{
		FsmClose(fd);
	}

/*	FsmReleaseMtxSem(FsmVolumeMtxSem); */

	return ERR_NONE;
}

/*
* Function Name: FsmRead
* Description  : Read from file, return the readed size
* Arguments    : fd        : file descriptor
*              : buffer    : content buffer
*              : size      : read size
* First Edit 2003.7.23 wsm
*/

uint32 FsmRead(uint32 fd, void * buffer, uint32 size)
{
	uint32		status;
	FsmFsDrvT *	FsP;

#ifdef FSM_DEBUG
	MonPrintf("Interface FsmRead in %s,%d \n", __FILE__, __LINE__);
#endif

	if (fd >= MAX_VFS_FD)
	{
		return 0;
	}

	if (size == 0)
	{
		FsmVfsFds[fd].ErrorCode = ERR_NONE;
		return 0;
	}

	if (buffer == NULL)
	{
		FsmVfsFds[fd].ErrorCode = ERR_PARAM;
		return 0;
	}

	if ((status = FsmGetMtxSem(FsmVfsFds[fd].MutexSem)) != ERR_NONE)
	{
		FsmVfsFds[fd].ErrorCode = status;
		return 0;
	}

	if((FsmVfsFds[fd].Flag == VFD_FLAG_FREE)
		|| (FsmVfsFds[fd].LowerFd == (uint32)(-1))
		|| (FsmVfsFds[fd].VolumeP == NULL))
	{
		FsmVfsFds[fd].ErrorCode = ERR_PARAM;
		FsmReleaseMtxSem(FsmVfsFds[fd].MutexSem);
		return 0;
	}

	FsP = FsmVfsFds[fd].VolumeP->FsDrvP;

	size = FsP->FsmRead( FsmVfsFds[fd].LowerFd, buffer, size, &status);

	FsmVfsFds[fd].ErrorCode = status;

	FsmReleaseMtxSem(FsmVfsFds[fd].MutexSem);

	return size;
}

/*
* Function Name: FsmWrite
* Description  : Write to a file, return the wrote size
* Arguments    : fd        : file descriptor
*              : buffer    : content buffer
*              : size      : write size
* First Edit 2003.7.23 wsm
*/

uint32 FsmWrite(uint32 fd, void * buffer, uint32 size)
{
	uint32		status;
	FsmFsDrvT *	FsP;

#ifdef FSM_DEBUG
	MonPrintf("Interface FsmWrite in %s,%d \n", __FILE__, __LINE__);
#endif

	if (fd >= MAX_VFS_FD)
	{
		return 0;
	}

	if (size == 0)
	{
		FsmVfsFds[fd].ErrorCode = ERR_NONE;
		return 0;
	}

	if (buffer == NULL)
	{
		FsmVfsFds[fd].ErrorCode = ERR_PARAM;
		return 0;
	}

	if ((status = FsmGetMtxSem(FsmVfsFds[fd].MutexSem)) != ERR_NONE)
	{
		FsmVfsFds[fd].ErrorCode = status;
		return 0;
	}

	if((FsmVfsFds[fd].Flag == VFD_FLAG_FREE)
		|| (FsmVfsFds[fd].LowerFd == (uint32)(-1))
		|| (FsmVfsFds[fd].VolumeP == NULL))
	{
		FsmVfsFds[fd].ErrorCode = ERR_PARAM;
		FsmReleaseMtxSem(FsmVfsFds[fd].MutexSem);
		return 0;
	}

	FsP = FsmVfsFds[fd].VolumeP->FsDrvP;

	size = FsP->FsmWrite(FsmVfsFds[fd].LowerFd, buffer, size, &status);

	FsmVfsFds[fd].ErrorCode = status;

	FsmReleaseMtxSem(FsmVfsFds[fd].MutexSem);

	return size;
}

/*
* Function Name: FsmSeek
* Description  : Shift a file offset, return the error code
* Arguments    : fd        : file descriptor
*              : offset    : the shift size
*              : whence    : base position
* First Edit 2003.7.23 wsm
*/

uint32 FsmSeek(uint32 fd, int32 offset, uint32 whence)
{
	uint32			status;
	FsmFsDrvT *		FsP;
	FsmIoctlSeekT   arg;

#ifdef FSM_DEBUG
	MonPrintf("Interface FsmSeek in %s,%d \n", __FILE__, __LINE__);
#endif

	if (fd >= MAX_VFS_FD)
	{
		return ERR_PARAM;
	}

	if ((status = FsmGetMtxSem(FsmVfsFds[fd].MutexSem)) != ERR_NONE)
	{
		FsmVfsFds[fd].ErrorCode = status;
		return status;
	}

	if((FsmVfsFds[fd].Flag == VFD_FLAG_FREE)
		|| (FsmVfsFds[fd].LowerFd == (uint32)(-1))
		|| (FsmVfsFds[fd].VolumeP == NULL))
	{
		FsmVfsFds[fd].ErrorCode = ERR_PARAM;
		FsmReleaseMtxSem(FsmVfsFds[fd].MutexSem);
		return ERR_PARAM;
	}

	FsP = FsmVfsFds[fd].VolumeP->FsDrvP;

	arg.offset = offset;
	arg.whence = whence;

	status = FsP->FsmIoCtrl(FsmVfsFds[fd].LowerFd, FSM_IOCTL_SEEK, (void *)&arg);

	FsmVfsFds[fd].ErrorCode = status;

	FsmReleaseMtxSem(FsmVfsFds[fd].MutexSem);

	return status;
}

/*
* Function Name: FsmTell
* Description  : get the file offset
* Arguments    : fd        : file descriptor
* First Edit 2003.7.23 wsm
*/

int32 FsmTell(uint32 fd)
{
	uint32			status;
	FsmFsDrvT *		FsP;
	uint32			pos;

#ifdef FSM_DEBUG
	MonPrintf("Interface FsmTell in %s,%d \n", __FILE__, __LINE__);
#endif

	if (fd >= MAX_VFS_FD)
	{
		return -1;
	}

	if ((status = FsmGetMtxSem(FsmVfsFds[fd].MutexSem)) != ERR_NONE)
	{
		FsmVfsFds[fd].ErrorCode = status;
		return -1;
	}

	if((FsmVfsFds[fd].Flag == VFD_FLAG_FREE)
		|| (FsmVfsFds[fd].LowerFd == (uint32)(-1))
		|| (FsmVfsFds[fd].VolumeP == NULL))
	{
		FsmVfsFds[fd].ErrorCode = ERR_PARAM;
		FsmReleaseMtxSem(FsmVfsFds[fd].MutexSem);
		return -1;
	}

	FsP = FsmVfsFds[fd].VolumeP->FsDrvP;

	status = FsP->FsmIoCtrl(FsmVfsFds[fd].LowerFd, FSM_IOCTL_TELL, &pos);

	FsmVfsFds[fd].ErrorCode = status;

	FsmReleaseMtxSem(FsmVfsFds[fd].MutexSem);

	if(status == ERR_NONE)
		return pos;
	else
		return -1;
}

/*
* Function Name: FsmEof
* Description  : if the offset reac the end of file
* Arguments    : fd        : file descriptor
* First Edit 2003.7.23 wsm
*/

uint32 FsmEof(uint32 fd, uint32 * Eof)
{
	uint32			status;
	FsmFsDrvT *		FsP;

#ifdef FSM_DEBUG
	MonPrintf("Interface FsmError in %s,%d \n", __FILE__, __LINE__);
#endif

	*Eof = FALSE;

	if (fd >= MAX_VFS_FD)
	{
		return ERR_PARAM;
	}

	if ((status = FsmGetMtxSem(FsmVfsFds[fd].MutexSem)) != ERR_NONE)
	{
		FsmVfsFds[fd].ErrorCode = status;
		return status;
	}

	if((FsmVfsFds[fd].Flag == VFD_FLAG_FREE)
		|| (FsmVfsFds[fd].LowerFd == (uint32)(-1))
		|| (FsmVfsFds[fd].VolumeP == NULL))
	{
		FsmVfsFds[fd].ErrorCode = ERR_PARAM;
		FsmReleaseMtxSem(FsmVfsFds[fd].MutexSem);
		return ERR_PARAM;
	}

⌨️ 快捷键说明

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