📄 fsioctl.c
字号:
#if QUOTA_ENABLED
/*-----------------------------------------------------------------*/
/* If volume has quotas, remember link used space. */
/*-----------------------------------------------------------------*/
if (Flash->quota_enabled)
used += (strlen(link_ptr->name) + 1 + OFFIL_SZ);
#endif /* QUOTA_ENABLED */
/*-----------------------------------------------------------------*/
/* Remove file from the files table and adjust free entries. */
/*-----------------------------------------------------------------*/
link_ptr->comm->addr->type = FEMPTY;
++Flash->total_free;
FlashIncrementTblEntries(link_ptr->comm->addr);
Flash->tbls_size -= OFCOM_SZ;
}
/*-------------------------------------------------------------------*/
/* If an open dir structure has pointer to this entry, update it. */
/*-------------------------------------------------------------------*/
for (i = 0; i < DIROPEN_MAX; ++i)
if (Files[i].ioctl == FlashIoctl && Files[i].pos == tmp_ent)
Files[i].pos = link_ptr->prev;
/*-------------------------------------------------------------------*/
/* Remove the directory link, keeping directory structure. */
/*-------------------------------------------------------------------*/
if (link_ptr->prev)
link_ptr->prev->entry.dir.next = link_ptr->next;
else
dir->first = link_ptr->next;
if (link_ptr->next)
link_ptr->next->entry.dir.prev = link_ptr->prev;
/*-------------------------------------------------------------------*/
/* Check if the file is to be removed. */
/*-------------------------------------------------------------------*/
if (rmv_file)
{
/*-----------------------------------------------------------------*/
/* Clear comm ptr, set next and prev to NULL, and mark type empty. */
/*-----------------------------------------------------------------*/
link_ptr->comm = NULL;
link_ptr->next = link_ptr->prev = NULL;
tmp_ent->type = FEMPTY;
/*-----------------------------------------------------------------*/
/* Increment number of free entries. */
/*-----------------------------------------------------------------*/
++Flash->total_free;
FlashIncrementTblEntries(tmp_ent);
Flash->tbls_size -= (OFFIL_SZ + strlen(link_ptr->name) + 1);
#if QUOTA_ENABLED
/*-----------------------------------------------------------------*/
/* If quota enabled, update quota values due to file removal. */
/*-----------------------------------------------------------------*/
if (Flash->quota_enabled)
{
FFSEnt *ent, *root = &Flash->files_tbl->tbl[0];
used += OFCOM_SZ;
/*---------------------------------------------------------------*/
/* Update used from parent to root. */
/*---------------------------------------------------------------*/
for (ent = link_ptr->parent_dir; ent;
ent = ent->entry.dir.parent_dir)
{
PfAssert(ent->type == FDIREN && ent->entry.dir.used >= used);
ent->entry.dir.used -= used;
}
/*---------------------------------------------------------------*/
/* Update free below. */
/*---------------------------------------------------------------*/
FlashFreeBelow(root);
/*---------------------------------------------------------------*/
/* Recompute free at each node. */
/*---------------------------------------------------------------*/
FlashFree(root, root->entry.dir.max_q - FlashVirtUsed(root));
}
#endif /* QUOTA_ENABLED */
/*-----------------------------------------------------------------*/
/* Do garbage collection if necessary. */
/*-----------------------------------------------------------------*/
if (Flash->total_free >= (FNUM_ENT * 5 / 3))
FlashGarbageCollect();
}
/*-------------------------------------------------------------------*/
/* Else don't free the entry yet. Free it when the last open file */
/* descriptor for this link is closed. For now, just set next and */
/* prev to REMOVED_LINK. */
/*-------------------------------------------------------------------*/
else
link_ptr->next = link_ptr->prev = (FFSEnt *)REMOVED_LINK;
/*-------------------------------------------------------------------*/
/* Do a sync to save new state of file system. */
/*-------------------------------------------------------------------*/
return FlashSync(Flash->do_sync);
}
/***********************************************************************/
/* find_file: Look for a file with name path in dir */
/* */
/* Inputs: dir = parent directory to look into */
/* path = file name */
/* mode = permissions directory must have */
/* entry = place to store found file */
/* search_flag = look for file only/ file and dir */
/* */
/* Returns: -1 if error in searching, 0 otherwise (entry will have */
/* either pointer to found file or NULL otherwise) */
/* */
/***********************************************************************/
static int find_file(const FDIR_T *dir, const char *path, int mode,
FFSEnt **entry, int search_flag)
{
/*-------------------------------------------------------------------*/
/* If path ends in '/', return error (it's not a file), else look if */
/* file exists. */
/*-------------------------------------------------------------------*/
if (path[strlen(path) - 1] == '/')
{
set_errno(EINVAL);
return -1;
}
/*-------------------------------------------------------------------*/
/* Check that parent directory has permissions. */
/*-------------------------------------------------------------------*/
if (CheckPerm(dir->comm, mode))
return -1;
/*-------------------------------------------------------------------*/
/* Look for file in its parent directory. */
/*-------------------------------------------------------------------*/
for (*entry = dir->first; *entry; *entry = (*entry)->entry.dir.next)
{
/*-----------------------------------------------------------------*/
/* Check if entry's name matches our file's name. */
/*-----------------------------------------------------------------*/
if (!strcmp((*entry)->entry.dir.name, path))
{
/*---------------------------------------------------------------*/
/* Error if looking for regular file and this is a directory. */
/*---------------------------------------------------------------*/
if (search_flag == F_ONLY && (*entry)->type != FFILEN)
{
set_errno(EISDIR);
return -1;
}
break;
}
}
return 0;
}
/***********************************************************************/
/* find_new_place: Find a free entry from among the list of tables */
/* */
/* Input: smallest = ptr to table to be removed */
/* */
/* Returns: pointer to found entry or NULL if no entry was found */
/* */
/***********************************************************************/
static FFSEnt *find_new_place(const FFSEnts *smallest)
{
int i;
FFSEnts *tbl;
/*-------------------------------------------------------------------*/
/* Loop over every file table. */
/*-------------------------------------------------------------------*/
for (tbl = Flash->files_tbl; tbl; tbl = tbl->next_tbl)
{
/*-----------------------------------------------------------------*/
/* Check if table is not being removed and has a free entry. */
/*-----------------------------------------------------------------*/
if ((tbl != smallest) && tbl->free)
{
/*---------------------------------------------------------------*/
/* Decrease free entry count and return pointer to free entry. */
/*---------------------------------------------------------------*/
--tbl->free;
for (i = 0;; ++i)
{
PfAssert(i < FNUM_ENT);
if (tbl->tbl[i].type == FEMPTY)
return &tbl->tbl[i];
}
}
}
/*-------------------------------------------------------------------*/
/* No free entries were found. */
/*-------------------------------------------------------------------*/
return NULL;
}
/***********************************************************************/
/* update_entries: Go through all non-empty entries, and for entry */
/* pointing to old entry, update it to the new entry */
/* */
/* Inputs: old_ent = pointer to old entry */
/* new_ent = pointer to new entry */
/* */
/***********************************************************************/
static void update_entries(const FFSEnt *old_ent, FFSEnt *new_ent)
{
FFSEnts *curr_tbl = Flash->files_tbl;
FFSEnt *curr_dir;
FDIR_T *dir;
FFIL_T *link_ptr;
int i;
ui32 dummy;
for (i = 0; curr_tbl; ++i)
{
/*-----------------------------------------------------------------*/
/* If entry is a directory, look at next, prev, parent, first, and */
/* actual file to see if any is equal to the old entry. */
/*-----------------------------------------------------------------*/
if (curr_tbl->tbl[i].type == FDIREN)
{
dir = &(curr_tbl->tbl[i].entry.dir);
if (dir->next == old_ent)
dir->next = new_ent;
else if (dir->prev == old_ent)
dir->prev = new_ent;
else if (dir->parent_dir == old_ent)
dir->parent_dir = new_ent;
else if (dir->first == old_ent)
dir->first = new_ent;
else if (dir->comm->addr == old_ent)
{
new_ent->entry.comm.addr = new_ent;
dir->comm = &(new_ent->entry.comm);
}
}
/*-----------------------------------------------------------------*/
/* Else if entry is link, look at next, prev, parent and the actual*/
/* file to see if any is equal to the old entry. */
/*-----------------------------------------------------------------*/
else if (curr_tbl->tbl[i].type == FFILEN)
{
link_ptr = &(curr_tbl->tbl[i].entry.file);
if (link_ptr->next == old_ent)
link_ptr->next = new_ent;
else if (link_ptr->prev == old_ent)
link_ptr->prev = new_ent;
else if (link_ptr->parent_dir == old_ent)
link_ptr->parent_dir = new_ent;
else if (link_ptr->comm->addr == old_ent)
{
new_ent->entry.comm.addr = new_ent;
link_ptr->comm = &(new_ent->entry.comm);
}
}
/*-----------------------------------------------------------------*/
/* If we are at the end of the current table, go to the next one. */
/*-----------------------------------------------------------------*/
if (i == (FNUM_ENT - 1))
{
i = -1;
curr_tbl = curr_tbl->next_tbl;
}
}
/*-------------------------------------------------------------------*/
/* Adjust all the open streams handles if necessary. */
/*-------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -