📄 fsioctl.c
字号:
buf->st_atime = (time_t)link_ptr->comm->ac_time;
buf->st_mtime = (time_t)link_ptr->comm->mod_time;
}
/***********************************************************************/
/* seek_within_file: Help function for FSEEK (steps through file) */
/* */
/* Inputs: stream = pointer to file control block */
/* offset = new seek location */
/* curr_pos = current position within file */
/* */
/* Returns: NULL on success, (void*)-1 on error */
/* */
/***********************************************************************/
static void *seek_within_file(FILE *stream, i32 offset, i32 curr_pos)
{
i32 old_pos;
fpos_t beg_ptr;
void *vp;
/*-------------------------------------------------------------------*/
/* If stream has a cached entry, free it. */
/*-------------------------------------------------------------------*/
if (stream->cached && FreeSector(&stream->cached, &Flash->cache))
return (void *)-1;
/*-------------------------------------------------------------------*/
/* Get valid position from old_ptr or set it to the end of the file. */
/*-------------------------------------------------------------------*/
if (stream->old_ptr.sector != (ui16)-1)
old_pos = (i32)(stream->old_ptr.sect_off * Flash->sect_sz +
stream->old_ptr.offset);
else
old_pos = (i32)((FFSEnt *)stream->handle)->entry.file.comm->size;
/*-------------------------------------------------------------------*/
/* Choose among curr_pos, old_pos, or beginning of file, whichever */
/* is closer to where we want to get. The only time when beginning */
/* of file is better than the other two is when both curr and old */
/* position are beyond where we want to seek. */
/*-------------------------------------------------------------------*/
if (curr_pos > offset && old_pos > offset)
{
beg_ptr.sector =
((FFSEnt *)stream->handle)->entry.file.comm->frst_sect;
beg_ptr.offset = 0;
beg_ptr.sect_off = 0;
return seek_up(offset, stream, beg_ptr);
}
/*-------------------------------------------------------------------*/
/* Else choose between old_pos and curr_pos and seek from there up */
/* to the right spot. */
/*-------------------------------------------------------------------*/
else
{
/*-----------------------------------------------------------------*/
/* If old_pos is past location, use curr_pos. */
/*-----------------------------------------------------------------*/
if (old_pos > offset)
{
/*---------------------------------------------------------------*/
/* Adjust offset by subtracting curr_pos from it. */
/*---------------------------------------------------------------*/
offset -= curr_pos;
beg_ptr = stream->curr_ptr;
vp = seek_up(offset, stream, stream->curr_ptr);
stream->old_ptr = beg_ptr;
return vp;
}
/*-----------------------------------------------------------------*/
/* Else if curr_pos is past location, use old_pos. */
/*-----------------------------------------------------------------*/
else if (curr_pos > offset)
{
/*---------------------------------------------------------------*/
/* Adjust offset by subtracting old_pos from it. */
/*---------------------------------------------------------------*/
offset -= old_pos;
return seek_up(offset, stream, stream->old_ptr);
}
/*-----------------------------------------------------------------*/
/* Else choose the one that's closest. */
/*-----------------------------------------------------------------*/
else
{
/*---------------------------------------------------------------*/
/* Use whichever is bigger between curr_pos and old_pos. */
/*---------------------------------------------------------------*/
if (old_pos > curr_pos)
{
/*-------------------------------------------------------------*/
/* Adjust offset by subtracting old position from it. */
/*-------------------------------------------------------------*/
offset -= old_pos;
return seek_up(offset, stream, stream->old_ptr);
}
else
{
/*-------------------------------------------------------------*/
/* Adjust offset by subtracting curr position from it. */
/*-------------------------------------------------------------*/
offset -= curr_pos;
beg_ptr = stream->curr_ptr;
vp = seek_up(offset, stream, stream->curr_ptr);
stream->old_ptr = beg_ptr;
return vp;
}
}
}
}
/***********************************************************************/
/* seek_past_end: Adjust file position past EOF */
/* */
/* Inputs: offset = length of fseek in bytes */
/* stream = pointer to file control block (FILE) */
/* */
/* Returns: NULL on success, (void *)-1 on error */
/* */
/***********************************************************************/
static void *seek_past_end(i32 offset, FILE *stream)
{
FFIL_T *link_ptr = &((FFSEnt *)stream->handle)->entry.file;
FCOM_T *file = link_ptr->comm;
/*-------------------------------------------------------------------*/
/* Files created by creatn() cannot seek past end. */
/*-------------------------------------------------------------------*/
if (offset && (link_ptr->comm->mode & S_CREATN))
{
set_errno(EINVAL);
return (void *)-1;
}
/*-------------------------------------------------------------------*/
/* If stream has a cached entry, free it. */
/*-------------------------------------------------------------------*/
if (stream->cached && FreeSector(&stream->cached, &Flash->cache))
return (void *)-1;
/*-------------------------------------------------------------------*/
/* If offset is zero, set current pointer to EOF. */
/*-------------------------------------------------------------------*/
if (offset == 0)
FlashPoint2End(&stream->curr_ptr, file);
/*-------------------------------------------------------------------*/
/* Else set current pointer past the EOF. */
/*-------------------------------------------------------------------*/
else
{
/*-----------------------------------------------------------------*/
/* Current sector will be invalid since we're past EOF. */
/*-----------------------------------------------------------------*/
stream->curr_ptr.sector = FDRTY_SECT;
/*-----------------------------------------------------------------*/
/* Position is given by sect_off and offset. */
/*-----------------------------------------------------------------*/
stream->curr_ptr.sect_off = (file->size + offset) / Flash->sect_sz;
stream->curr_ptr.offset = (ui16)((file->size + offset) %
Flash->sect_sz);
}
return NULL;
}
/***********************************************************************/
/* seek_up: Helper function for FSEEK */
/* */
/* Inputs: offset = length of fseek in bytes */
/* stream = pointer to file control block (FILE) */
/* start_pos = start position (beginning, curr, or old) */
/* */
/* Returns: NULL on success, (void *)-1 on error */
/* */
/***********************************************************************/
static void *seek_up(i32 offset, FILE *stream, fpos_t start_pos)
{
FCOM_T *file = ((FFSEnt *)stream->handle)->entry.file.comm;
ui32 num_sects, i;
/*-------------------------------------------------------------------*/
/* If seek goes past start sector, subtract starting position from */
/* offset. */
/*-------------------------------------------------------------------*/
if (offset > (Flash->sect_sz - start_pos.offset))
offset -= (Flash->sect_sz - start_pos.offset);
/*-------------------------------------------------------------------*/
/* Else adjust offset and return. */
/*-------------------------------------------------------------------*/
else
{
start_pos.offset += (ui16)offset;
stream->curr_ptr = start_pos;
return NULL;
}
/*-------------------------------------------------------------------*/
/* Move to the next sector in file. */
/*-------------------------------------------------------------------*/
++start_pos.sect_off;
start_pos.sector = Flash->sect_tbl[start_pos.sector].next;
/*-------------------------------------------------------------------*/
/* Figure out how many sectors we have to go up. */
/*-------------------------------------------------------------------*/
num_sects = (ui32)offset / Flash->sect_sz;
start_pos.offset = (ui16)((ui32)offset % Flash->sect_sz);
/*-------------------------------------------------------------------*/
/* Step through to the desired num_sects. */
/*-------------------------------------------------------------------*/
for (i = 0; i < num_sects; ++i)
start_pos.sector = Flash->sect_tbl[start_pos.sector].next;
start_pos.sect_off += num_sects;
/*-------------------------------------------------------------------*/
/* If this was the last sector, we're at the end of the file, but */
/* not past it. */
/*-------------------------------------------------------------------*/
if (start_pos.sector == FLAST_SECT)
FlashPoint2End(&start_pos, file);
/*-------------------------------------------------------------------*/
/* Update curr_ptr and return success. */
/*-------------------------------------------------------------------*/
stream->curr_ptr = start_pos;
return NULL;
}
/***********************************************************************/
/* 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;
FFSEnts *curr_tbl;
/*-------------------------------------------------------------------*/
/* Go through all mounted volumes. */
/*-------------------------------------------------------------------*/
for (i = 0; i < NUM_FFS_VOLS; ++i)
{
/*-----------------------------------------------------------------*/
/* If this volume is mounted, check all its entries for name dup. */
/*-----------------------------------------------------------------*/
if (MountedList.head == &FlashGlobals[i].sys ||
FlashGlobals[i].sys.prev || FlashGlobals[i].sys.next)
{
/*---------------------------------------------------------------*/
/* Acquire exclusive access to the flash file system. */
/*---------------------------------------------------------------*/
semPend(FlashSem, WAIT_FOREVER);
/*---------------------------------------------------------------*/
/* Go through each table in volume. */
/*---------------------------------------------------------------*/
for (curr_tbl = FlashGlobals[i].files_tbl; curr_tbl;
curr_tbl = curr_tbl->next_tbl)
{
/*-------------------------------------------------------------*/
/* Go through all entries in table. */
/*-------------------------------------------------------------*/
for (j = 0; j < FNUM_ENT; ++j)
{
/*-----------------------------------------------------------*/
/* If entry is a file and names match, stop. */
/*-----------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -