📄 rsioctl.c
字号:
/***********************************************************************/
/* */
/* Module: rsioctl.c */
/* Release: 2004.5 */
/* Version: 2005.0 */
/* Purpose: Implements RAM file system ioctl() */
/* */
/*---------------------------------------------------------------------*/
/* */
/* Copyright 2005, 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 "ramfsp.h"
#if NUM_RFS_VOLS
/***********************************************************************/
/* Symbol Definitions */
/***********************************************************************/
#define F_ONLY 0
#define F_AND_D 1
/***********************************************************************/
/* Function Prototypes */
/***********************************************************************/
static void garbageCollect(void);
/***********************************************************************/
/* Local Function Definitions */
/***********************************************************************/
/***********************************************************************/
/* incTblEntries: Increment the number of free entries */
/* */
/* Input: entry = pointer to freed table entry */
/* */
/***********************************************************************/
static void incTblEntries(const RFSEnt *entry)
{
RFSEnts *table;
/*-------------------------------------------------------------------*/
/* Look for table that contains the freed entry. */
/*-------------------------------------------------------------------*/
for (table = Ram->files_tbl; table; table = table->next_tbl)
{
/*-----------------------------------------------------------------*/
/* If found table with entry, increment number of free entries. */
/*-----------------------------------------------------------------*/
if (entry >= &table->tbl[0] && entry <= &table->tbl[FNUM_ENT - 1])
{
++table->free;
break;
}
}
/*-------------------------------------------------------------------*/
/* Ensure that the table was found. */
/*-------------------------------------------------------------------*/
PfAssert(table);
}
/***********************************************************************/
/* find_file: Look for a file with name path in dir */
/* */
/* Inputs: dir = parent directory to look into */
/* path = file name */
/* mode = permissions directory must have */
/* entry = place to store found file */
/* search_flag = look for file only/ file and dir */
/* */
/* Returns: -1 if error in searching, 0 otherwise(entry will have */
/* either pointer to found file or NULL otherwise) */
/* */
/***********************************************************************/
static int find_file(const RDIR_T *dir, const char *path, int mode,
RFSEnt **entry, int search_flag)
{
/*-------------------------------------------------------------------*/
/* If path ends in '/', return error (it's not a file). */
/*-------------------------------------------------------------------*/
if (path[strlen(path) - 1] == '/')
{
set_errno(EINVAL);
return -1;
}
/*-------------------------------------------------------------------*/
/* Check that parent directory has permissions. */
/*-------------------------------------------------------------------*/
if (CheckPerm((void *)dir->comm, mode))
return -1;
/*-------------------------------------------------------------------*/
/* Look for file in its parent directory. */
/*-------------------------------------------------------------------*/
for (*entry = dir->first; *entry; *entry = (*entry)->entry.dir.next)
{
/*-----------------------------------------------------------------*/
/* Check if entry's name matches our file's name. */
/*-----------------------------------------------------------------*/
if (!strncmp((*entry)->entry.dir.name, path, FILENAME_MAX))
{
/*---------------------------------------------------------------*/
/* Error if looking for regular file and this is a directory. */
/*---------------------------------------------------------------*/
if (search_flag == F_ONLY && (*entry)->type != FFILEN)
{
set_errno(EISDIR);
return -1;
}
break;
}
}
return 0;
}
/***********************************************************************/
/* 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)
{
ui32 num_sects, i;
/*-------------------------------------------------------------------*/
/* If seek goes past start sector, subtract starting position from */
/* offset. */
/*-------------------------------------------------------------------*/
if (offset > (RAM_SECT_SZ - start_pos.offset))
offset -= (RAM_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 = (ui32)((RamSect *)start_pos.sector)->next;
/*-------------------------------------------------------------------*/
/* Figure out how many sectors we have to go up. */
/*-------------------------------------------------------------------*/
num_sects = (ui32)offset / RAM_SECT_SZ;
start_pos.offset = (ui32)offset % RAM_SECT_SZ;
/*-------------------------------------------------------------------*/
/* Step through to the desired num_sects. */
/*-------------------------------------------------------------------*/
for (i = 0; i < num_sects; ++i)
start_pos.sector = (ui32)((RamSect *)start_pos.sector)->next;
start_pos.sect_off += num_sects;
/*-------------------------------------------------------------------*/
/* Update curr_ptr and return success. */
/*-------------------------------------------------------------------*/
stream->curr_ptr = start_pos;
return NULL;
}
/***********************************************************************/
/* 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;
/*-------------------------------------------------------------------*/
/* Get valid position from old_ptr. */
/*-------------------------------------------------------------------*/
old_pos = (i32)stream->old_ptr.sect_off * RAM_SECT_SZ +
stream->old_ptr.offset;
/*-------------------------------------------------------------------*/
/* 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 =
(ui32)((RFSEnt *)stream->handle)->entry.file.comm->frst_sect;
beg_ptr.offset = 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) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -