📄 fsioctl.c
字号:
for (i = 0; i < FOPEN_MAX; ++i)
if (Files[i].handle == old_ent)
Files[i].handle = new_ent;
/*-------------------------------------------------------------------*/
/* Adjust all file_ptrs in the cache entries that point to old. */
/*-------------------------------------------------------------------*/
UpdateFilePtrs(&Flash->cache, old_ent, new_ent);
/*-------------------------------------------------------------------*/
/* Finally, if current directory is the same as old, update it. */
/*-------------------------------------------------------------------*/
FsReadCWD(&dummy, (void *)&curr_dir);
if (curr_dir == old_ent)
FsSaveCWD((ui32)Flash, (ui32)new_ent);
}
/***********************************************************************/
/* close_dir: Close a directory */
/* */
/* Inputs: entry = pointer to dir entry in files table */
/* stream = pointer to dir control block */
/* */
/***********************************************************************/
static void close_dir(FFSEnt *entry, const FILE *stream)
{
FDIR_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 == FlashIoctl &&
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: 0 on success, -1 on error */
/* */
/***********************************************************************/
static int close_file(FFSEnt *entry, FILE *stream)
{
FFIL_T *link_ptr = &entry->entry.file;
int i;
#if QUOTA_ENABLED
ui32 used = 0;
#endif /* QUOTA_ENABLED */
/*-------------------------------------------------------------------*/
/* Free the current sector, if it's not free already. */
/*-------------------------------------------------------------------*/
if (stream->cached && FreeSector(&stream->cached, &Flash->cache))
return -1;
/*-------------------------------------------------------------------*/
/* Free the file control block associated with this file. */
/*-------------------------------------------------------------------*/
stream->read = NULL;
stream->write = NULL;
stream->ioctl = NULL;
stream->volume = NULL;
stream->curr_ptr.sector = (ui16)-1;
stream->curr_ptr.offset = 0;
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 the number of links to this file is 0, need to remove the */
/* contents of the file. */
/*-----------------------------------------------------------------*/
if (link_ptr->comm->links == 0)
{
/*---------------------------------------------------------------*/
/* A previous remove() must have been issued for this file. */
/*---------------------------------------------------------------*/
PfAssert(link_ptr->next == (FFSEnt *)REMOVED_LINK &&
link_ptr->prev == (FFSEnt *)REMOVED_LINK);
/*---------------------------------------------------------------*/
/* Truncate file size to zero. */
/*---------------------------------------------------------------*/
FlashTruncZero(link_ptr, ADJUST_FCBs);
#if QUOTA_ENABLED
/*---------------------------------------------------------------*/
/* If volume has quotas, remember link used space. */
/*---------------------------------------------------------------*/
if (Flash->quota_enabled)
used += OFCOM_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 entry has next and prev set to REMOVED_LINK, free it. */
/*-----------------------------------------------------------------*/
if (link_ptr->next == (FFSEnt *)REMOVED_LINK &&
link_ptr->prev == (FFSEnt *)REMOVED_LINK)
{
/*---------------------------------------------------------------*/
/* Clear struct fields. */
/*---------------------------------------------------------------*/
link_ptr->comm = NULL;
link_ptr->next = link_ptr->prev = NULL;
entry->type = FEMPTY;
/*---------------------------------------------------------------*/
/* Increment number of free entries. */
/*---------------------------------------------------------------*/
++Flash->total_free;
FlashIncrementTblEntries(entry);
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 += (strlen(link_ptr->name) + 1 + OFFIL_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();
return 0;
}
}
/*-------------------------------------------------------------------*/
/* 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 == FlashIoctl &&
Files[i].flags & FCB_FILE);
link_ptr->file = &Files[i];
break;
}
PfAssert(i < FOPEN_MAX);
}
return 0;
}
/***********************************************************************/
/* 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, FFSEnt *entry)
{
FFIL_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 = (off_t)link_ptr->comm->size;
else
buf->st_size = 0;
/*-------------------------------------------------------------------*/
/* Look at the access and modification times. */
/*-------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -