int
rtems_rfs_file_open (rtems_rfs_file_system*  fs,
                     rtems_rfs_ino           ino,
                     uint32_t                flags,
                     rtems_rfs_file_handle** file)
{
  rtems_rfs_file_handle* handle;
  rtems_rfs_file_shared* shared;
  int                    rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
    printf ("rtems-rfs: file-open: ino=%" PRId32 "\n", ino);
            
  *file = NULL;

  /*
   * Allocate a new handle and initialise it. Do this before we deal with the
   * shared node data so we do not have to be concerned with reference
   * counting.
   */
  handle = malloc (sizeof (rtems_rfs_file_handle));
  if (!handle)
    return ENOMEM;

  memset (handle, 0, sizeof (rtems_rfs_file_handle));

  rc = rtems_rfs_buffer_handle_open (fs, &handle->buffer);
  if (rc > 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
      printf ("rtems-rfs: file-open: buffer handle open failed: %d: %s\n",
              rc, strerror (rc));
    free (handle);
    return rc;
  }
  
  /*
   * Scan the file system data list of open files for this ino. If found up
   * the reference count and return the pointer to the data.
   */
  shared = rtems_rfs_file_get_shared (fs, ino);
  if (shared)
  {
    shared->references++;
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
      printf ("rtems-rfs: file-open: ino=%" PRId32 " shared\n", ino);
  }
  else
  {
    /*
     * None exists so create. Copy in the shared parts of the inode we hold in
     * memory.
     */
    shared = malloc (sizeof (rtems_rfs_file_shared));
    if (!shared)
    {
      rtems_rfs_buffer_handle_close (fs, &handle->buffer);
      free (handle);
      return ENOMEM;
    }

    memset (shared, 0, sizeof (rtems_rfs_file_shared));
    
    rc = rtems_rfs_inode_open (fs, ino, &shared->inode, true);
    if (rc > 0)
    {
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
        printf ("rtems-rfs: file-open: inode open failed: %d: %s\n",
                rc, strerror (rc));
      free (shared);
      rtems_rfs_buffer_handle_close (fs, &handle->buffer);
      free (handle);
      return rc;
    }

    rc = rtems_rfs_block_map_open (fs, &shared->inode, &shared->map);
    if (rc > 0)
    {
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
        printf ("rtems-rfs: file-open: block map open failed: %d: %s\n",
                rc, strerror (rc));
      rtems_rfs_inode_close (fs, &shared->inode);
      free (shared);
      rtems_rfs_buffer_handle_close (fs, &handle->buffer);
      free (handle);
      return rc;
    }

    shared->references = 1;
    shared->size.count = rtems_rfs_inode_get_block_count (&shared->inode);
    shared->size.offset = rtems_rfs_inode_get_block_offset (&shared->inode);
    shared->atime = rtems_rfs_inode_get_atime (&shared->inode);
    shared->mtime = rtems_rfs_inode_get_mtime (&shared->inode);
    shared->ctime = rtems_rfs_inode_get_ctime (&shared->inode);
    shared->fs = fs;

    rtems_chain_append (&fs->file_shares, &shared->link);

    rtems_rfs_inode_unload (fs, &shared->inode, false);

    if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
      printf ("rtems-rfs: file-open: ino=%" PRId32 " share created\n", ino);
  }

  handle->flags  = flags;
  handle->shared = shared;
  
  *file = handle;
  
  return 0;
}
Example #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;
}