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

📄 fsioctl.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*                                                                     */
/***********************************************************************/
static void *remove_dir(FFSEnt *dir_ent)
{
  FDIR_T *dir = &dir_ent->entry.dir;
  uid_t uid;
  gid_t gid;
  uint i;

  /*-------------------------------------------------------------------*/
  /* If we're trying to delete the root directory, return error.       */
  /*-------------------------------------------------------------------*/
  if (dir_ent == &Flash->files_tbl->tbl[0])
  {
    set_errno(ENOENT);
    return (void *)-1;
  }

  /*-------------------------------------------------------------------*/
  /* Check that parent directory has write permissions.                */
  /*-------------------------------------------------------------------*/
  if (CheckPerm(dir->parent_dir->entry.dir.comm, F_WRITE))
    return (void *)-1;

  /*-------------------------------------------------------------------*/
  /* Check owner is trying to remove directory.                        */
  /*-------------------------------------------------------------------*/
  FsGetId(&uid, &gid);
  if (uid != dir->comm->user_id)
  {
    set_errno(EPERM);
    return (void *)-1;
  }

  /*-------------------------------------------------------------------*/
  /* If dir is the only link and is not empty, return error.           */
  /*-------------------------------------------------------------------*/
  if (dir->first && dir->comm->links == 1)
  {
    set_errno(EEXIST);
    return (void *)-1;
  }

  /*-------------------------------------------------------------------*/
  /* If directory is open or if it's the current working directory of  */
  /* any task, return error.                                           */
  /*-------------------------------------------------------------------*/
  if (dir->dir || dir->cwds)
  {
    set_errno(EBUSY);
    return (void *)-1;
  }

  /*-------------------------------------------------------------------*/
  /* If an open directory structure is using this entry, update it.    */
  /*-------------------------------------------------------------------*/
  for (i = 0; i < DIROPEN_MAX; ++i)
    if (Files[i].ioctl == FlashIoctl && Files[i].pos == dir_ent)
      Files[i].pos = dir->prev;

  /*-------------------------------------------------------------------*/
  /* Remove the temp dir from the Flash->files_tbl.                    */
  /*-------------------------------------------------------------------*/
  if (dir->prev)
    dir->prev->entry.dir.next = dir->next;
  else
    dir->parent_dir->entry.dir.first = dir->next;
  if (dir->next)
    dir->next->entry.dir.prev = dir->prev;

#if QUOTA_ENABLED
  /*-------------------------------------------------------------------*/
  /* If volume has quota enabled, update quota values.                 */
  /*-------------------------------------------------------------------*/
  if (Flash->quota_enabled)
  {
    ui32 used;
    FFSEnt *ent, *root = &Flash->files_tbl->tbl[0];

    /*-----------------------------------------------------------------*/
    /* Directory should be empty and no links should point to it.      */
    /*-----------------------------------------------------------------*/
    PfAssert(dir->first == NULL && dir->comm->links == 1);

    /*-----------------------------------------------------------------*/
    /* Check free below, reserved below and used.                      */
    /*-----------------------------------------------------------------*/
    PfAssert(dir->res_below == 0 && dir->free_below == 0 &&
             dir->used == 0);

    /*-----------------------------------------------------------------*/
    /* Update used from parent to root.                                */
    /*-----------------------------------------------------------------*/
    used = strlen(dir->name) + 1 + OFDIR_SZ + OFDIR_QUOTA_SZ + OFCOM_SZ;
    for (ent = dir->parent_dir; ent; ent = ent->entry.dir.parent_dir)
    {
      PfAssert(ent->type == FDIREN && ent->entry.dir.used >= used);
      ent->entry.dir.used -= used;
    }

    /*-----------------------------------------------------------------*/
    /* Update reserved below from parent to root.                      */
    /*-----------------------------------------------------------------*/
    for (ent = dir->parent_dir;; ent = ent->entry.dir.parent_dir)
    {
      PfAssert(ent->entry.dir.res_below >= dir->min_q);
      ent->entry.dir.res_below -= dir->min_q;

      /*---------------------------------------------------------------*/
      /* Stop when we reach a directory with a reservation because     */
      /* the directories above this one don't have their reserved below*/
      /* affected by directory removal.                                */
      /*---------------------------------------------------------------*/
      if (ent->entry.dir.min_q != 0)
        break;
    }

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

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

    /*-----------------------------------------------------------------*/
    /* Reset the quota values.                                         */
    /*-----------------------------------------------------------------*/
    dir->min_q = dir->max_q = dir->free = 0;
  }
#endif /* QUOTA_ENABLED */

  /*-------------------------------------------------------------------*/
  /* If this was the only link remove the file entry as well.          */
  /*-------------------------------------------------------------------*/
  if (--dir->comm->links == 0)
  {
    dir->comm->addr->type = FEMPTY;
    ++Flash->total_free;
    FlashIncrementTblEntries(dir->comm->addr);
    Flash->tbls_size -= OFCOM_SZ;
  }

  /*-------------------------------------------------------------------*/
  /* Clear out the entry for the removed directory.                    */
  /*-------------------------------------------------------------------*/
  dir_ent->type = FEMPTY;
  dir->next = dir->prev = dir->first = NULL;

  /*-------------------------------------------------------------------*/
  /* Adjust the number of free file entries.                           */
  /*-------------------------------------------------------------------*/
  ++Flash->total_free;
  FlashIncrementTblEntries(dir_ent);
  Flash->tbls_size -= (OFDIR_SZ + strlen(dir->name) + 1);
#if QUOTA_ENABLED
  if (Flash->quota_enabled)
    Flash->tbls_size -= OFDIR_QUOTA_SZ;
#endif /* QUOTA_ENABLED */

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

  /*-------------------------------------------------------------------*/
  /* Do a sync to save everything before returning.                    */
  /*-------------------------------------------------------------------*/
  return FlashSync(Flash->do_sync);
}

/***********************************************************************/
/* remove_file: Helper function to remove file                         */
/*                                                                     */
/*      Inputs: dir_ent = parent directory for file to be removed      */
/*              fname = name of file to be removed                     */
/*                                                                     */
/*     Returns: NULL on success, (void *)-1 on error                   */
/*                                                                     */
/***********************************************************************/
static void *remove_file(FFSEnt *dir_ent, const char *fname)
{
  FFIL_T *link_ptr;
  FFSEnt *tmp_ent;
  uid_t  uid;
  gid_t  gid;
  uint   i;
  int    rmv_file;
  FDIR_T *dir = &dir_ent->entry.dir;

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

  /*-------------------------------------------------------------------*/
  /* Look for the file in the directory.                               */
  /*-------------------------------------------------------------------*/
  if (find_file(dir, fname, F_EXECUTE | F_WRITE, &tmp_ent, F_ONLY))
    return (void *)-1;
  if (tmp_ent == NULL)
  {
    set_errno(ENOENT);
    return (void *)-1;
  }
  link_ptr = &tmp_ent->entry.file;

  /*-------------------------------------------------------------------*/
  /* Ensure that owner is trying to remove file.                       */
  /*-------------------------------------------------------------------*/
  FsGetId(&uid, &gid);
  if (uid != tmp_ent->entry.file.comm->user_id)
  {
    set_errno(EPERM);
    return (void *)-1;
  }

  /*-------------------------------------------------------------------*/
  /* All the dirty entries in the cache that belong to this file must  */
  /* be cleaned. Also, for dirty old ones, increment number of free    */
  /* sectors.                                                          */
  /*-------------------------------------------------------------------*/
  if (Flash->cache.dirty_old || Flash->cache.dirty_new)
  {
    /*-----------------------------------------------------------------*/
    /* All dirty entries belonging to file must be cleared.            */
    /*-----------------------------------------------------------------*/
    Flash->cache.dirty_old = Flash->cache.dirty_new = FALSE;
    for (i = 0; i < Flash->cache.pool_size; ++i)
    {
      /*---------------------------------------------------------------*/
      /* If sector dirty, either it belongs to file or set dirty flags.*/
      /*---------------------------------------------------------------*/
      if (Flash->cache.pool[i].dirty != CLEAN)
      {
        /*-------------------------------------------------------------*/
        /* If it belongs to the file, clear it. If dirty old, bump up  */
        /* free sectors count.                                         */
        /*-------------------------------------------------------------*/
        if (Flash->cache.pool[i].file_ptr == link_ptr->comm)
        {
          if (Flash->cache.pool[i].dirty == DIRTY_OLD)
            ++Flash->free_sects;
          Flash->cache.pool[i].dirty = CLEAN;
        }

        /*-------------------------------------------------------------*/
        /* Else, mark the appropriate flag.                            */
        /*-------------------------------------------------------------*/
        else if (Flash->cache.pool[i].dirty == DIRTY_NEW)
          Flash->cache.dirty_new = TRUE;
        else
          Flash->cache.dirty_old = TRUE;
      }
    }
  }

  /*-------------------------------------------------------------------*/
  /* Determine whether the file to be removed is open or not.          */
  /*-------------------------------------------------------------------*/
  rmv_file = (link_ptr->file == NULL);

  /*-------------------------------------------------------------------*/
  /* Decrement the number of links for the file.                       */
  /*-------------------------------------------------------------------*/
  --link_ptr->comm->links;

  /*-------------------------------------------------------------------*/
  /* If this was the only link to the file and there are no open file  */
  /* descriptors associated with link, clear contents of file.         */
  /*-------------------------------------------------------------------*/
  if (link_ptr->comm->links == 0 && rmv_file)
  {
    /*-----------------------------------------------------------------*/
    /* Truncate file size to zero.                                     */
    /*-----------------------------------------------------------------*/
    FlashTruncZero(link_ptr, ADJUST_FCBs);

⌨️ 快捷键说明

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