📄 fsioctl.c
字号:
/* */
/***********************************************************************/
static void *remove_dir(FFSEnt *dir_ent)
{
FDIR_T *dir = &dir_ent->entry.dir;
uid_t uid;
gid_t gid;
uint i;
/*-------------------------------------------------------------------*/
/* If we're trying to delete the root directory, return error. */
/*-------------------------------------------------------------------*/
if (dir_ent == &Flash->files_tbl->tbl[0])
{
set_errno(ENOENT);
return (void *)-1;
}
/*-------------------------------------------------------------------*/
/* Check that parent directory has write permissions. */
/*-------------------------------------------------------------------*/
if (CheckPerm(dir->parent_dir->entry.dir.comm, F_WRITE))
return (void *)-1;
/*-------------------------------------------------------------------*/
/* Check owner is trying to remove directory. */
/*-------------------------------------------------------------------*/
FsGetId(&uid, &gid);
if (uid != dir->comm->user_id)
{
set_errno(EPERM);
return (void *)-1;
}
/*-------------------------------------------------------------------*/
/* If dir is the only link and is not empty, return error. */
/*-------------------------------------------------------------------*/
if (dir->first && dir->comm->links == 1)
{
set_errno(EEXIST);
return (void *)-1;
}
/*-------------------------------------------------------------------*/
/* If directory is open or if it's the current working directory of */
/* any task, return error. */
/*-------------------------------------------------------------------*/
if (dir->dir || dir->cwds)
{
set_errno(EBUSY);
return (void *)-1;
}
/*-------------------------------------------------------------------*/
/* If an open directory structure is using this entry, update it. */
/*-------------------------------------------------------------------*/
for (i = 0; i < DIROPEN_MAX; ++i)
if (Files[i].ioctl == FlashIoctl && Files[i].pos == dir_ent)
Files[i].pos = dir->prev;
/*-------------------------------------------------------------------*/
/* Remove the temp dir from the Flash->files_tbl. */
/*-------------------------------------------------------------------*/
if (dir->prev)
dir->prev->entry.dir.next = dir->next;
else
dir->parent_dir->entry.dir.first = dir->next;
if (dir->next)
dir->next->entry.dir.prev = dir->prev;
#if QUOTA_ENABLED
/*-------------------------------------------------------------------*/
/* If volume has quota enabled, update quota values. */
/*-------------------------------------------------------------------*/
if (Flash->quota_enabled)
{
ui32 used;
FFSEnt *ent, *root = &Flash->files_tbl->tbl[0];
/*-----------------------------------------------------------------*/
/* Directory should be empty and no links should point to it. */
/*-----------------------------------------------------------------*/
PfAssert(dir->first == NULL && dir->comm->links == 1);
/*-----------------------------------------------------------------*/
/* Check free below, reserved below and used. */
/*-----------------------------------------------------------------*/
PfAssert(dir->res_below == 0 && dir->free_below == 0 &&
dir->used == 0);
/*-----------------------------------------------------------------*/
/* Update used from parent to root. */
/*-----------------------------------------------------------------*/
used = strlen(dir->name) + 1 + OFDIR_SZ + OFDIR_QUOTA_SZ + OFCOM_SZ;
for (ent = dir->parent_dir; ent; ent = ent->entry.dir.parent_dir)
{
PfAssert(ent->type == FDIREN && ent->entry.dir.used >= used);
ent->entry.dir.used -= used;
}
/*-----------------------------------------------------------------*/
/* Update reserved below from parent to root. */
/*-----------------------------------------------------------------*/
for (ent = dir->parent_dir;; ent = ent->entry.dir.parent_dir)
{
PfAssert(ent->entry.dir.res_below >= dir->min_q);
ent->entry.dir.res_below -= dir->min_q;
/*---------------------------------------------------------------*/
/* Stop when we reach a directory with a reservation because */
/* the directories above this one don't have their reserved below*/
/* affected by directory removal. */
/*---------------------------------------------------------------*/
if (ent->entry.dir.min_q != 0)
break;
}
/*-----------------------------------------------------------------*/
/* Update free below. */
/*-----------------------------------------------------------------*/
FlashFreeBelow(root);
/*-----------------------------------------------------------------*/
/* Recompute free at each node. */
/*-----------------------------------------------------------------*/
FlashFree(root, root->entry.dir.max_q - FlashVirtUsed(root));
/*-----------------------------------------------------------------*/
/* Reset the quota values. */
/*-----------------------------------------------------------------*/
dir->min_q = dir->max_q = dir->free = 0;
}
#endif /* QUOTA_ENABLED */
/*-------------------------------------------------------------------*/
/* If this was the only link remove the file entry as well. */
/*-------------------------------------------------------------------*/
if (--dir->comm->links == 0)
{
dir->comm->addr->type = FEMPTY;
++Flash->total_free;
FlashIncrementTblEntries(dir->comm->addr);
Flash->tbls_size -= OFCOM_SZ;
}
/*-------------------------------------------------------------------*/
/* Clear out the entry for the removed directory. */
/*-------------------------------------------------------------------*/
dir_ent->type = FEMPTY;
dir->next = dir->prev = dir->first = NULL;
/*-------------------------------------------------------------------*/
/* Adjust the number of free file entries. */
/*-------------------------------------------------------------------*/
++Flash->total_free;
FlashIncrementTblEntries(dir_ent);
Flash->tbls_size -= (OFDIR_SZ + strlen(dir->name) + 1);
#if QUOTA_ENABLED
if (Flash->quota_enabled)
Flash->tbls_size -= OFDIR_QUOTA_SZ;
#endif /* QUOTA_ENABLED */
/*-------------------------------------------------------------------*/
/* Do garbage collection if necessary. */
/*-------------------------------------------------------------------*/
if (Flash->total_free >= (FNUM_ENT * 5 / 3))
FlashGarbageCollect();
/*-------------------------------------------------------------------*/
/* Do a sync to save everything before returning. */
/*-------------------------------------------------------------------*/
return FlashSync(Flash->do_sync);
}
/***********************************************************************/
/* remove_file: Helper function to remove file */
/* */
/* Inputs: dir_ent = parent directory for file to be removed */
/* fname = name of file to be removed */
/* */
/* Returns: NULL on success, (void *)-1 on error */
/* */
/***********************************************************************/
static void *remove_file(FFSEnt *dir_ent, const char *fname)
{
FFIL_T *link_ptr;
FFSEnt *tmp_ent;
uid_t uid;
gid_t gid;
uint i;
int rmv_file;
FDIR_T *dir = &dir_ent->entry.dir;
#if QUOTA_ENABLED
ui32 used = 0;
#endif /* QUOTA_ENABLED */
/*-------------------------------------------------------------------*/
/* Look for the file in the directory. */
/*-------------------------------------------------------------------*/
if (find_file(dir, fname, F_EXECUTE | F_WRITE, &tmp_ent, F_ONLY))
return (void *)-1;
if (tmp_ent == NULL)
{
set_errno(ENOENT);
return (void *)-1;
}
link_ptr = &tmp_ent->entry.file;
/*-------------------------------------------------------------------*/
/* Ensure that owner is trying to remove file. */
/*-------------------------------------------------------------------*/
FsGetId(&uid, &gid);
if (uid != tmp_ent->entry.file.comm->user_id)
{
set_errno(EPERM);
return (void *)-1;
}
/*-------------------------------------------------------------------*/
/* All the dirty entries in the cache that belong to this file must */
/* be cleaned. Also, for dirty old ones, increment number of free */
/* sectors. */
/*-------------------------------------------------------------------*/
if (Flash->cache.dirty_old || Flash->cache.dirty_new)
{
/*-----------------------------------------------------------------*/
/* All dirty entries belonging to file must be cleared. */
/*-----------------------------------------------------------------*/
Flash->cache.dirty_old = Flash->cache.dirty_new = FALSE;
for (i = 0; i < Flash->cache.pool_size; ++i)
{
/*---------------------------------------------------------------*/
/* If sector dirty, either it belongs to file or set dirty flags.*/
/*---------------------------------------------------------------*/
if (Flash->cache.pool[i].dirty != CLEAN)
{
/*-------------------------------------------------------------*/
/* If it belongs to the file, clear it. If dirty old, bump up */
/* free sectors count. */
/*-------------------------------------------------------------*/
if (Flash->cache.pool[i].file_ptr == link_ptr->comm)
{
if (Flash->cache.pool[i].dirty == DIRTY_OLD)
++Flash->free_sects;
Flash->cache.pool[i].dirty = CLEAN;
}
/*-------------------------------------------------------------*/
/* Else, mark the appropriate flag. */
/*-------------------------------------------------------------*/
else if (Flash->cache.pool[i].dirty == DIRTY_NEW)
Flash->cache.dirty_new = TRUE;
else
Flash->cache.dirty_old = TRUE;
}
}
}
/*-------------------------------------------------------------------*/
/* Determine whether the file to be removed is open or not. */
/*-------------------------------------------------------------------*/
rmv_file = (link_ptr->file == NULL);
/*-------------------------------------------------------------------*/
/* Decrement the number of links for the file. */
/*-------------------------------------------------------------------*/
--link_ptr->comm->links;
/*-------------------------------------------------------------------*/
/* If this was the only link to the file and there are no open file */
/* descriptors associated with link, clear contents of file. */
/*-------------------------------------------------------------------*/
if (link_ptr->comm->links == 0 && rmv_file)
{
/*-----------------------------------------------------------------*/
/* Truncate file size to zero. */
/*-----------------------------------------------------------------*/
FlashTruncZero(link_ptr, ADJUST_FCBs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -