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

📄 fsmdfs.c

📁 norflash的文件系统。 用于中低端手机开发的参考
💻 C
📖 第 1 页 / 共 5 页
字号:

		FsmDfsFds[fd].FilePointer = 0; /* offset into sector. */
	}
	else
	{
		status = ERR_PARAM;
		goto DfsOpen_Exit2;
	}

/*	FsmDfsFds[fd].AccessMode = mode; */
	FsmDfsFds[fd].FirstLsn = entry.FirstLsn;
	FsmDfsFds[fd].ParentDirFirstLsn = ParentDirFirstLsn;
	FsmDfsFds[fd].CreateDate = entry.Date;
	FsmDfsFds[fd].CreateTime = entry.Time;
	FsmDfsFds[fd].Attrib = entry.Type;

DfsOpen_Exit_Success:

	FsmDfsFds[fd].Flag = DFD_FLAG_IN_USE;	/* prevent from being preempted. */

	FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);

	if(ErrorCodeP != NULL)
		*ErrorCodeP = ERR_NONE;

	return fd;

DfsOpen_Exit2:

	FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
	DfsFreeFd(fd);

DfsOpen_Exit:

	if(ErrorCodeP != NULL)
		*ErrorCodeP = status;

	return INVALID_FILE_HANDLE;
}

/*
* Function Name: DfsRead
* Description  : Read from a file or directory , implement the read interface
* Arguments    : fd        : file descriptor
*              : buffer    : content buffer
*              : size      : read size
* First Edit 2003.8.13 wsm
*/
uint32 FsmDfsRead(uint32 fd, uint8 * buf, uint32 size, uint32 *ErrorCode)
{
	uint32				status;

	FsmDevObjHdrT *		DevP;
	FsmFlashMediaT *	MediaP;


#ifdef FSM_DEBUG
	MonPrintf("Interface DfsRead\n");
#endif

	if (fd >= MAX_DFS_FD)
	{
		status = ERR_PARAM;
		goto DfsRead_Exit;
	}

	if(FsmDfsFds[fd].Flag != DFD_FLAG_IN_USE)
	{
		status = ERR_PARAM;
		goto DfsRead_Exit;
	}

	if(size == 0)
	{
		if(ErrorCode != NULL)
		{
			*ErrorCode = ERR_NONE;
		}

		return 0;
	}

	if(buf == NULL)
	{
		status = ERR_PARAM;
		goto DfsRead_Exit;
	}

	/* Get the semaphore of this file. */
	status = FsmGetMtxSem(FsmDfsFds[fd].MutexSem);

	if(status != ERR_NONE)
	{
		goto DfsRead_Exit;
	}

	/* CHECK  if the fd is in PENDING or FREE state. */
	if(FsmDfsFds[fd].Flag != DFD_FLAG_IN_USE)
	{
		/* Release the semaphore of this file. */
		FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
		status = ERR_PARAM;
		goto DfsRead_Exit;
	}


	DevP    = FsmDfsFds[fd].FdHdr.DevObjP;
	MediaP  = (FsmFlashMediaT *)DevP->MediaObjP;


	/* if read directory entry. */
	if (FsmDfsFds[fd].Attrib == ENTRY_TYPE_SUBDIR)
	{
		uint32				SectorLsn;
		uint32				sector_offset;
		FsmFileDirEntryT	entry;

		/*
		 * For directory fd, FileLength field stores  
		 * Sector LSN for next directory entry read.
		 */
		SectorLsn     = FsmDfsFds[fd].FileLength; 
		sector_offset = FsmDfsFds[fd].FilePointer;

		/*
		if ((status = FsmGetMtxSem(MediaP->MapTblLock)) != ERR_NONE)
		{
			// Release the semaphore of this file. 
			FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
			goto DfsRead_Exit;
		}
		*/

		status = DfsReadFileEntry(DevP, &SectorLsn, &sector_offset, &entry);

		/*
		FsmReleaseMtxSem(MediaP->MapTblLock);
		*/

		if(status != ERR_NONE)
		{
			/* Release the semaphore of this file. */
			FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
			goto DfsRead_Exit;
		}

		sector_offset += sizeof(FsmFileDirEntryT);
		FsmDfsFds[fd].FileLength  = SectorLsn;
		FsmDfsFds[fd].FilePointer = sector_offset;

		/* Release the semaphore of this file. */
		FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);

		((FsmFileInfoT *)buf)->FileLength = entry.Length;
		((FsmFileInfoT *)buf)->CreateDate = entry.Date;
		((FsmFileInfoT *)buf)->CreateTime = entry.Time;
		((FsmFileInfoT *)buf)->Attrib = entry.Type;

		FsmMemoryMove((uint8 *)((FsmFileInfoT *)buf)->FileName, 
					  (uint8 *)entry.FileName, 
					  FIELD_SIZE(FsmFileDirEntryT, FileName)
					  );

		((FsmFileInfoT *)buf)->FileName[FIELD_SIZE(FsmFileDirEntryT, FileName)] = 0;

        switch(((FsmFileInfoT *)buf)->Attrib)
        {
		case ENTRY_TYPE_SUBDIR:
			((FsmFileInfoT *)buf)->Attrib = FSM_FILE_ATTRIB_DIR;
			break;

		case ENTRY_TYPE_FILE:
			((FsmFileInfoT *)buf)->Attrib = FSM_FILE_ATTRIB_ARCHIVE;
			break;

		default:
#if (OS_TYPE == OS_WINDOWS)
			ASSERT(0);
#endif
			break;
        }

		if(ErrorCode != NULL)
		{
			*ErrorCode = ERR_NONE;
		}

		return sizeof(FsmFileInfoT);
	}
	else    /* read file. */
	{
		uint32                read_size;

		if(FsmDfsFds[fd].FileLength <= FsmDfsFds[fd].FilePointer)
		{
			/* Release the semaphore of this file. */
			FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
			status = ERR_EOF;
			goto DfsRead_Exit;
		}

		read_size = FsmDfsFds[fd].FileLength - FsmDfsFds[fd].FilePointer;

		if(read_size < size)
		{
			size = read_size;
		}

		read_size = 0;

		if ((status = FsmGetMtxSem(MediaP->MapTblLock)) != ERR_NONE)
		{
			/* Release the semaphore of this file. */
			FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
			goto DfsRead_Exit;
		}

		status = DfsReadData( DevP, 
							  buf,
							  FsmDfsFds[fd].FirstLsn,
							  FsmDfsFds[fd].FilePointer,
							  size,
							  &read_size
							  );

		if((status != ERR_NONE) && (status != ERR_EOF))
		{
			FsmReleaseMtxSem(MediaP->MapTblLock);

			/* Release the semaphore of this file. */
			FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);

			goto DfsRead_Exit; /* return zero. */

			/*
			if(ErrorCode != NULL)
			{
				*ErrorCode = status;
			}

			return read_size;
			*/
		}

		/* merge the content in queue */
		status = QueueReadData(QUEUE_FILE_DIR, fd, FsmDfsFds[fd].FilePointer, buf, size, &read_size);

		FsmReleaseMtxSem(MediaP->MapTblLock);

		if (status == ERR_NONE)
		{
			FsmDfsFds[fd].FilePointer += read_size;
		}

		/* Release the semaphore of this file. */
		FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);

		if (ErrorCode != NULL)
		{
			*ErrorCode = status;
		}

		return read_size;
	}

DfsRead_Exit:

	if(ErrorCode != NULL)
	{
		*ErrorCode = status;
	}

	return 0;
}

/*
* Function Name: DfsWrite
* Description  : Write to a file , implement the write interface
* Arguments    : fd        : file descriptor
*              : buffer    : content buffer
*              : size      : write size
* First Edit 2003.8.13 wsm
*/
uint32 FsmDfsWrite(uint32 fd, uint8 * buf, uint32 size, uint32 *ErrorCode)
{
	uint32				status;
	FsmFlashMediaT *	MediaP;
	uint32				AvailSpace;
	uint32				needSpace;

	uint32				append_size;
	uint32				modify_size;
	uint32				write_size;

	FsmDfsFileDescriptorT *	FdP;


#ifdef FSM_DEBUG
	MonPrintf("Interface DfsWrite\n");
#endif

	if (fd >= MAX_DFS_FD)
	{
		status = ERR_PARAM;
		goto DfsWrite_Exit;
	}

	FdP = &FsmDfsFds[fd];

	if(FdP->Flag != DFD_FLAG_IN_USE)
	{
		status = ERR_PARAM;
		goto DfsWrite_Exit;
	}

	/* Get the semaphore of this file. */
	status = FsmGetMtxSem(FdP->MutexSem);

	if(status != ERR_NONE)
	{
		goto DfsWrite_Exit;
	}

	/* CHECK if the fd is in PENDING or FREE state. */
	if(FdP->Flag != DFD_FLAG_IN_USE)
	{
		status = ERR_PARAM;
		goto DfsWrite_Exit1;
	}

	/* check if the operation is permitted. */
	if ((FdP->AccessMode & FSM_OPEN_WRITE) != FSM_OPEN_WRITE)
	{
		status = ERR_ACCESS_DENY;
		goto DfsWrite_Exit1;
	}

	if ((FdP->AccessMode & FSM_OPEN_DIR) == FSM_OPEN_DIR)
	{
		status = ERR_ACCESS_DENY;
		goto DfsWrite_Exit1;
	}

	if(size == 0)
	{
		/* Release the semaphore of this file. */
		FsmReleaseMtxSem(FdP->MutexSem);

		if(ErrorCode != NULL)
		{
			*ErrorCode = ERR_NONE;
		}

		return 0;
	}

	if(buf == NULL)
	{
		status = ERR_PARAM;
		goto DfsWrite_Exit1;
	}


#ifdef DFS_DIR_LOCK_ENABLED


	/* !!!!!!!!!!  NOTE  !!!!!!!!!*/
	/*
	 *  We have kept the file semaphore.
	 *  Care should be taken to avoid deadlock.
	 */
	/* check the directory operation */
	if ((status = FsmGetMtxSem(FsmDfsMtxSem)) != ERR_NONE )
	{
		goto DfsWrite_Exit1;
	}

	if (DfsIsParentDirOpened(FdP->PathName) != 0)
	{
		FsmReleaseMtxSem(FsmDfsMtxSem);
		status = ERR_ACCESS_DENY;
		goto DfsWrite_Exit1;
	}

	FsmReleaseMtxSem(FsmDfsMtxSem);

#endif /* DFS_DIR_LOCK_ENABLED */


	MediaP = (FsmFlashMediaT *)(FdP->FdHdr.DevObjP->MediaObjP);

	/* space calualation */
	AvailSpace = DfsAvailSpaceCalc(MediaP);

	append_size = 0;
	modify_size = 0;

	if((FdP->FilePointer + size) > FdP->FileLength)
	{
		append_size = (FdP->FilePointer + size) - FdP->FileLength;
		modify_size = FdP->FileLength - FdP->FilePointer;
	}
	else
	{
		modify_size = size;
	}

	needSpace = 0;

	if(modify_size > 0)
	{
		needSpace += ACCUM_CNT_MODIFY;

		needSpace += ACCUM_CNT_MODIFY_RESERVED(FdP->FilePointer,
											   modify_size, 
											   MediaP->SectorSize);
	}

	if(append_size > 0)
	{
		needSpace += ACCUM_CNT_APPEND(FdP->FileLength, append_size, MediaP->SectorSize);
	}

	if (AvailSpace < needSpace)
	{
		status = ERR_FULL;
		goto DfsWrite_Exit1;
	}

	write_size = 0;

	if(modify_size > 0)
	{
		/* add the modify to write queue */

		status = QueueAddFileDir(CMD_MODIFY, fd, FdP->FilePointer, buf, modify_size);

		if (status != ERR_NONE)
		{
			goto DfsWrite_Exit1;
		}

		buf += modify_size;

		FdP->FilePointer += modify_size;
		write_size       += modify_size;
	}

	if(append_size > 0)
	{
		status = QueueAddFileDir(CMD_APPEND, fd, FdP->FilePointer, buf, append_size);

		if (status == ERR_NONE)
		{
			FdP->FilePointer += append_size;

			FdP->FileLength += append_size;

			write_size += append_size;
		}
	}

	/* Release the semaphore of this file. */
	FsmReleaseMtxSem(FdP->MutexSem);

	if(ErrorCode != NULL)
	{
		*ErrorCode = status;
	}

	return write_size;

DfsWrite_Exit1:

	/* Release the semaphore of this file. */
	FsmReleaseMtxSem(FdP->MutexSem);

DfsWrite_Exit:

	if(ErrorCode != NULL)
	{
		*ErrorCode = status;
	}

	return 0;
}

/*
* Function Name: DfsClose
* Description  : Close an opened file , implement the close interface
* Arguments    : fd        : file descriptor
* First Edit 2003.8.13 wsm
*/
uint32 FsmDfsClose(uint32 fd)
{
	uint32		status;

#ifdef FSM_DEBUG
	MonPrintf("Interface DfsColse\n");
#endif

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

	if(FsmDfsFds[fd].Flag != DFD_FLAG_IN_USE)
	{
		return ERR_PARAM;
	}

	status = FsmGetMtxSem(FsmDfsFds[fd].MutexSem);

	if(status != ERR_NONE)
	{
		return status;
	}

	if(FsmDfsFds[fd].Flag != DFD_FLAG_IN_USE)
	{
		FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);

		return ERR_PARAM;
	}

	/*

	// maybe this implementation is better, safer than the current.
	status = WaitFdEmpty(fd, WAIT_FOREVER);

	if(status == ERR_NONE)
	{
		FsmDfsFds[fd].Flag = DFD_FLAG_PENDING;	// prevent from re-entering.
	}

	FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);

	if(status == ERR_NONE)
	{
		DfsFreeFd(fd);
	}

	return status;

	*/


	FsmDfsFds[fd].Flag = DFD_FLAG_PENDING;	/* prevent from re-entering. */

	FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);

	status = WaitFdEmpty(fd, WAIT_FOREVER);

	DfsFreeFd(fd);

	return status;
}

/*
* Function Name: DfsCreate
* Description  : Create a new file , implement the create interface
* Arguments    : filename  : file path
* First Edit 2003.8.13 wsm
*/
uint32 FsmDfsCreate(FsmDevObjHdrT * DevObjP, char * path, uint32 mode, uint32 * ErrorCodeP)
{
	uint32				status;
    char	*			name;
	uint32				len;
	uint32				fd;
	uint32              ParentDirFirstLsn;
	FsmFileDirEntryT    entry;
	char				dir[DFS_MAX_PATH_LEN + 1];

	uint32				AvailSpace;
	uint32				needSpace;


#ifdef FSM_DEBUG
	MonPrintf("Interface DfsCreate\n");
#endif

	if(strlen(path) > DFS_MAX_PATH_LEN)
	{
		status = ERR_PARAM;
		goto DfsCreate_Exit;
	}

	name = ExtractFilename(path);

	if(name == NULL)
	{
		status = ERR_PARAM;
		goto DfsCreate_Exit;
	}

	if(DfsFilenameValid(path) == FALSE)
	{
		status = ERR_PARAM;
		goto DfsCreate_Exit;
	}

	len = strlen(name);
	if((len == 0) || (len > DFS_MAX_FILE_NAME_LEN))
	{
		status = ERR_PARAM;
		goto DfsCreate_Exit;
	}

	if(ExtractDir(path, &len) != 0)
	{
		if(len > 0)

⌨️ 快捷键说明

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