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

📄 rsioctl.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*                                                                     */
/***********************************************************************/
static void *remove_file(RFSEnt *dir_ent, const char *fname)
{
  RFIL_T *link_ptr;
  RFSEnt *tmp_ent;
  uid_t  uid;
  gid_t  gid;
  uint   i;
  int    rmv_file;
  RDIR_T *dir = &dir_ent->entry.dir;

  /*-------------------------------------------------------------------*/
  /* 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;
  }

  /*-------------------------------------------------------------------*/
  /* 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.                                     */
    /*-----------------------------------------------------------------*/
    ram_trunc_zero(link_ptr);

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

  /*-------------------------------------------------------------------*/
  /* If an open dir structure has pointer to this entry, update it.    */
  /*-------------------------------------------------------------------*/
  for (i = 0; i < FOPEN_MAX; ++i)
    if (Files[i].ioctl == RamIoctl && 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;

  /*-------------------------------------------------------------------*/
  /* If the file is to be removed, clear the comm ptr and set the link */
  /* entry to empty, clear file, next and prev.                        */
  /*-------------------------------------------------------------------*/
  if (rmv_file)
  {
    link_ptr->comm = NULL;
    link_ptr->parent_dir = link_ptr->next = link_ptr->prev = NULL;
    link_ptr->file = NULL;
    tmp_ent->type = FEMPTY;

    /*-----------------------------------------------------------------*/
    /* Increment number of free entries.                               */
    /*-----------------------------------------------------------------*/
    ++Ram->total_free;
    incTblEntries(tmp_ent);

    /*-----------------------------------------------------------------*/
    /* Do garbage collection if necessary.                             */
    /*-----------------------------------------------------------------*/
    if (Ram->total_free >= (FNUM_ENT * 5 / 3))
      garbageCollect();
  }

  /*-------------------------------------------------------------------*/
  /* 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 = (RFSEnt *)REMOVED_LINK;

  /*-------------------------------------------------------------------*/
  /* Do a sync to save new state of file system.                       */
  /*-------------------------------------------------------------------*/
  return NULL;
}

/***********************************************************************/
/* 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 RFSEnt *find_new_place(const RFSEnts *smallest)
{
  RFSEnts *tbl;
  int i;

  /*-------------------------------------------------------------------*/
  /* Loop over every file table.                                       */
  /*-------------------------------------------------------------------*/
  for (tbl = Ram->files_tbl; tbl; tbl = tbl->next_tbl)
  {
    /*-----------------------------------------------------------------*/
    /* Check if table is not one 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 = pointer to old entry                             */
/*              new = pointer to new entry                             */
/*                                                                     */
/***********************************************************************/
static void update_entries(const RFSEnt *old, RFSEnt *new)
{
  RFSEnts *curr_tbl = Ram->files_tbl;
  RFSEnt *curr_dir;
  RDIR_T *dir;
  RFIL_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)
        dir->next = new;
      else if (dir->prev == old)
        dir->prev = new;
      else if (dir->parent_dir == old)
        dir->parent_dir = new;
      else if (dir->first == old)
        dir->first = new;
      else if (dir->comm->addr == old)
      {
        new->entry.comm.addr = new;
        dir->comm = &(new->entry.comm);
      }
    }

    /*-----------------------------------------------------------------*/
    /* Else if entry is link, look at next, prev, 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)
        link_ptr->next = new;
      else if (link_ptr->prev == old)
        link_ptr->prev = new;
      else if (link_ptr->comm->addr == old)
      {
        new->entry.comm.addr = new;
        link_ptr->comm = &(new->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.                 */
  /*-------------------------------------------------------------------*/
  for (i = 0; i < FOPEN_MAX; ++i)
    if (Files[i].handle == old)
      Files[i].handle = new;

  /*-------------------------------------------------------------------*/
  /* Finally, if FlashCurrDir is the same as old, update it.           */
  /*-------------------------------------------------------------------*/
  FsReadCWD(&dummy, (void *)&curr_dir);
  if (curr_dir == old)
    FsSaveCWD((ui32)Ram, (ui32)new);
}

/***********************************************************************/
/* garbageCollect: Remove table with most free entries                 */
/*                                                                     */
/***********************************************************************/
static void garbageCollect(void)
{
  int i, max_free = 0;
  RFSEnt *entry;
  RFSEnts *table = NULL, *curr_tbl;

  /*-------------------------------------------------------------------*/
  /* Skip if any opendir() has unmatched closedir().                   */
  /*-------------------------------------------------------------------*/
  if (Ram->opendirs)
    return;

  /*-------------------------------------------------------------------*/
  /* Walk thru all tables except the first one, finding the one with   */
  /* most free entries.                                                */
  /*-------------------------------------------------------------------*/
  for (curr_tbl = Ram->files_tbl->next_tbl; curr_tbl;
       curr_tbl = curr_tbl->next_tbl)
  {
    /*-----------------------------------------------------------------*/
    /* Remember table with most free entries.                          */
    /*-----------------------------------------------------------------*/
    if (curr_tbl->free > max_free)
    {
      table = curr_tbl;
      max_free = curr_tbl->free;
    }
  }

  /*-------------------------------------------------------------------*/
  /* Loop until all entries on this table are free.                    */
  /*-------------------------------------------------------------------*/
  while (table)
  {
    /*-----------------------------------------------------------------*/
    /* Check if table is now empty.                                    */
    /*-----------------------------------------------------------------*/
    if (table->free == FNUM_ENT)
    {

⌨️ 快捷键说明

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