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

📄 fsmdfs.c

📁 norflash的文件系统。 用于中低端手机开发的参考
💻 C
📖 第 1 页 / 共 5 页
字号:
		{
			FsmMemoryMove((uint8 *)dir, (uint8 *)path, len);
			dir[len] = 0; /* It is a zero-end string now. */

			/* If it is not root dir, then discard the last slash. */
			if(strlen(dir) != 1)
				dir[len - 1] = 0; 
		}
		else
		{
			status = ERR_PARAM;
			goto DfsCreate_Exit;
		}
	}
	else
	{
		status = ERR_PARAM;
		goto DfsCreate_Exit;
	}

	if ((status = FsmGetMtxSem(FsmDfsMtxSem)) != ERR_NONE )
	{
		goto DfsCreate_Exit;
	}

	if (DfsIsFileOpened(path) != INVALID_FILE_HANDLE)
	{
		/* file or directory has existed and has been opened. */
		FsmReleaseMtxSem(FsmDfsMtxSem);

		status = ERR_ACCESS_DENY;

		goto DfsCreate_Exit;
	}


#ifdef DFS_DIR_LOCK_ENABLED

	if (DfsIsParentDirOpened(path) != 0)
	{
		FsmReleaseMtxSem(FsmDfsMtxSem);

		status = ERR_ACCESS_DENY;

		goto DfsCreate_Exit;
	}

#endif /* DFS_DIR_LOCK_ENABLED */

	fd = DfsAllocFd();

	if (fd == INVALID_FILE_HANDLE)
	{
		FsmReleaseMtxSem(FsmDfsMtxSem);

		status = ERR_MAX_OPEN;

		goto DfsCreate_Exit;
	}

	FsmDfsFds[fd].AccessMode = mode;	/* prevent the followed open for write or for read if mode = WRITE. */

	FsmDfsFds[fd].FdHdr.DevObjP = DevObjP;	/* prevent this device from being unmounted. */

	strcpy(FsmDfsFds[fd].PathName, path);

	FsmReleaseMtxSem(FsmDfsMtxSem);

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

	if(status != ERR_NONE)
	{
		DfsFreeFd(fd);
		goto DfsCreate_Exit;
	}

	status = DfsLocateFile(DevObjP, path, &ParentDirFirstLsn, &entry);

	/* file or directory already exists. */
	if(status == ERR_NONE)
	{
		status = ERR_EXIST;
		goto DfsCreate_Exit2;
	}

	if(status != ERR_NOTEXIST)
	{
		goto DfsCreate_Exit2;
	}

	/* check if the parent directory exists. */
	status = DfsLocateFile(DevObjP, dir, &ParentDirFirstLsn, &entry);

	/* parent dir doesn't exist. */
	if(status != ERR_NONE)
	{
		goto DfsCreate_Exit2;
	}

	/* fill the local fd structure */

/*	FsmDfsFds[fd].AccessMode = mode; */
	FsmDfsFds[fd].ParentDirFirstLsn = entry.FirstLsn;
	FsmDfsFds[fd].FilePointer = 0;

	FsmDfsFds[fd].CreateDate = FsmGetCurrentDate();
	FsmDfsFds[fd].CreateTime = (uint16)FsmGetCurrentTime();

	/* This field will be updated by the write task. */
	FsmDfsFds[fd].FirstLsn = (uint32)(-1);

	if (mode & FSM_OPEN_FILE)
	{
		FsmDfsFds[fd].FileLength = 0;
		FsmDfsFds[fd].Attrib = ENTRY_TYPE_FILE;

		needSpace = ACCUM_CNT_CREATE;
	}
	else if (mode & FSM_OPEN_DIR)
	{
		/* 
		 * For subdirectory, Length always = 0.
		 * We will use this field as file pointer
		 * along with FilePointer field.
		 * In that case, Length field stores sector LSN,
		 * and FilePointer field stores offset into the sector.
		 */
		/* This field will also be updated by write task. */
		FsmDfsFds[fd].FileLength = (uint32)(-1);	/* FirstLsn. */
		FsmDfsFds[fd].Attrib = ENTRY_TYPE_SUBDIR;

		needSpace = ACCUM_CNT_MKDIR;
	}
	else
	{
		status = ERR_PARAM;
		goto DfsCreate_Exit2;
	}

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

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

	/* for the create of the directory */
	if (mode & FSM_OPEN_DIR)
	{
		/* It is to create a new directory. */
		status = QueueAddFileDir(CMD_MKDIR, fd, 0, (uint8 *)path, strlen(path));

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

		WaitFdEmpty(fd, WAIT_FOREVER);

		/*
		// we can return the Directory FD if it is required.

		// If this feature is implemented, open function should
		// search directory in queue when target directory is not 
		// found in the device. (it is very complicated.)

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

		FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);

		status = ERR_NONE;

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

		return fd;
		*/

		/*
		 * Don't set Flag field to DFD_FLAG_IN_USE,
		 * because it will be freed immediately.
		 */
		FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);

		DfsFreeFd(fd);

		status = ERR_NONE;

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

		return INVALID_FILE_HANDLE;
	}
	else
	{
		/* It is to creat a new file. */
		status = QueueAddFileDir(CMD_CREATE, fd, 0, NULL, 0);

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

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

		FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);

		status = ERR_NONE;

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

		return fd;
	}

DfsCreate_Exit2:

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

DfsCreate_Exit:

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

	return INVALID_FILE_HANDLE;
}

/*
* Function Name: DfsDelete
* Description  : Delete a file , implement the delete interface
* Arguments    : filename  : file path
* First Edit 2003.8.13 wsm
*/
uint32 FsmDfsDelete(FsmDevObjHdrT * DevObjP, char * path)
{
	uint32				status;
	FsmFileDirEntryT	entry;
    uint32				AvailSpace;
    uint32				needSpace;
	uint32				ParentDirFirstLsn;
	uint32				fd;
	uint32				len;


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

	if (DfsFilenameValid(path) == FALSE)
	{
	    return ERR_PARAM;
	}

	len = strlen(path);

	if ((len == 0) || (len > DFS_MAX_PATH_LEN))
	{
	    return ERR_PARAM;
	}

	if ((len == 1) && ((*path == '\\') || (*path == '/')))
	{
		/* It is root dir, cannot be deleted. */
		return ERR_ACCESS_DENY;
	}

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

	if (DfsIsFileOpened(path) != INVALID_FILE_HANDLE)
	{
		/* file or directory is opened. */
		FsmReleaseMtxSem(FsmDfsMtxSem);

		return ERR_ACCESS_DENY;
	}


#ifdef DFS_DIR_LOCK_ENABLED

	if (DfsIsParentDirOpened(path) != 0)
	{
		FsmReleaseMtxSem(FsmDfsMtxSem);
		return ERR_ACCESS_DENY;
	}

#endif /* DFS_DIR_LOCK_ENABLED */

	fd = DfsAllocFd();		/* fd in PENDING state. 
							 * We must not set this fd to IN_USE state, 
							 * for it is being deleted. */

	if (fd == INVALID_FILE_HANDLE)
	{
		FsmReleaseMtxSem(FsmDfsMtxSem);
		return ERR_MAX_OPEN;
	}

	FsmDfsFds[fd].AccessMode = FSM_OPEN_WRITE;	/* prevent the followed open for write or read. */

	FsmDfsFds[fd].FdHdr.DevObjP = DevObjP;	/* prevent this device from being unmounted. */

	strcpy(FsmDfsFds[fd].PathName, path);

	FsmReleaseMtxSem(FsmDfsMtxSem);

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

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

	/* search the file or directory in device. */
	status = DfsLocateFile(DevObjP, path, &ParentDirFirstLsn, &entry);
	if (status != ERR_NONE)
	{
		/* if cannot find, release the fd semaphore, free fd, return error. */
		FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
		DfsFreeFd(fd);
		return ERR_NOTEXIST;
	}

	/* fill the FD content */
	FsmDfsFds[fd].FileLength = entry.Length;
	FsmDfsFds[fd].FirstLsn = entry.FirstLsn;
	FsmDfsFds[fd].ParentDirFirstLsn = ParentDirFirstLsn;
	FsmDfsFds[fd].FilePointer = 0;
	FsmDfsFds[fd].CreateDate = entry.Date;
	FsmDfsFds[fd].CreateTime = entry.Time;
	FsmDfsFds[fd].Attrib = entry.Type;

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

	needSpace = ACCUM_CNT_DELETE;

	if (AvailSpace < needSpace)
	{
		FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
		DfsFreeFd(fd);
		return ERR_FULL;
	}


	if (FsmDfsFds[fd].Attrib == ENTRY_TYPE_FILE)
	{
		/* delete a file. */

		FsmDfsFds[fd].AccessMode |= FSM_OPEN_FILE;

		/* add a queue item to the wirte queue */
		status = QueueAddFileDir(CMD_DELETE, fd, 0, NULL, 0);
		if (status != ERR_NONE)
		{
			FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
			DfsFreeFd(fd);
			return status;
		}
	}
	else if (FsmDfsFds[fd].Attrib == ENTRY_TYPE_SUBDIR)
    {
		/* delete a directory. */

		char		dir[DFS_MAX_PATH_LEN + 3];
		uint32		SectorLsn;
		uint32		sector_offset;
		uint8		slash_ch;
		uint8		found = FALSE;
		uint16		entry_cnt = 0;
		uint16		i;


		strcpy(dir, path);

		slash_ch = '\\';

		if(dir[0] == '/')
		{
			slash_ch = '/';
		}

		len = strlen(dir);

		if ((dir[len - 1] == '\\') || (dir[len - 1] == '/'))
		{
			dir[len] = '*'; 
			dir[len + 1] = 0;
		}
		else
		{
			dir[len] = slash_ch;
			dir[len + 1] = '*';
			dir[len + 2] = 0;
		}

		/* !!!!!!!!!!  NOTE  !!!!!!!!!*/
		/*
		 *  We have kept the file semaphore.
		 *  Care should be taken to avoid deadlock.
		 */
		if((status = FsmGetMtxSem(FsmDfsMtxSem)) != ERR_NONE)
		{
			FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
			DfsFreeFd(fd);
			return status;
		}

		for (i = 0; i < MAX_DFS_FD; i++)
		{
			/* if there is file under this dir in use. */
			if (FsmStringMatched(dir, FsmDfsFds[i].PathName) == 1)
			{
				FsmReleaseMtxSem(FsmDfsMtxSem);
				FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
				DfsFreeFd(fd);
				return ERR_ACCESS_DENY;
			}
		}

		/* !!!!!!!!!!  NOTE  !!!!!!!!!*/
		/*
		 *  Free the FD lock here.
		 */
		FsmReleaseMtxSem(FsmDfsMtxSem);


		SectorLsn = FsmDfsFds[fd].FirstLsn;
		sector_offset = FsmDfsFds[fd].FilePointer;

		found = FALSE;
		entry_cnt = 0;

        /* check if the dir is empty, ignore the ".." entry. */
		while(TRUE)
		{
			status = DfsReadFileEntry(DevObjP, &SectorLsn, &sector_offset, &entry);

			if(status != ERR_NONE)
			{
				break;
			}

			/* From now on, dir[] is used to hold the file name. */
			FsmMemoryMove((uint8 *)dir, 
						  (uint8 *)entry.FileName, 
						  FIELD_SIZE(FsmFileDirEntryT, FileName)
						  );

			dir[FIELD_SIZE(FsmFileDirEntryT, FileName)] = 0;

			if(strcmp(dir, "..") != 0)
			{
				found = TRUE;
				break;
			}

			sector_offset += sizeof(FsmFileDirEntryT);

			entry_cnt++;

			if(entry_cnt >= 2)
			{
				/* error occurs, found two ".." entries. */
				break;
			}
		}

		if (found == TRUE)
		{
			/* dir is not empty, delete fails. */
			FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
			DfsFreeFd(fd);
			return ERR_ACCESS_DENY;
		}

		/* The directory could be deleted */
		FsmDfsFds[fd].AccessMode |= FSM_OPEN_DIR;

		/* add a queue item to the wirte queue */
		status = QueueAddFileDir(CMD_RMDIR, fd, 0, NULL, 0);

		if (status != ERR_NONE)
		{
			FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
			DfsFreeFd(fd);
			return status;
		}
	}

	WaitFdEmpty(fd, WAIT_FOREVER); /* wait until the operation is done */

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

	return status;
}

/*
* Function Name: DfsIoctrl
* Description  : Parse command , implement the ioctrl interface
* Arguments    : command      :command
*              : fd           : file descriptor
*              : argument     : point to the arguments structure
* First Edit 2003.8.13 wsm
*/
uint32 FsmDfsIoCtrl( uint32 fd, uint32 cmd, void * arg)
{
	uint32		status;

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

	switch(cmd)
	{
	case FSM_IOCTL_RENAME:
	case FSM_IOCTL_GET_FREE_SPACE:
	case FSM_IOCTL_FORMAT:
		break;

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

	status = ERR_NONE;

	switch(cmd)
	{
	case FSM_IOCTL_GET_ATTRIB:
		status = DfsFileGetAttrib(fd, (FsmFileAttribT *)arg);
		break;

	case FSM_IOCTL_TRUNCATE:
		status = DfsFileTruncate(fd, *((uint32 *)arg));
		break;

	case FSM_IOCTL_RENAME:
		status = DfsFileRename((FsmIoctlRenameT *)arg);
		break;

	case FSM_IOCTL_FLUSH:
		status = DfsFileFlush(fd);
		break;

	case FSM_IOCTL_GET_FREE_SPACE:
		status = DfsGetVolumeFreeSpace((FsmIoctlGetFreeSpaceT *)arg);
		break;

	case FSM_IOCTL_SEEK:
		status = DfsFileSeek(fd, (FsmIoctlSeekT *)arg);
		break;

	case FSM_IOCTL_TELL:
		status = ERR_NONE;
		*(uint32 *)arg = (FsmDfsFds[fd].FilePointer);
		break;

	case FSM_IOCTL_EOF:
		status = DfsFileEof(fd, (uint32 *)arg);
		break;

	case FSM_IOCTL_FORMAT:
        status = DfsFormat((FsmDevObjHdrT *)arg);
		break;

	default:
		status = ERR_NOT_SUPPORT;
		break;
	}

	return status;
}

/* implement the EOF */
uint32 DfsFileEof(uint32 fd, uint32 * eof)
{
	FsmDfsFileDescriptorT *	FdP;

	FdP = &FsmDfsFds[fd];

	if (FdP->Attrib == ENTRY_TYPE_SUBDIR)
	{
		return ERR_PARAM;
	}

	*eof = (FdP->FileLength == FdP->FilePointer);

	return ERR_NONE;
}

/* implement the Seek */
uint32 DfsFileSeek(uint32 fd, FsmIoctlSeekT * arg)
{
	uint32		status;

⌨️ 快捷键说明

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