📄 rsioctl.c
字号:
/* */
/***********************************************************************/
static void seek_past_end(i32 offset, FILE *stream)
{
RCOM_T *file = ((RFSEnt *)stream->handle)->entry.file.comm;
/*-------------------------------------------------------------------*/
/* If offset is zero, set current pointer to EOF. */
/*-------------------------------------------------------------------*/
if (offset == 0)
RamPoint2End(&stream->curr_ptr, file);
/*-------------------------------------------------------------------*/
/* Else set current pointer past the EOF. */
/*-------------------------------------------------------------------*/
else
{
/*-----------------------------------------------------------------*/
/* Position is given by sect_off and offset. */
/*-----------------------------------------------------------------*/
stream->curr_ptr.sector = SEEK_PAST_END;
stream->curr_ptr.sect_off = (file->size + offset) / RAM_SECT_SZ;
stream->curr_ptr.offset = (file->size + offset) % RAM_SECT_SZ;
}
}
/***********************************************************************/
/* ram_trunc_zero: Make a file zero length */
/* */
/* Input: entry = pointer to file in files table */
/* */
/***********************************************************************/
static void ram_trunc_zero(const RFIL_T *entry)
{
ui32 i;
/*-------------------------------------------------------------------*/
/* If the file has non-zero length, erase all the bytes. */
/*-------------------------------------------------------------------*/
if (entry->comm->size)
{
/*-----------------------------------------------------------------*/
/* Truncate the file by freeing all of its sectors. */
/*-----------------------------------------------------------------*/
while (entry->comm->last_sect)
RamFreeSect(entry->comm);
entry->comm->size = 0;
/*-----------------------------------------------------------------*/
/* Invalidate curr_ptr for any stream pointing to this file. */
/*-----------------------------------------------------------------*/
for (i = 0; i < FOPEN_MAX; ++i)
{
if (Files[i].ioctl == RamIoctl &&
((RFSEnt *)Files[i].handle)->entry.file.comm == entry->comm)
{
Files[i].curr_ptr.sector = (ui32)NULL;
Files[i].curr_ptr.sect_off = 0;
Files[i].old_ptr.sector = (ui32)NULL;
Files[i].old_ptr.sect_off = 0;
}
}
}
}
/***********************************************************************/
/* truncatef: Truncate the length of a file to desired length */
/* */
/* Inputs: entry = pointer to file in files table */
/* length = desired file length */
/* */
/* Returns: NULL on success, (void *)-1 otherwise */
/* */
/***********************************************************************/
static void *truncatef(RFSEnt *entry, off_t length)
{
ui16 last_sect_offset;
int count, num_sects, i;
RFIL_T *lnk = &entry->entry.file;
RamSect *sect;
/*-------------------------------------------------------------------*/
/* Just return if the actual length equals the desired length. */
/*-------------------------------------------------------------------*/
if (lnk->comm->size == length)
return NULL;
/*-------------------------------------------------------------------*/
/* If length is 0, remove whole data content. */
/*-------------------------------------------------------------------*/
if (length == 0)
ram_trunc_zero(lnk);
/*-------------------------------------------------------------------*/
/* Else if actual size is less then desired size, append. */
/*-------------------------------------------------------------------*/
else if (lnk->comm->size < length)
{
/*-----------------------------------------------------------------*/
/* Add the extra zero-valued bytes to the file. */
/*-----------------------------------------------------------------*/
if (RamSeekPastEnd(length - lnk->comm->size, lnk->file))
return (void *)-1;
}
/*-------------------------------------------------------------------*/
/* Else actual size is greater than desired size, truncate. */
/*-------------------------------------------------------------------*/
else if (lnk->comm->size > length)
{
/*-----------------------------------------------------------------*/
/* Calculate number of remaining sectors and last sector offset. */
/*-----------------------------------------------------------------*/
num_sects = length / RAM_SECT_SZ;
last_sect_offset = length % RAM_SECT_SZ;
if (num_sects && last_sect_offset == 0)
{
--num_sects;
last_sect_offset = RAM_SECT_SZ;
}
/*-----------------------------------------------------------------*/
/* Go to last new sector. */
/*-----------------------------------------------------------------*/
sect = lnk->comm->frst_sect;
for (count = 0; count < num_sects; ++count)
sect = sect->next;
/*-----------------------------------------------------------------*/
/* Remove all sectors from current one to end. */
/*-----------------------------------------------------------------*/
while (lnk->comm->last_sect != sect)
RamFreeSect(lnk->comm);
/*-----------------------------------------------------------------*/
/* Update file's one past last pointer and size. */
/*-----------------------------------------------------------------*/
lnk->comm->one_past_last = last_sect_offset;
lnk->comm->size = num_sects * RAM_SECT_SZ + last_sect_offset;
/*-----------------------------------------------------------------*/
/* Check if any file descriptor need to be updated. */
/*-----------------------------------------------------------------*/
for (i = 0; i < FOPEN_MAX; ++i)
if (Files[i].handle == lnk && Files[i].ioctl == RamIoctl)
{
/*-------------------------------------------------------------*/
/* If curr_ptr is invalid, set it to end of file. */
/*-------------------------------------------------------------*/
if (Files[i].curr_ptr.sector != SEEK_PAST_END &&
(Files[i].curr_ptr.sect_off > num_sects ||
(Files[i].curr_ptr.sect_off == num_sects &&
Files[i].curr_ptr.offset > last_sect_offset)))
Files[i].curr_ptr.sector = SEEK_PAST_END;
/*-------------------------------------------------------------*/
/* If old_ptr is invalid, set it to end of file. */
/*-------------------------------------------------------------*/
if (Files[i].old_ptr.sector != SEEK_PAST_END &&
(Files[i].old_ptr.sect_off > num_sects ||
(Files[i].old_ptr.sect_off == num_sects &&
Files[i].old_ptr.offset > last_sect_offset)))
Files[i].old_ptr.sector = SEEK_PAST_END;
}
}
/*-------------------------------------------------------------------*/
/* Update file access and modified times. Return success. */
/*-------------------------------------------------------------------*/
lnk->comm->ac_time = lnk->comm->mod_time = OsSecCount;
return NULL;
}
/***********************************************************************/
/* remove_dir: Helper function to remove dir */
/* */
/* Input: dir_ent = directory to be removed */
/* */
/* Returns: NULL on success, (void *)-1 on error */
/* */
/***********************************************************************/
static void *remove_dir(RFSEnt *dir_ent)
{
RDIR_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 == &Ram->files_tbl->tbl[0])
{
set_errno(ENOENT);
return (void *)-1;
}
/*-------------------------------------------------------------------*/
/* Check that parent directory has write permissions. */
/*-------------------------------------------------------------------*/
if (CheckPerm((void *)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 == RamIoctl && Files[i].pos == dir_ent)
Files[i].pos = dir->prev;
/*-------------------------------------------------------------------*/
/* Remove the directory from the files table. */
/*-------------------------------------------------------------------*/
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 this was the only link remove the file entry as well. */
/*-------------------------------------------------------------------*/
if (--dir->comm->links == 0)
{
dir->comm->addr->type = FEMPTY;
++Ram->total_free;
incTblEntries(dir->comm->addr);
}
/*-------------------------------------------------------------------*/
/* 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. */
/*-------------------------------------------------------------------*/
++Ram->total_free;
incTblEntries(dir_ent);
/*-------------------------------------------------------------------*/
/* Do garbage collection if necessary. */
/*-------------------------------------------------------------------*/
if (Ram->total_free >= (FNUM_ENT * 5 / 3))
garbageCollect();
return NULL;
}
/***********************************************************************/
/* 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -