📄 fsmdfs.c
字号:
FsmDfsFileDescriptorT * FdP;
FdP = &FsmDfsFds[fd];
if(FdP->Flag != DFD_FLAG_IN_USE)
{
return ERR_PARAM;
}
/* Get the semaphore of this file. */
status = FsmGetMtxSem(FdP->MutexSem);
if(status != ERR_NONE)
{
return status;
}
/* CHECK if the fd is in PENDING or FREE state. */
if(FdP->Flag != DFD_FLAG_IN_USE)
{
FsmReleaseMtxSem(FdP->MutexSem);
return ERR_PARAM;
}
if (FdP->Attrib == ENTRY_TYPE_SUBDIR)
{
FsmReleaseMtxSem(FdP->MutexSem);
return ERR_PARAM;
}
status = ERR_PARAM;
if (arg->whence == FSM_FILE_BEGIN)
{
if ((arg->offset >= 0) && ((uint32)arg->offset <= FdP->FileLength))
{
FdP->FilePointer = arg->offset;
status = ERR_NONE;
}
}
else if (arg->whence == FSM_FILE_END)
{
if ((arg->offset <= 0) && (FdP->FileLength >= (uint32)(-arg->offset)))
{
FdP->FilePointer = FdP->FileLength - (uint32)(-arg->offset);
status = ERR_NONE;
}
}
else if (arg->whence == FSM_FILE_CURRENT)
{
if ((arg->offset >= 0)
&& ((arg->offset + FdP->FilePointer) <= FdP->FileLength))
{
FdP->FilePointer = arg->offset + FdP->FilePointer;
status = ERR_NONE;
}
else if((arg->offset < 0)
&& (FdP->FilePointer >= (uint32)(-arg->offset)))
{
FdP->FilePointer = FdP->FilePointer - (uint32)(-arg->offset);
status = ERR_NONE;
}
}
FsmReleaseMtxSem(FdP->MutexSem);
return status;
}
/* */
uint32 DfsFileGetAttrib(uint32 fd, FsmFileAttribT * attrib)
{
uint32 status;
/* Get the semaphore of this file. */
status = FsmGetMtxSem(FsmDfsFds[fd].MutexSem);
if(status != ERR_NONE)
{
return status;
}
attrib->FileLength = FsmDfsFds[fd].FileLength;
attrib->CreateDate = FsmDfsFds[fd].CreateDate;
attrib->CreateTime = FsmDfsFds[fd].CreateTime;
attrib->Attrib = FsmDfsFds[fd].Attrib;
FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
switch(attrib->Attrib)
{
case ENTRY_TYPE_SUBDIR:
attrib->Attrib = FSM_FILE_ATTRIB_DIR;
break;
case ENTRY_TYPE_FILE:
attrib->Attrib = FSM_FILE_ATTRIB_ARCHIVE;
break;
default:
#if (OS_TYPE == OS_WINDOWS)
ASSERT(0);
#endif
break;
}
return ERR_NONE;
}
/* implement the Truncate */
uint32 DfsFileTruncate(uint32 fd, uint32 size)
{
uint32 status;
uint32 AvailSpace;
uint32 needSpace;
FsmDfsFileDescriptorT * FdP;
FdP = &FsmDfsFds[fd];
if(FdP->Flag != DFD_FLAG_IN_USE)
{
return ERR_PARAM;
}
/* Get the semaphore of this file. */
status = FsmGetMtxSem(FdP->MutexSem);
if(status != ERR_NONE)
{
return status;
}
/* CHECK if the fd is in PENDING or FREE state. */
if(FdP->Flag != DFD_FLAG_IN_USE)
{
FsmReleaseMtxSem(FdP->MutexSem);
return ERR_PARAM;
}
if (FdP->Attrib == ENTRY_TYPE_SUBDIR)
{
FsmReleaseMtxSem(FdP->MutexSem);
return ERR_ACCESS_DENY;
}
if ((FdP->AccessMode & FSM_OPEN_WRITE) != FSM_OPEN_WRITE)
{
FsmReleaseMtxSem(FdP->MutexSem);
return ERR_ACCESS_DENY;
}
if (FdP->FileLength == size)
{
FsmReleaseMtxSem(FdP->MutexSem);
return ERR_NONE;
}
if (FdP->FileLength < size)
{
FsmReleaseMtxSem(FdP->MutexSem);
return ERR_PARAM;
}
#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)
{
FsmReleaseMtxSem(FdP->MutexSem);
return status;
}
if (DfsIsParentDirOpened(FsmDfsFds[fd].PathName) != 0)
{
FsmReleaseMtxSem(FsmDfsMtxSem);
FsmReleaseMtxSem(FdP->MutexSem);
return ERR_ACCESS_DENY;
}
FsmReleaseMtxSem(FsmDfsMtxSem);
#endif /* DFS_DIR_LOCK_ENABLED */
AvailSpace = DfsAvailSpaceCalc((FsmFlashMediaT *)FdP->FdHdr.DevObjP->MediaObjP);
needSpace = ACCUM_CNT_TRUNCATE;
if (AvailSpace < needSpace)
{
FsmReleaseMtxSem(FdP->MutexSem);
return ERR_FULL;
}
status = QueueAddFileDir(CMD_TRUNCATE, fd, size, NULL, 0);
if (status == ERR_NONE)
{
FdP->FileLength = size;
if(FdP->FilePointer > size)
FdP->FilePointer = size;
}
FsmReleaseMtxSem(FdP->MutexSem);
return status;
}
/*
* rename a file or a directory.
*/
uint32 DfsFileRename(FsmIoctlRenameT * arg)
{
uint32 status;
FsmFileDirEntryT entry;
uint32 AvailSpace;
uint32 needSpace;
uint32 ParentDirFirstLsn;
uint32 fd;
uint32 len;
char newpath[DFS_MAX_PATH_LEN + 1];
len = strlen((char *)arg->path);
if(len > DFS_MAX_PATH_LEN)
{
return ERR_PARAM;
}
/* Is it root directory ? */
if ((len == 1)
&& ((*(arg->path) == '\\') || (*(arg->path) == '/')))
{
return ERR_ACCESS_DENY;
}
if(arg->newname == NULL)
{
return ERR_PARAM;
}
len = strlen(arg->newname);
if((len == 0) || (len > DFS_MAX_FILE_NAME_LEN))
{
return ERR_PARAM;
}
if(ExtractDir(arg->path, &len) != 0)
{
if((len + strlen(arg->newname)) > DFS_MAX_PATH_LEN)
{
return ERR_PARAM;
}
else if(len > 0)
{
FsmMemoryMove((uint8 *)newpath, (uint8 *)arg->path, len);
newpath[len] = 0;
strcat(newpath, arg->newname);
}
else
{
return ERR_PARAM;
}
}
else
{
return ERR_PARAM;
}
if((status = FsmGetMtxSem(FsmDfsMtxSem)) != ERR_NONE)
{
return status;
}
if(DfsIsFileOpened((char *)arg->path) != INVALID_FILE_HANDLE)
{
FsmReleaseMtxSem(FsmDfsMtxSem);
return ERR_ACCESS_DENY;
}
if(DfsIsFileOpened((char *)newpath) != INVALID_FILE_HANDLE)
{
FsmReleaseMtxSem(FsmDfsMtxSem);
return ERR_EXIST;
}
#ifdef DFS_DIR_LOCK_ENABLED
if (DfsIsParentDirOpened((char *)arg->path) != 0)
{
FsmReleaseMtxSem(FsmDfsMtxSem);
return ERR_ACCESS_DENY;
}
#endif /* DFS_DIR_LOCK_ENABLED */
if ((fd = DfsAllocFd()) == INVALID_FILE_HANDLE)
{
FsmReleaseMtxSem(FsmDfsMtxSem);
return ERR_MAX_OPEN;
}
FsmDfsFds[fd].AccessMode = FSM_OPEN_WRITE;
FsmDfsFds[fd].FdHdr.DevObjP = arg->DevObjP; /* prevent this device from being unmounted. */
strcpy(FsmDfsFds[fd].PathName, arg->path);
FsmReleaseMtxSem(FsmDfsMtxSem);
status = FsmGetMtxSem(FsmDfsFds[fd].MutexSem);
if(status != ERR_NONE)
{
DfsFreeFd(fd);
return status;
}
/* check if the new name file exist. */
status = DfsLocateFile(arg->DevObjP, newpath, &ParentDirFirstLsn, &entry);
if (status == ERR_NONE)
{
/* new name exists. */
FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
DfsFreeFd(fd);
return ERR_EXIST;
}
/* check if the old filename exists. */
status = DfsLocateFile(arg->DevObjP, (char *)arg->path, &ParentDirFirstLsn, &entry);
if(status != ERR_NONE)
{
/* file doesn't exist. */
FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
DfsFreeFd(fd);
return ERR_NOTEXIST;
}
/* */
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_RENAME;
if (AvailSpace < needSpace)
{
FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
DfsFreeFd(fd);
return ERR_FULL;
}
status = QueueAddFileDir(CMD_RENAME, fd, 0, (uint8 *)arg->newname, strlen(arg->newname) + 1);
/* Added '1' for the NULL-terminated string -----^ */
if (status != ERR_NONE)
{
FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
DfsFreeFd(fd);
return status;
}
WaitFdEmpty(fd, WAIT_FOREVER);
FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
DfsFreeFd(fd);
return ERR_NONE;
}
uint32 DfsFileFlush(uint32 fd)
{
uint32 status;
FsmDfsFileDescriptorT * FdP;
FdP = &FsmDfsFds[fd];
if(FdP->Flag != DFD_FLAG_IN_USE)
{
return ERR_PARAM;
}
/* Get the semaphore of this file. */
status = FsmGetMtxSem(FdP->MutexSem);
if(status != ERR_NONE)
{
return status;
}
/* CHECK if the fd is in PENDING or FREE state. */
if(FdP->Flag != DFD_FLAG_IN_USE)
{
FsmReleaseMtxSem(FdP->MutexSem);
return ERR_PARAM;
}
WaitFdEmpty(fd, WAIT_FOREVER);
FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
return ERR_NONE;
}
uint32 DfsGetVolumeFreeSpace(FsmIoctlGetFreeSpaceT* arg)
{
FsmFlashMediaT * MediaP;
FsmFlashDevT * DevP;
DevP = (FsmFlashDevT *)arg->DevObjP;
MediaP = (FsmFlashMediaT *)arg->DevObjP->MediaObjP;
*(arg->total_space) = (DevP->Blocks - 1) * MediaP->SectorSize * MediaP->SectorsPerBlock;
*(arg->avail_space) = DfsAvailSpaceCalc(MediaP);
*(arg->avail_space) *= MediaP->SectorSize;
*(arg->free_space) = *(arg->avail_space);
return ERR_NONE;
}
uint32 DfsFormat(FsmDevObjHdrT * DevObjP)
{
uint16 i;
uint32 status;
uint32 Address;
uint32 FsmTag;
DEV_WRITE_FUNCPTR DevWrite;
if(DevObjP == NULL)
{
return ERR_PARAM;
}
DevWrite = DevObjP->DevDrvP->FsmDevWrite;
if (DevWrite == NULL)
{
return ERR_SYSTEM;
}
FsmTag = 0;
Address = ((FsmFlashDevT *)DevObjP)->BlockSize;
Address -= (sizeof(FsmBlockInfoT) - FIELD_OFFSET(FsmBlockInfoT, Tag));
for (i = 0; i < ((FsmFlashDevT *)DevObjP)->Blocks; i++)
{
status = DevWrite( DevObjP,
(uint8 *)&FsmTag,
Address,
FIELD_SIZE(FsmBlockInfoT, Tag)
);
if (status != ERR_NONE)
{
return status;
}
Address += ((FsmFlashDevT *)DevObjP)->BlockSize;
}
return ERR_NONE;
}
#if 0
/* for wear-level test only. */
uint32 DfsGetBlockInfo(FsmDevObjHdrT * DevObjP, uint32 * EraseNum)
{
uint16 i;
FsmFlashMediaT * MediaP;
FsmBlockStatisticT * BlkInfoP;
if(DevObjP == NULL)
{
return ERR_SYSTEM;
}
MediaP = DevObjP->MediaObjP;
if (MediaP == NULL)
{
return ERR_SYSTEM;
}
BlkInfoP = MediaP->BlockInfoP;
for (i = 0; i < ((FsmFlashDevT *)DevObjP)->Blocks; i++)
{
EraseNum[i] = BlkInfoP[i].EraseCount;
}
return ERR_NONE;
}
#endif
/************************************** help functions ************************************/
/* locate file in the flash. */
static uint32 DfsLocateFile(
FsmDevObjHdrT * DevP,
char * path,
uint32 * ParentDirFirstLsn,
FsmFileDirEntryT * entry
)
{
uint32 status = ERR_PARAM;
uint32 FirstLsn;
uint32 SectorLsn;
uint32 sector_offset;
uint32 name_len;
uint32 offset;
uint32 start;
uint32 dir_name_len;
uint32 max_name_len = FIELD_SIZE(FsmFileDirEntryT, FileName);
char dirname[FIELD_SIZE(FsmFileDirEntryT, FileName) + 1];
char read_dirname[FIELD_SIZE(FsmFileDirEntryT, FileName) + 1];
#ifdef FSM_DEBUG
MonPrintf("Enter the DfsLocateFile\n");
#endif
if(path == NULL)
{
return ERR_PARAM;
}
name_len = strlen(path);
if(name_len == 0)
{
return ERR_PARAM;
}
FsmMemorySet((uint8 *)entry, 0, sizeof(FsmFileDirEntryT));
if(name_len == 1)
{
if((*path == '/') || (*path == '\\'))
{
/* it is root directory. */
entry->FirstLsn = 0;
entry->Length = 0;
entry->Status = ENTRY_VALID;
entry->Type = ENTRY_TYPE_SUBDIR;
*ParentDirFirstLsn = (uint32)(-1);
return ERR_NONE;
}
}
*ParentDirFirstLsn = (uint32)(-1);
FirstLsn = 0;
SectorLsn = FirstLsn;
sector_offset = 0;
offset = 0;
start = 0;
dir_name_len = 0;
GetFirstPath(&path[offset], &start, &dir_name_len);
if(dir_name_len > max_name_len)
{
return ERR_PARAM;
}
FsmMemoryMove((uint8 *)dirname, (uint8 *)&path[offset + start], dir_name_len);
dirname[dir_name_len] = 0;
while(offset < name_len)
{
status = DfsReadFileEntry(DevP, &SectorLsn, §or_offset, entry);
if(status != ERR_NONE)
{
break;
}
FsmMemoryMove((uint8 *)read_dirname,
(uint8 *)entry->FileName,
FIELD_SIZE(FsmFileDirEntryT, FileName)
);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -