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

📄 rsioctl.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*                                                                     */
/***********************************************************************/
static void seek_past_end(i32 offset, FILE *stream)
{
  RCOM_T *file = ((RFSEnt *)stream->handle)->entry.file.comm;

  /*-------------------------------------------------------------------*/
  /* If offset is zero, set current pointer to EOF.                    */
  /*-------------------------------------------------------------------*/
  if (offset == 0)
    RamPoint2End(&stream->curr_ptr, file);

  /*-------------------------------------------------------------------*/
  /* Else set current pointer past the EOF.                            */
  /*-------------------------------------------------------------------*/
  else
  {
    /*-----------------------------------------------------------------*/
    /* Position is given by sect_off and offset.                       */
    /*-----------------------------------------------------------------*/
    stream->curr_ptr.sector = SEEK_PAST_END;
    stream->curr_ptr.sect_off = (file->size + offset) / RAM_SECT_SZ;
    stream->curr_ptr.offset = (file->size + offset) % RAM_SECT_SZ;
  }
}

/***********************************************************************/
/* ram_trunc_zero: Make a file zero length                             */
/*                                                                     */
/*       Input: entry = pointer to file in files table                 */
/*                                                                     */
/***********************************************************************/
static void ram_trunc_zero(const RFIL_T *entry)
{
  ui32 i;

  /*-------------------------------------------------------------------*/
  /* If the file has non-zero length, erase all the bytes.             */
  /*-------------------------------------------------------------------*/
  if (entry->comm->size)
  {
    /*-----------------------------------------------------------------*/
    /* Truncate the file by freeing all of its sectors.                */
    /*-----------------------------------------------------------------*/
    while (entry->comm->last_sect)
      RamFreeSect(entry->comm);
    entry->comm->size = 0;

    /*-----------------------------------------------------------------*/
    /* Invalidate curr_ptr for any stream pointing to this file.       */
    /*-----------------------------------------------------------------*/
    for (i = 0; i < FOPEN_MAX; ++i)
    {
      if (Files[i].ioctl == RamIoctl &&
          ((RFSEnt *)Files[i].handle)->entry.file.comm == entry->comm)
      {
        Files[i].curr_ptr.sector = (ui32)NULL;
        Files[i].curr_ptr.sect_off = 0;
        Files[i].old_ptr.sector = (ui32)NULL;
        Files[i].old_ptr.sect_off = 0;
      }
    }
  }
}

/***********************************************************************/
/*   truncatef: Truncate the length of a file to desired length        */
/*                                                                     */
/*      Inputs: entry = pointer to file in files table                 */
/*              length = desired file length                           */
/*                                                                     */
/*     Returns: NULL on success, (void *)-1 otherwise                  */
/*                                                                     */
/***********************************************************************/
static void *truncatef(RFSEnt *entry, off_t length)
{
  ui16 last_sect_offset;
  int  count, num_sects, i;
  RFIL_T *lnk = &entry->entry.file;
  RamSect *sect;

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

  /*-------------------------------------------------------------------*/
  /* Else if actual size is less then desired size, append.            */
  /*-------------------------------------------------------------------*/
  else if (lnk->comm->size < length)
  {
    /*-----------------------------------------------------------------*/
    /* Add the extra zero-valued bytes to the file.                    */
    /*-----------------------------------------------------------------*/
    if (RamSeekPastEnd(length - lnk->comm->size, lnk->file))
      return (void *)-1;
  }

  /*-------------------------------------------------------------------*/
  /* Else actual size is greater than desired size, truncate.          */
  /*-------------------------------------------------------------------*/
  else if (lnk->comm->size > length)
  {
    /*-----------------------------------------------------------------*/
    /* Calculate number of remaining sectors and last sector offset.   */
    /*-----------------------------------------------------------------*/
    num_sects = length / RAM_SECT_SZ;
    last_sect_offset = length % RAM_SECT_SZ;
    if (num_sects && last_sect_offset == 0)
    {
      --num_sects;
      last_sect_offset = RAM_SECT_SZ;
    }

    /*-----------------------------------------------------------------*/
    /* Go to last new sector.                                          */
    /*-----------------------------------------------------------------*/
    sect = lnk->comm->frst_sect;
    for (count = 0; count < num_sects; ++count)
      sect = sect->next;

    /*-----------------------------------------------------------------*/
    /* Remove all sectors from current one to end.                     */
    /*-----------------------------------------------------------------*/
    while (lnk->comm->last_sect != sect)
      RamFreeSect(lnk->comm);

    /*-----------------------------------------------------------------*/
    /* Update file's one past last pointer and size.                   */
    /*-----------------------------------------------------------------*/
    lnk->comm->one_past_last = last_sect_offset;
    lnk->comm->size = num_sects * RAM_SECT_SZ + last_sect_offset;

    /*-----------------------------------------------------------------*/
    /* Check if any file descriptor need to be updated.                */
    /*-----------------------------------------------------------------*/
    for (i = 0; i < FOPEN_MAX; ++i)
      if (Files[i].handle == lnk && Files[i].ioctl == RamIoctl)
      {
        /*-------------------------------------------------------------*/
        /* If curr_ptr is invalid, set it to end of file.              */
        /*-------------------------------------------------------------*/
        if (Files[i].curr_ptr.sector != SEEK_PAST_END &&
            (Files[i].curr_ptr.sect_off > num_sects ||
             (Files[i].curr_ptr.sect_off == num_sects &&
              Files[i].curr_ptr.offset > last_sect_offset)))
          Files[i].curr_ptr.sector = SEEK_PAST_END;

        /*-------------------------------------------------------------*/
        /* If old_ptr is invalid, set it to end of file.               */
        /*-------------------------------------------------------------*/
        if (Files[i].old_ptr.sector != SEEK_PAST_END &&
            (Files[i].old_ptr.sect_off > num_sects ||
             (Files[i].old_ptr.sect_off == num_sects &&
              Files[i].old_ptr.offset > last_sect_offset)))
          Files[i].old_ptr.sector = SEEK_PAST_END;
      }
  }

  /*-------------------------------------------------------------------*/
  /* Update file access and modified times. Return success.            */
  /*-------------------------------------------------------------------*/
  lnk->comm->ac_time = lnk->comm->mod_time = OsSecCount;
  return NULL;
}

/***********************************************************************/
/*  remove_dir: Helper function to remove dir                          */
/*                                                                     */
/*       Input: dir_ent = directory to be removed                      */
/*                                                                     */
/*     Returns: NULL on success, (void *)-1 on error                   */
/*                                                                     */
/***********************************************************************/
static void *remove_dir(RFSEnt *dir_ent)
{
  RDIR_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 == &Ram->files_tbl->tbl[0])
  {
    set_errno(ENOENT);
    return (void *)-1;
  }

  /*-------------------------------------------------------------------*/
  /* Check that parent directory has write permissions.                */
  /*-------------------------------------------------------------------*/
  if (CheckPerm((void *)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 == RamIoctl && Files[i].pos == dir_ent)
      Files[i].pos = dir->prev;

  /*-------------------------------------------------------------------*/
  /* Remove the directory from the files table.                        */
  /*-------------------------------------------------------------------*/
  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 this was the only link remove the file entry as well.          */
  /*-------------------------------------------------------------------*/
  if (--dir->comm->links == 0)
  {
    dir->comm->addr->type = FEMPTY;
    ++Ram->total_free;
    incTblEntries(dir->comm->addr);
  }

  /*-------------------------------------------------------------------*/
  /* 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.                           */
  /*-------------------------------------------------------------------*/
  ++Ram->total_free;
  incTblEntries(dir_ent);

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

  return NULL;
}

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

⌨️ 快捷键说明

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