📄 fsmdfs.c
字号:
{
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, §or_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 + -