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

📄 fsioctl.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  for (i = 0; i < FOPEN_MAX; ++i)
    if (Files[i].handle == old_ent)
      Files[i].handle = new_ent;

  /*-------------------------------------------------------------------*/
  /* Adjust all file_ptrs in the cache entries that point to old.      */
  /*-------------------------------------------------------------------*/
  UpdateFilePtrs(&Flash->cache, old_ent, new_ent);

  /*-------------------------------------------------------------------*/
  /* Finally, if current directory is the same as old, update it.      */
  /*-------------------------------------------------------------------*/
  FsReadCWD(&dummy, (void *)&curr_dir);
  if (curr_dir == old_ent)
    FsSaveCWD((ui32)Flash, (ui32)new_ent);
}

/***********************************************************************/
/*   close_dir: Close a directory                                      */
/*                                                                     */
/*      Inputs: entry  = pointer to dir entry in files table           */
/*              stream = pointer to dir control block                  */
/*                                                                     */
/***********************************************************************/
static void close_dir(FFSEnt *entry, const FILE *stream)
{
  FDIR_T *dir_ptr = &entry->entry.dir;
  int i;

  /*-------------------------------------------------------------------*/
  /* If no more open links, reset.                                     */
  /*-------------------------------------------------------------------*/
  if (--dir_ptr->comm->open_links == 0)
  {
    dir_ptr->dir = NULL;
    return;
  }

  /*-------------------------------------------------------------------*/
  /* If the dir entry is set to stream on which close was performed,   */
  /* find another stream opened on the file to replace it.             */
  /*-------------------------------------------------------------------*/
  if (dir_ptr->dir == stream)
  {
    for (i = 0; i < DIROPEN_MAX; ++i)
      if (Files[i].handle == dir_ptr && stream != &Files[i])
      {
        PfAssert(Files[i].ioctl == FlashIoctl &&
                 Files[i].flags & FCB_DIR);
        dir_ptr->dir = &Files[i];
      }
  }
}

/***********************************************************************/
/*  close_file: Close a file                                           */
/*                                                                     */
/*      Inputs: entry  = pointer to file entry in files table          */
/*              stream = pointer to file control block                 */
/*                                                                     */
/*     Returns: 0 on success, -1 on error                              */
/*                                                                     */
/***********************************************************************/
static int close_file(FFSEnt *entry, FILE *stream)
{
  FFIL_T *link_ptr = &entry->entry.file;
  int     i;

#if QUOTA_ENABLED
  ui32 used = 0;
#endif /* QUOTA_ENABLED */

  /*-------------------------------------------------------------------*/
  /* Free the current sector, if it's not free already.                */
  /*-------------------------------------------------------------------*/
  if (stream->cached && FreeSector(&stream->cached, &Flash->cache))
    return -1;

  /*-------------------------------------------------------------------*/
  /* Free the file control block associated with this file.            */
  /*-------------------------------------------------------------------*/
  stream->read = NULL;
  stream->write = NULL;
  stream->ioctl = NULL;
  stream->volume = NULL;
  stream->curr_ptr.sector = (ui16)-1;
  stream->curr_ptr.offset = 0;
  stream->curr_ptr.sect_off = 0;

  /*-------------------------------------------------------------------*/
  /* If it is the last link open, reset the file mode and check for    */
  /* removal as well.                                                  */
  /*-------------------------------------------------------------------*/
  if (--link_ptr->comm->open_links == 0)
  {
    /*-----------------------------------------------------------------*/
    /* Clear the open_mode and the stream associated with file.        */
    /*-----------------------------------------------------------------*/
    link_ptr->comm->open_mode = 0;
    link_ptr->file = NULL;

    /*-----------------------------------------------------------------*/
    /* If the number of links to this file is 0, need to remove the    */
    /* contents of the file.                                           */
    /*-----------------------------------------------------------------*/
    if (link_ptr->comm->links == 0)
    {
      /*---------------------------------------------------------------*/
      /* A previous remove() must have been issued for this file.      */
      /*---------------------------------------------------------------*/
      PfAssert(link_ptr->next == (FFSEnt *)REMOVED_LINK &&
               link_ptr->prev == (FFSEnt *)REMOVED_LINK);

      /*---------------------------------------------------------------*/
      /* Truncate file size to zero.                                   */
      /*---------------------------------------------------------------*/
      FlashTruncZero(link_ptr, ADJUST_FCBs);

#if QUOTA_ENABLED
      /*---------------------------------------------------------------*/
      /* If volume has quotas, remember link used space.               */
      /*---------------------------------------------------------------*/
      if (Flash->quota_enabled)
        used += OFCOM_SZ;
#endif /* QUOTA_ENABLED */

      /*---------------------------------------------------------------*/
      /* Remove file from the files table and adjust free entries.     */
      /*---------------------------------------------------------------*/
      link_ptr->comm->addr->type = FEMPTY;
      ++Flash->total_free;
      FlashIncrementTblEntries(link_ptr->comm->addr);
      Flash->tbls_size -= OFCOM_SZ;
    }

    /*-----------------------------------------------------------------*/
    /* If entry has next and prev set to REMOVED_LINK, free it.        */
    /*-----------------------------------------------------------------*/
    if (link_ptr->next == (FFSEnt *)REMOVED_LINK &&
        link_ptr->prev == (FFSEnt *)REMOVED_LINK)
    {
      /*---------------------------------------------------------------*/
      /* Clear struct fields.                                          */
      /*---------------------------------------------------------------*/
      link_ptr->comm = NULL;
      link_ptr->next = link_ptr->prev = NULL;
      entry->type = FEMPTY;

      /*---------------------------------------------------------------*/
      /* Increment number of free entries.                             */
      /*---------------------------------------------------------------*/
      ++Flash->total_free;
      FlashIncrementTblEntries(entry);
      Flash->tbls_size -= (OFFIL_SZ + strlen(link_ptr->name) + 1);

#if QUOTA_ENABLED
      /*---------------------------------------------------------------*/
      /* If quota enabled, update quota values due to file removal.    */
      /*---------------------------------------------------------------*/
      if (Flash->quota_enabled)
      {
        FFSEnt *ent, *root = &Flash->files_tbl->tbl[0];
        used += (strlen(link_ptr->name) + 1 + OFFIL_SZ);

        /*-------------------------------------------------------------*/
        /* Update used from parent to root.                            */
        /*-------------------------------------------------------------*/
        for (ent = link_ptr->parent_dir; ent;
             ent = ent->entry.dir.parent_dir)
        {
          PfAssert(ent->type == FDIREN && ent->entry.dir.used >= used);
          ent->entry.dir.used -= used;
        }

        /*-------------------------------------------------------------*/
        /* Update free below.                                          */
        /*-------------------------------------------------------------*/
        FlashFreeBelow(root);

        /*-------------------------------------------------------------*/
        /* Recompute free at each node.                                */
        /*-------------------------------------------------------------*/
        FlashFree(root, root->entry.dir.max_q - FlashVirtUsed(root));
      }
#endif /* QUOTA_ENABLED */

      /*---------------------------------------------------------------*/
      /* Do garbage collection if necessary.                           */
      /*---------------------------------------------------------------*/
      if (Flash->total_free >= (FNUM_ENT * 5 / 3))
        FlashGarbageCollect();

      return 0;
    }
  }

  /*-------------------------------------------------------------------*/
  /* Else, if we are closing a stream opened in write mode, clear the  */
  /* write option from the mode.                                       */
  /*-------------------------------------------------------------------*/
  else if ((link_ptr->file == stream) &&
           (link_ptr->comm->open_mode & (F_APPEND | F_WRITE)))
    link_ptr->comm->open_mode &= ~(F_APPEND | F_WRITE);

  /*-------------------------------------------------------------------*/
  /* If the file entry is set to stream on which close was performed,  */
  /* find another stream opened on the file to replace it.             */
  /*-------------------------------------------------------------------*/
  if (link_ptr->file == stream)
  {
    for (i = 0; i < FOPEN_MAX; ++i)
      if (Files[i].handle == link_ptr && stream != &Files[i])
      {
        PfAssert(Files[i].ioctl == FlashIoctl &&
                 Files[i].flags & FCB_FILE);
        link_ptr->file = &Files[i];
        break;
      }
    PfAssert(i < FOPEN_MAX);
  }

  return 0;
}

/***********************************************************************/
/*  statistics: Auxiliary function for FSTAT and STAT to fill out the  */
/*              struct stat contents                                   */
/*                                                                     */
/*      Inputs: buf = stat structure to be filled                      */
/*              entry = pointer to the entry for the stat              */
/*                                                                     */
/***********************************************************************/
static void statistics(struct stat *buf, FFSEnt *entry)
{
  FFIL_T *link_ptr = &entry->entry.file;

  /*-------------------------------------------------------------------*/
  /* Look at the mode for the file/dir. Start with the permissions.    */
  /*-------------------------------------------------------------------*/
  buf->st_mode = link_ptr->comm->mode;

  /*-------------------------------------------------------------------*/
  /* Set the bit corresponding to file/dir according to the entry.     */
  /*-------------------------------------------------------------------*/
  if (entry->type == FDIREN)
    buf->st_mode |= S_DIR;

  /*-------------------------------------------------------------------*/
  /* st_dev is always 0.                                               */
  /*-------------------------------------------------------------------*/
  buf->st_dev = 0;

  /*-------------------------------------------------------------------*/
  /* Get the uid and gid (0 if permissions not used).                  */
  /*-------------------------------------------------------------------*/
  buf->st_uid = link_ptr->comm->user_id;
  buf->st_gid = link_ptr->comm->group_id;

  /*-------------------------------------------------------------------*/
  /* Look at the serial number for the file/dir.                       */
  /*-------------------------------------------------------------------*/
  buf->st_ino = (ino_t)link_ptr->comm->fileno;

  /*-------------------------------------------------------------------*/
  /* Look at the number of links for the file/dir.                     */
  /*-------------------------------------------------------------------*/
  buf->st_nlink = (nlink_t)link_ptr->comm->links;

  /*-------------------------------------------------------------------*/
  /* Look at the size for the file. For a dir the size is 0.           */
  /*-------------------------------------------------------------------*/
  if (entry->type == FFILEN)
    buf->st_size = (off_t)link_ptr->comm->size;
  else
    buf->st_size = 0;

  /*-------------------------------------------------------------------*/
  /* Look at the access and modification times.                        */
  /*-------------------------------------------------------------------*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -