📄 rsioctl.c
字号:
/* */
/***********************************************************************/
static void *remove_file(RFSEnt *dir_ent, const char *fname)
{
RFIL_T *link_ptr;
RFSEnt *tmp_ent;
uid_t uid;
gid_t gid;
uint i;
int rmv_file;
RDIR_T *dir = &dir_ent->entry.dir;
/*-------------------------------------------------------------------*/
/* 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;
}
/*-------------------------------------------------------------------*/
/* 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. */
/*-----------------------------------------------------------------*/
ram_trunc_zero(link_ptr);
/*-----------------------------------------------------------------*/
/* Remove file from the files table and adjust free entries. */
/*-----------------------------------------------------------------*/
link_ptr->comm->addr->type = FEMPTY;
++Ram->total_free;
incTblEntries(link_ptr->comm->addr);
}
/*-------------------------------------------------------------------*/
/* If an open dir structure has pointer to this entry, update it. */
/*-------------------------------------------------------------------*/
for (i = 0; i < FOPEN_MAX; ++i)
if (Files[i].ioctl == RamIoctl && 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;
/*-------------------------------------------------------------------*/
/* If the file is to be removed, clear the comm ptr and set the link */
/* entry to empty, clear file, next and prev. */
/*-------------------------------------------------------------------*/
if (rmv_file)
{
link_ptr->comm = NULL;
link_ptr->parent_dir = link_ptr->next = link_ptr->prev = NULL;
link_ptr->file = NULL;
tmp_ent->type = FEMPTY;
/*-----------------------------------------------------------------*/
/* Increment number of free entries. */
/*-----------------------------------------------------------------*/
++Ram->total_free;
incTblEntries(tmp_ent);
/*-----------------------------------------------------------------*/
/* Do garbage collection if necessary. */
/*-----------------------------------------------------------------*/
if (Ram->total_free >= (FNUM_ENT * 5 / 3))
garbageCollect();
}
/*-------------------------------------------------------------------*/
/* 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 = (RFSEnt *)REMOVED_LINK;
/*-------------------------------------------------------------------*/
/* Do a sync to save new state of file system. */
/*-------------------------------------------------------------------*/
return NULL;
}
/***********************************************************************/
/* 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 RFSEnt *find_new_place(const RFSEnts *smallest)
{
RFSEnts *tbl;
int i;
/*-------------------------------------------------------------------*/
/* Loop over every file table. */
/*-------------------------------------------------------------------*/
for (tbl = Ram->files_tbl; tbl; tbl = tbl->next_tbl)
{
/*-----------------------------------------------------------------*/
/* Check if table is not one 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 = pointer to old entry */
/* new = pointer to new entry */
/* */
/***********************************************************************/
static void update_entries(const RFSEnt *old, RFSEnt *new)
{
RFSEnts *curr_tbl = Ram->files_tbl;
RFSEnt *curr_dir;
RDIR_T *dir;
RFIL_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)
dir->next = new;
else if (dir->prev == old)
dir->prev = new;
else if (dir->parent_dir == old)
dir->parent_dir = new;
else if (dir->first == old)
dir->first = new;
else if (dir->comm->addr == old)
{
new->entry.comm.addr = new;
dir->comm = &(new->entry.comm);
}
}
/*-----------------------------------------------------------------*/
/* Else if entry is link, look at next, prev, 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)
link_ptr->next = new;
else if (link_ptr->prev == old)
link_ptr->prev = new;
else if (link_ptr->comm->addr == old)
{
new->entry.comm.addr = new;
link_ptr->comm = &(new->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. */
/*-------------------------------------------------------------------*/
for (i = 0; i < FOPEN_MAX; ++i)
if (Files[i].handle == old)
Files[i].handle = new;
/*-------------------------------------------------------------------*/
/* Finally, if FlashCurrDir is the same as old, update it. */
/*-------------------------------------------------------------------*/
FsReadCWD(&dummy, (void *)&curr_dir);
if (curr_dir == old)
FsSaveCWD((ui32)Ram, (ui32)new);
}
/***********************************************************************/
/* garbageCollect: Remove table with most free entries */
/* */
/***********************************************************************/
static void garbageCollect(void)
{
int i, max_free = 0;
RFSEnt *entry;
RFSEnts *table = NULL, *curr_tbl;
/*-------------------------------------------------------------------*/
/* Skip if any opendir() has unmatched closedir(). */
/*-------------------------------------------------------------------*/
if (Ram->opendirs)
return;
/*-------------------------------------------------------------------*/
/* Walk thru all tables except the first one, finding the one with */
/* most free entries. */
/*-------------------------------------------------------------------*/
for (curr_tbl = Ram->files_tbl->next_tbl; curr_tbl;
curr_tbl = curr_tbl->next_tbl)
{
/*-----------------------------------------------------------------*/
/* Remember table with most free entries. */
/*-----------------------------------------------------------------*/
if (curr_tbl->free > max_free)
{
table = curr_tbl;
max_free = curr_tbl->free;
}
}
/*-------------------------------------------------------------------*/
/* Loop until all entries on this table are free. */
/*-------------------------------------------------------------------*/
while (table)
{
/*-----------------------------------------------------------------*/
/* Check if table is now empty. */
/*-----------------------------------------------------------------*/
if (table->free == FNUM_ENT)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -