📄 rsioctl.c
字号:
PfAssert(Ram->files_tbl != table);
/*---------------------------------------------------------------*/
/* Remove and free table. Update counters, and then return. */
/*---------------------------------------------------------------*/
if (table->prev_tbl)
table->prev_tbl->next_tbl = table->next_tbl;
if (table->next_tbl)
table->next_tbl->prev_tbl = table->prev_tbl;
table->next_tbl = table->prev_tbl = NULL;
free(table);
Ram->total_free -= FNUM_ENT;
return;
}
/*-----------------------------------------------------------------*/
/* Look for the next non-empty entry in the table to be moved. */
/*-----------------------------------------------------------------*/
for (i = 0; i < FNUM_ENT; ++i)
{
if (table->tbl[i].type != FEMPTY)
{
/*-------------------------------------------------------------*/
/* Find a place for the non-empty entry to be moved to. */
/*-------------------------------------------------------------*/
entry = find_new_place(table);
/*-------------------------------------------------------------*/
/* If no more free entries, stop the garbage collection. */
/*-------------------------------------------------------------*/
if (entry == NULL)
return;
/*-------------------------------------------------------------*/
/* Move entry and update all pointers to it. */
/*-------------------------------------------------------------*/
entry->type = table->tbl[i].type;
entry->entry = table->tbl[i].entry;
table->tbl[i].type = FEMPTY;
++table->free;
update_entries(&table->tbl[i], entry);
}
}
}
}
/***********************************************************************/
/* close_dir: Close a directory */
/* */
/* Inputs: entry = pointer to dir entry in files table */
/* stream = pointer to dir control block */
/* */
/***********************************************************************/
static void close_dir(RFSEnt *entry, const FILE *stream)
{
RDIR_T *dir_ptr = &entry->entry.dir;
int i;
/*-------------------------------------------------------------------*/
/* If no more open links, reset. */
/*-------------------------------------------------------------------*/
if (--dir_ptr->comm->open_links == 0)
{
dir_ptr->dir = NULL;
return;
}
/*-------------------------------------------------------------------*/
/* If the dir entry is set to stream on which close was performed, */
/* find another stream opened on the file to replace it. */
/*-------------------------------------------------------------------*/
if (dir_ptr->dir == stream)
{
for (i = 0; i < DIROPEN_MAX; ++i)
if (Files[i].handle == dir_ptr && stream != &Files[i])
{
PfAssert(Files[i].ioctl == RamIoctl &&
Files[i].flags & FCB_DIR);
dir_ptr->dir = &Files[i];
}
}
}
/***********************************************************************/
/* close_file: Close a file */
/* */
/* Inputs: entry = pointer to file entry in files table */
/* stream = pointer to file control block */
/* */
/* Returns: NULL on success, (void *)-1 on error */
/* */
/***********************************************************************/
static void *close_file(RFSEnt *entry, FILE *stream)
{
RFIL_T *link_ptr = &entry->entry.file;
int i;
/*-------------------------------------------------------------------*/
/* Free the file control block associated with this file. */
/*-------------------------------------------------------------------*/
stream->read = NULL;
stream->write = NULL;
stream->curr_ptr.sector = (ui16)-1;
stream->curr_ptr.offset = stream->curr_ptr.sect_off = 0;
/*-------------------------------------------------------------------*/
/* If it is the last link open, reset the file mode and check for */
/* removal as well. */
/*-------------------------------------------------------------------*/
if (--link_ptr->comm->open_links == 0)
{
/*-----------------------------------------------------------------*/
/* Clear the open_mode and the stream associated with file. */
/*-----------------------------------------------------------------*/
link_ptr->comm->open_mode = 0;
link_ptr->file = NULL;
/*-----------------------------------------------------------------*/
/* If it's a temporary file, remove it without any checking. */
/*-----------------------------------------------------------------*/
if (link_ptr->comm->temp)
{
if (remove_file(entry->entry.file.parent_dir,
entry->entry.file.name))
return (void *)-1;
}
/*-----------------------------------------------------------------*/
/* If the number of links to this file is 0 need to remove the */
/* contents of the file as well. */
/*-----------------------------------------------------------------*/
else if (link_ptr->comm->links == 0)
{
/*---------------------------------------------------------------*/
/* 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 the file entry was previously removed, clear it. */
/*-----------------------------------------------------------------*/
if (link_ptr->next == (RFSEnt *)REMOVED_LINK &&
link_ptr->prev == (RFSEnt *)REMOVED_LINK)
{
/*---------------------------------------------------------------*/
/* Clear struct fields. */
/*---------------------------------------------------------------*/
link_ptr->comm = NULL;
link_ptr->next = link_ptr->prev = NULL;
link_ptr->file = NULL;
entry->type = FEMPTY;
/*---------------------------------------------------------------*/
/* Increment number of free entries. */
/*---------------------------------------------------------------*/
++Ram->total_free;
incTblEntries(entry);
/*---------------------------------------------------------------*/
/* Do garbage collection if necessary. */
/*---------------------------------------------------------------*/
if (Ram->total_free >= (FNUM_ENT * 5 / 3))
garbageCollect();
}
}
/*-------------------------------------------------------------------*/
/* Else, if we are closing a stream opened in write mode, clear the */
/* write option from the mode. */
/*-------------------------------------------------------------------*/
else if ((link_ptr->file == stream) &&
(link_ptr->comm->open_mode & (F_APPEND | F_WRITE)))
link_ptr->comm->open_mode &= ~(F_APPEND | F_WRITE);
/*-------------------------------------------------------------------*/
/* If the file entry is set to stream on which close was performed, */
/* find another stream opened on the file to replace it. */
/*-------------------------------------------------------------------*/
if (link_ptr->file == stream)
{
for (i = 0; i < FOPEN_MAX; ++i)
if (Files[i].handle == link_ptr && stream != &Files[i])
{
PfAssert(Files[i].ioctl == RamIoctl &&
Files[i].flags & FCB_FILE);
link_ptr->file = &Files[i];
}
}
return NULL;
}
/***********************************************************************/
/* statistics: Auxiliary function for FSTAT and STAT to fill out the */
/* struct stat contents */
/* */
/* Inputs: buf = stat structure to be filled */
/* entry = pointer to the entry for the stat */
/* */
/***********************************************************************/
static void statistics(struct stat *buf, RFSEnt *entry)
{
RFIL_T *link_ptr = &entry->entry.file;
/*-------------------------------------------------------------------*/
/* Look at the mode for the file/dir. Start with the permissions. */
/*-------------------------------------------------------------------*/
buf->st_mode = link_ptr->comm->mode;
/*-------------------------------------------------------------------*/
/* Set the bit corresponding to file/dir according to the entry. */
/*-------------------------------------------------------------------*/
if (entry->type == FDIREN)
buf->st_mode |= S_DIR;
/*-------------------------------------------------------------------*/
/* st_dev is always 0. */
/*-------------------------------------------------------------------*/
buf->st_dev = 0;
/*-------------------------------------------------------------------*/
/* Get the uid and gid (0 if permissions not used). */
/*-------------------------------------------------------------------*/
buf->st_uid = link_ptr->comm->user_id;
buf->st_gid = link_ptr->comm->group_id;
/*-------------------------------------------------------------------*/
/* Look at the serial number for the file/dir. */
/*-------------------------------------------------------------------*/
buf->st_ino = (ino_t)link_ptr->comm->fileno;
/*-------------------------------------------------------------------*/
/* Look at the number of links for the file/dir. */
/*-------------------------------------------------------------------*/
buf->st_nlink = (nlink_t)link_ptr->comm->links;
/*-------------------------------------------------------------------*/
/* Look at the size for the file. For a dir the size is 0. */
/*-------------------------------------------------------------------*/
if (entry->type == FFILEN)
buf->st_size = link_ptr->comm->size;
else
buf->st_size = 0;
/*-------------------------------------------------------------------*/
/* Look at the access and modified times. */
/*-------------------------------------------------------------------*/
buf->st_atime = link_ptr->comm->ac_time;
buf->st_mtime = link_ptr->comm->mod_time;
}
/***********************************************************************/
/* check_name: Search through all entries for name */
/* */
/* Input: name = filename to look for */
/* */
/* Returns: 0 if the name was not found, 1 if it was */
/* */
/***********************************************************************/
static int check_name(const char *name)
{
int i, j;
RFSEnts *curr_tbl;
/*-------------------------------------------------------------------*/
/* Go through all mounted volumes. */
/*-------------------------------------------------------------------*/
for (i = 0; i < NUM_RFS_VOLS; ++i)
{
/*-----------------------------------------------------------------*/
/* If this volume is mounted, check all its entries for name dup. */
/*-----------------------------------------------------------------*/
if (MountedList.head == &RamGlobals[i].sys ||
RamGlobals[i].sys.prev || RamGlobals[i].sys.next)
{
/*---------------------------------------------------------------*/
/* Go through each table in volume. */
/*---------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -