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

📄 fsioctl.c

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