📄 fsioctl.c
字号:
/***********************************************************************/
/* */
/* Module: fsioctl.c */
/* Release: 2004.5 */
/* Version: 2004.16 */
/* Purpose: Implements flash file system ioctl() */
/* */
/*---------------------------------------------------------------------*/
/* */
/* Copyright 2004, Blunk Microsystems */
/* ALL RIGHTS RESERVED */
/* */
/* Licensees have the non-exclusive right to use, modify, or extract */
/* this computer program for software development at a single site. */
/* This program may be resold or disseminated in executable format */
/* only. The source code may not be redistributed or resold. */
/* */
/***********************************************************************/
#include <stddef.h>
#include "flashfsp.h"
#if NUM_FFS_VOLS
/***********************************************************************/
/* Symbol Definitions */
/***********************************************************************/
#define F_ONLY 0
#define F_AND_D 1
/***********************************************************************/
/* Function Prototypes */
/***********************************************************************/
static int check_name(const char *name);
static void *seek_within_file(FILE *stream, i32 offset, i32 curr_pos);
static void *seek_up(i32 offset, FILE *stream, fpos_t ptr);
static int find_file(const FDIR_T *dir, const char *path, int mode,
FFSEnt **entry, int search_flag);
static ui32 unique_fileno(void);
#if FFS_DEBUG
int printf(const char *, ...);
#endif
/***********************************************************************/
/* Local Function Definitions */
/***********************************************************************/
/***********************************************************************/
/* truncatef: Truncate the length of a file to desired length */
/* */
/* Inputs: entry = pointer to file in Flash->files_tbl */
/* length = desired file length */
/* */
/* Returns: NULL on success, (void *)-1 otherwise */
/* */
/***********************************************************************/
static void *truncatef(FFSEnt *entry, off_t length)
{
ui16 sect, last_sect_offset;
ui32 count, num_sects, i;
FFIL_T *lnk = &entry->entry.file;
#if QUOTA_ENABLED
ui32 rmv_sects = 0;
#endif /* QUOTA_ENABLED */
/*-------------------------------------------------------------------*/
/* 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)
FlashTruncZero(lnk, DONT_ADJUST_FCBs);
/*-------------------------------------------------------------------*/
/* Else if actual size smaller than length, append zeroes. */
/*-------------------------------------------------------------------*/
else if (lnk->comm->size < length)
{
FILE fcb, *fcb_ptr;
int append_set = FALSE;
/*-----------------------------------------------------------------*/
/* If file control block associated with file use it, else create */
/* one. */
/*-----------------------------------------------------------------*/
if (lnk->file != NULL)
fcb_ptr = lnk->file;
else
{
fcb_ptr = &fcb;
FsInitFCB(fcb_ptr, FCB_FILE);
fcb_ptr->handle = lnk;
fcb_ptr->curr_ptr.sector = lnk->comm->frst_sect;
fcb_ptr->curr_ptr.offset = 0;
fcb_ptr->curr_ptr.sect_off = 0;
fcb_ptr->old_ptr = fcb_ptr->curr_ptr;
if (!(lnk->comm->open_mode & (F_APPEND | F_WRITE)))
{
lnk->comm->open_mode |= F_APPEND;
append_set = TRUE;
}
}
/*-----------------------------------------------------------------*/
/* Increase file size by desired amount. */
/*-----------------------------------------------------------------*/
if (FlashSeekPastEnd((i32)(length - lnk->comm->size), fcb_ptr,
DONT_ADJUST_FCBs))
return (void *)-1;
/*-----------------------------------------------------------------*/
/* If open mode set here, reset it. */
/*-----------------------------------------------------------------*/
if (append_set)
lnk->comm->open_mode &= ~F_APPEND;
}
/*-------------------------------------------------------------------*/
/* Else actual size is greater than desired size, truncate. */
/*-------------------------------------------------------------------*/
else
{
/*-----------------------------------------------------------------*/
/* Figure out how many sectors still in file and offset of last */
/* sector. */
/*-----------------------------------------------------------------*/
num_sects = (length + Flash->sect_sz - 1) / Flash->sect_sz;
last_sect_offset = length - (num_sects - 1) * Flash->sect_sz;
/*-----------------------------------------------------------------*/
/* Go to last new sector. */
/*-----------------------------------------------------------------*/
sect = lnk->comm->frst_sect;
for (count = 1; count < num_sects; ++count)
sect = Flash->sect_tbl[sect].next;
/*-----------------------------------------------------------------*/
/* Update file's last sector. */
/*-----------------------------------------------------------------*/
lnk->comm->last_sect = sect;
sect = Flash->sect_tbl[sect].next;
/*-----------------------------------------------------------------*/
/* Everything past it becomes dirty. */
/*-----------------------------------------------------------------*/
for (; sect != FLAST_SECT; sect = Flash->sect_tbl[sect].next)
{
/*---------------------------------------------------------------*/
/* First remove sector from cache. */
/*---------------------------------------------------------------*/
RemoveFromCache(&Flash->cache, sect, -1);
/*---------------------------------------------------------------*/
/* Adjust used_sects and blocks table. */
/*---------------------------------------------------------------*/
--Flash->used_sects;
--Flash->blocks[sect / Flash->block_sects].used_sects;
/*---------------------------------------------------------------*/
/* Mark sector as dirty. */
/*---------------------------------------------------------------*/
Flash->sect_tbl[sect].prev = FDRTY_SECT;
/*---------------------------------------------------------------*/
/* Adjust next set of blocks to be erased. */
/*---------------------------------------------------------------*/
if (Flash->sect_tbl[sect].next / Flash->block_sects !=
sect / Flash->block_sects)
FlashAdjustEraseSet(sect / Flash->block_sects);
#if QUOTA_ENABLED
/*---------------------------------------------------------------*/
/* If quotas enabled, count the number of removed sectors. */
/*---------------------------------------------------------------*/
if (Flash->quota_enabled)
++rmv_sects;
#endif /* QUOTA_ENABLED */
}
/*-----------------------------------------------------------------*/
/* Update file's one past last pointer. */
/*-----------------------------------------------------------------*/
Flash->sect_tbl[lnk->comm->last_sect].next = FLAST_SECT;
if (last_sect_offset == Flash->sect_sz)
{
lnk->comm->one_past_last.sector = (ui16)-1;
lnk->comm->one_past_last.offset = 0;
}
else
{
lnk->comm->one_past_last.sector = lnk->comm->last_sect;
lnk->comm->one_past_last.offset = last_sect_offset;
}
/*-----------------------------------------------------------------*/
/* Update file's size. */
/*-----------------------------------------------------------------*/
lnk->comm->size = (num_sects - 1) * Flash->sect_sz +
last_sect_offset;
/*-----------------------------------------------------------------*/
/* If there are any file descriptors for which curr_ptr/old_ptr */
/* need to be updated because of the truncation, update them. */
/*-----------------------------------------------------------------*/
for (i = 0; i < FOPEN_MAX; ++i)
if (Files[i].handle == lnk && Files[i].ioctl == FlashIoctl)
{
/*-------------------------------------------------------------*/
/* If curr_ptr points passed the new EOF, update it. */
/*-------------------------------------------------------------*/
if (Files[i].curr_ptr.sector != FDRTY_SECT &&
(Files[i].curr_ptr.sect_off >= num_sects ||
(Files[i].curr_ptr.sect_off == num_sects - 1 &&
Files[i].curr_ptr.offset > last_sect_offset)))
{
Files[i].curr_ptr.sector = FDRTY_SECT;
Files[i].cached = NULL;
}
/*-------------------------------------------------------------*/
/* If old_ptr points passed the new EOF, update it. */
/*-------------------------------------------------------------*/
if (Files[i].old_ptr.sector != FDRTY_SECT &&
(Files[i].old_ptr.sect_off >= num_sects ||
(Files[i].old_ptr.sect_off == num_sects - 1 &&
Files[i].old_ptr.offset > last_sect_offset)))
Files[i].old_ptr.sector = FDRTY_SECT;
}
}
/*-------------------------------------------------------------------*/
/* Update file access and modified times. */
/*-------------------------------------------------------------------*/
lnk->comm->ac_time = lnk->comm->mod_time = OsSecCount;
#if QUOTA_ENABLED
/*-------------------------------------------------------------------*/
/* If quotas enabled, adjust quota values due to file truncation. */
/*-------------------------------------------------------------------*/
if (Flash->quota_enabled)
{
FFSEnt *ent, *root = &Flash->files_tbl->tbl[0];
/*-----------------------------------------------------------------*/
/* Update used from parent to root. */
/*-----------------------------------------------------------------*/
for (ent = lnk->parent_dir; ent; ent = ent->entry.dir.parent_dir)
{
PfAssert(ent->type == FDIREN &&
ent->entry.dir.used >= rmv_sects * Flash->sect_sz);
ent->entry.dir.used -= rmv_sects * Flash->sect_sz;
}
/*-----------------------------------------------------------------*/
/* Update free below. */
/*-----------------------------------------------------------------*/
FlashFreeBelow(root);
/*-----------------------------------------------------------------*/
/* Recompute free at each node. */
/*-----------------------------------------------------------------*/
FlashFree(root, root->entry.dir.max_q - FlashVirtUsed(root));
}
#endif /* QUOTA_ENABLED */
return NULL;
}
/***********************************************************************/
/* remove_dir: Helper function to remove dir */
/* */
/* Input: dir_ent = directory to be removed */
/* */
/* Returns: NULL on success, (void *)-1 on error */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -