⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rsioctl.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/***********************************************************************/
/*                                                                     */
/*   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 + -