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

📄 fsioctl.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:

#if QUOTA_ENABLED
    /*-----------------------------------------------------------------*/
    /* If volume has quotas, remember link used space.                 */
    /*-----------------------------------------------------------------*/
    if (Flash->quota_enabled)
      used += (strlen(link_ptr->name) + 1 + OFFIL_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 an open dir structure has pointer to this entry, update it.    */
  /*-------------------------------------------------------------------*/
  for (i = 0; i < DIROPEN_MAX; ++i)
    if (Files[i].ioctl == FlashIoctl && Files[i].pos == tmp_ent)
      Files[i].pos = link_ptr->prev;

  /*-------------------------------------------------------------------*/
  /* Remove the directory link, keeping directory structure.           */
  /*-------------------------------------------------------------------*/
  if (link_ptr->prev)
    link_ptr->prev->entry.dir.next = link_ptr->next;
  else
    dir->first = link_ptr->next;
  if (link_ptr->next)
    link_ptr->next->entry.dir.prev = link_ptr->prev;

  /*-------------------------------------------------------------------*/
  /* Check if the file is to be removed.                               */
  /*-------------------------------------------------------------------*/
  if (rmv_file)
  {
    /*-----------------------------------------------------------------*/
    /* Clear comm ptr, set next and prev to NULL, and mark type empty. */
    /*-----------------------------------------------------------------*/
    link_ptr->comm = NULL;
    link_ptr->next = link_ptr->prev = NULL;
    tmp_ent->type = FEMPTY;

    /*-----------------------------------------------------------------*/
    /* Increment number of free entries.                               */
    /*-----------------------------------------------------------------*/
    ++Flash->total_free;
    FlashIncrementTblEntries(tmp_ent);
    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 += OFCOM_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();
  }

  /*-------------------------------------------------------------------*/
  /* Else don't free the entry yet. Free it when the last open file    */
  /* descriptor for this link is closed. For now, just set next and    */
  /* prev to REMOVED_LINK.                                             */
  /*-------------------------------------------------------------------*/
  else
    link_ptr->next = link_ptr->prev = (FFSEnt *)REMOVED_LINK;

  /*-------------------------------------------------------------------*/
  /* Do a sync to save new state of file system.                       */
  /*-------------------------------------------------------------------*/
  return FlashSync(Flash->do_sync);
}

/***********************************************************************/
/*   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 FDIR_T *dir, const char *path, int mode,
                     FFSEnt **entry, int search_flag)
{
  /*-------------------------------------------------------------------*/
  /* If path ends in '/', return error (it's not a file), else look if */
  /* file exists.                                                      */
  /*-------------------------------------------------------------------*/
  if (path[strlen(path) - 1] == '/')
  {
    set_errno(EINVAL);
    return -1;
  }

  /*-------------------------------------------------------------------*/
  /* Check that parent directory has permissions.                      */
  /*-------------------------------------------------------------------*/
  if (CheckPerm(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 (!strcmp((*entry)->entry.dir.name, path))
    {
      /*---------------------------------------------------------------*/
      /* 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;
}

/***********************************************************************/
/* find_new_place: Find a free entry from among the list of tables     */
/*                                                                     */
/*       Input: smallest = ptr to table to be removed                  */
/*                                                                     */
/*     Returns: pointer to found entry or NULL if no entry was found   */
/*                                                                     */
/***********************************************************************/
static FFSEnt *find_new_place(const FFSEnts *smallest)
{
  int i;
  FFSEnts *tbl;

  /*-------------------------------------------------------------------*/
  /* Loop over every file table.                                       */
  /*-------------------------------------------------------------------*/
  for (tbl = Flash->files_tbl; tbl; tbl = tbl->next_tbl)
  {
    /*-----------------------------------------------------------------*/
    /* Check if table is not being removed and has a free entry.       */
    /*-----------------------------------------------------------------*/
    if ((tbl != smallest) && tbl->free)
    {
      /*---------------------------------------------------------------*/
      /* Decrease free entry count and return pointer to free entry.   */
      /*---------------------------------------------------------------*/
      --tbl->free;
      for (i = 0;; ++i)
      {
        PfAssert(i < FNUM_ENT);
        if (tbl->tbl[i].type == FEMPTY)
          return &tbl->tbl[i];
      }
    }
  }

  /*-------------------------------------------------------------------*/
  /* No free entries were found.                                       */
  /*-------------------------------------------------------------------*/
  return NULL;
}

/***********************************************************************/
/* update_entries: Go through all non-empty entries, and for entry     */
/*                 pointing to old entry, update it to the new entry   */
/*                                                                     */
/*      Inputs: old_ent = pointer to old entry                         */
/*              new_ent = pointer to new entry                         */
/*                                                                     */
/***********************************************************************/
static void update_entries(const FFSEnt *old_ent, FFSEnt *new_ent)
{
  FFSEnts *curr_tbl = Flash->files_tbl;
  FFSEnt *curr_dir;
  FDIR_T *dir;
  FFIL_T *link_ptr;
  int     i;
  ui32   dummy;

  for (i = 0; curr_tbl; ++i)
  {
    /*-----------------------------------------------------------------*/
    /* If entry is a directory, look at next, prev, parent, first, and */
    /* actual file to see if any is equal to the old entry.            */
    /*-----------------------------------------------------------------*/
    if (curr_tbl->tbl[i].type == FDIREN)
    {
      dir = &(curr_tbl->tbl[i].entry.dir);
      if (dir->next == old_ent)
        dir->next = new_ent;
      else if (dir->prev == old_ent)
        dir->prev = new_ent;
      else if (dir->parent_dir == old_ent)
        dir->parent_dir = new_ent;
      else if (dir->first == old_ent)
        dir->first = new_ent;
      else if (dir->comm->addr == old_ent)
      {
        new_ent->entry.comm.addr = new_ent;
        dir->comm = &(new_ent->entry.comm);
      }
    }

    /*-----------------------------------------------------------------*/
    /* Else if entry is link, look at next, prev, parent and the actual*/
    /* file to see if any is equal to the old entry.                   */
    /*-----------------------------------------------------------------*/
    else if (curr_tbl->tbl[i].type == FFILEN)
    {
      link_ptr = &(curr_tbl->tbl[i].entry.file);
      if (link_ptr->next == old_ent)
        link_ptr->next = new_ent;
      else if (link_ptr->prev == old_ent)
        link_ptr->prev = new_ent;
      else if (link_ptr->parent_dir == old_ent)
        link_ptr->parent_dir = new_ent;
      else if (link_ptr->comm->addr == old_ent)
      {
        new_ent->entry.comm.addr = new_ent;
        link_ptr->comm = &(new_ent->entry.comm);
      }
    }

    /*-----------------------------------------------------------------*/
    /* If we are at the end of the current table, go to the next one.  */
    /*-----------------------------------------------------------------*/
    if (i == (FNUM_ENT - 1))
    {
      i = -1;
      curr_tbl = curr_tbl->next_tbl;
    }
  }

  /*-------------------------------------------------------------------*/
  /* Adjust all the open streams handles if necessary.                 */
  /*-------------------------------------------------------------------*/

⌨️ 快捷键说明

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