int
rtems_rfs_file_seek (rtems_rfs_file_handle* handle,
                     rtems_rfs_pos          pos,
                     rtems_rfs_pos*         new_pos)
{
  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
    printf ("rtems-rfs: file-seek: new=%" PRIu64 "\n", pos);
  
  /*
   * This call only sets the position if it is in a valid part of the file. The
   * user can request past the end of the file then write to extend the
   * file. The lseek entry states:
   *
   *    "Although lseek() may position the file offset beyond the end of the
   *     file, this function does not itself extend the size of the file."
   *
   * This means the file needs to set the file size to the pos only when a
   * write occurs.
   */
  if (pos < rtems_rfs_file_shared_get_size (rtems_rfs_file_fs (handle),
                                            handle->shared))
  {
    rtems_rfs_file_set_bpos (handle, pos);
    
    /*
     * If the file has a block check if it maps to the current position and it
     * does not release it. That will force us to get the block at the new
     * position when the I/O starts.
     */
    if (rtems_rfs_buffer_handle_has_block (&handle->buffer))
    {
      rtems_rfs_buffer_block block;
      int                    rc;
      
      rc = rtems_rfs_block_map_find (rtems_rfs_file_fs (handle),
                                     rtems_rfs_file_map (handle),
                                     rtems_rfs_file_bpos (handle),
                                     &block);
      if (rc > 0)
        return rc;
      if (rtems_rfs_buffer_bnum (&handle->buffer) != block)
      {        
        rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
                                              rtems_rfs_file_buffer (handle));
        if (rc > 0)
          return rc;
      }
    }
  }
  else
  {
    /*
     * The seek is outside the current file so release any buffer. A write will
     * extend the file.
     */
    int rc = rtems_rfs_file_io_release (handle);
    if (rc > 0)
      return rc;
  }
  
  *new_pos = pos;
  return 0;
}
Exemplo n.º 2
0
int
rtems_rfs_rtems_fstat (const rtems_filesystem_location_info_t* pathloc,
                       struct stat*                            buf)
{
  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
  rtems_rfs_inode_handle inode;
  rtems_rfs_file_shared* shared;
  uint16_t               mode;
  int                    rc;

  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_STAT))
    printf ("rtems-rfs-rtems: stat: in: ino:%" PRId32 "\n", ino);

  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
  if (rc)
  {
    return rtems_rfs_rtems_error ("stat: opening inode", rc);
  }

  mode = rtems_rfs_inode_get_mode (&inode);

  if (RTEMS_RFS_S_ISCHR (mode) || RTEMS_RFS_S_ISBLK (mode))
  {
    buf->st_rdev =
      rtems_filesystem_make_dev_t (rtems_rfs_inode_get_block (&inode, 0),
                                   rtems_rfs_inode_get_block (&inode, 1));
  }

  buf->st_dev     = rtems_rfs_fs_device (fs);
  buf->st_ino     = rtems_rfs_inode_ino (&inode);
  buf->st_mode    = rtems_rfs_rtems_mode (mode);
  buf->st_nlink   = rtems_rfs_inode_get_links (&inode);
  buf->st_uid     = rtems_rfs_inode_get_uid (&inode);
  buf->st_gid     = rtems_rfs_inode_get_gid (&inode);

  /*
   * Need to check is the ino is an open file. If so we take the values from
   * the open file rather than the inode.
   */
  shared = rtems_rfs_file_get_shared (fs, rtems_rfs_inode_ino (&inode));

  if (shared)
  {
    buf->st_atime   = rtems_rfs_file_shared_get_atime (shared);
    buf->st_mtime   = rtems_rfs_file_shared_get_mtime (shared);
    buf->st_ctime   = rtems_rfs_file_shared_get_ctime (shared);
    buf->st_blocks  = rtems_rfs_file_shared_get_block_count (shared);

    if (S_ISLNK (buf->st_mode))
      buf->st_size = rtems_rfs_file_shared_get_block_offset (shared);
    else
      buf->st_size = rtems_rfs_file_shared_get_size (fs, shared);
  }
  else
  {
    buf->st_atime   = rtems_rfs_inode_get_atime (&inode);
    buf->st_mtime   = rtems_rfs_inode_get_mtime (&inode);
    buf->st_ctime   = rtems_rfs_inode_get_ctime (&inode);
    buf->st_blocks  = rtems_rfs_inode_get_block_count (&inode);

    if (S_ISLNK (buf->st_mode))
      buf->st_size = rtems_rfs_inode_get_block_offset (&inode);
    else
      buf->st_size = rtems_rfs_inode_get_size (fs, &inode);
  }

  buf->st_blksize = rtems_rfs_fs_block_size (fs);

  rc = rtems_rfs_inode_close (fs, &inode);
  if (rc > 0)
  {
    return rtems_rfs_rtems_error ("stat: closing inode", rc);
  }

  return 0;
}