예제 #1
0
/**
 * This routine will read the next directory entry based on the directory
 * offset. The offset should be equal to -n- time the size of an individual
 * dirent structure. If n is not an integer multiple of the sizeof a dirent
 * structure, an integer division will be performed to determine directory
 * entry that will be returned in the buffer. Count should reflect -m- times
 * the sizeof dirent bytes to be placed in the buffer.  If there are not -m-
 * dirent elements from the current directory position to the end of the
 * exisiting file, the remaining entries will be placed in the buffer and the
 * returned value will be equal to -m actual- times the size of a directory
 * entry.
 */
static ssize_t
rtems_rfs_rtems_dir_read (rtems_libio_t* iop,
                          void*          buffer,
                          size_t         count)
{
  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo);
  rtems_rfs_ino          ino = rtems_rfs_rtems_get_iop_ino (iop);
  rtems_rfs_inode_handle inode;
  struct dirent*         dirent;
  ssize_t                bytes_transferred;
  int                    d;
  int                    rc;

  count  = count / sizeof (struct dirent);
  dirent = buffer;
  
  rtems_rfs_rtems_lock (fs);
  
  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
  if (rc)
  {
    rtems_rfs_rtems_unlock (fs);
    return rtems_rfs_rtems_error ("dir_read: read inode", rc);
  }

  bytes_transferred = 0;
  
  for (d = 0; d < count; d++, dirent++)
  {
    size_t size;
    rc = rtems_rfs_dir_read (fs, &inode, iop->offset, dirent, &size);
    if (rc == ENOENT)
    {
      rc = 0;
      break;
    }
    if (rc > 0)
    {
      bytes_transferred = rtems_rfs_rtems_error ("dir_read: dir read", rc);
      break;
    }
    iop->offset += size;
    bytes_transferred += sizeof (struct dirent);
  }

  rtems_rfs_inode_close (fs, &inode);
  rtems_rfs_rtems_unlock (fs);
  
  return bytes_transferred;
}
/**
 * This handler maps an open() operation onto rtems_io_open().
 *
 * @param iop
 * @param pathname
 * @param flag
 * @param mode
 * @return int
 */
static int
rtems_rfs_rtems_device_open ( rtems_libio_t *iop,
                              const char    *pathname,
                              uint32_t       flag,
                              uint32_t       mode)
{
  rtems_libio_open_close_args_t args;
  rtems_rfs_file_system*        fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo);
  rtems_rfs_ino                 ino = rtems_rfs_rtems_get_iop_ino (iop);
  rtems_rfs_inode_handle        inode;
  int                           major;
  int                           minor;
  rtems_status_code             status;
  int                           rc;
  
  rtems_rfs_rtems_lock (fs);
  
  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
  if (rc > 0)
  {
    rtems_rfs_rtems_unlock (fs);
    return rtems_rfs_rtems_error ("device_open: opening inode", rc);
  }

  major = rtems_rfs_inode_get_block (&inode, 0);
  minor = rtems_rfs_inode_get_block (&inode, 1);

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

  rtems_rfs_rtems_unlock (fs);
  
  iop->data0 = major;
  iop->data1 = (void*)((intptr_t) minor);
  
  args.iop   = iop;
  args.flags = iop->flags;
  args.mode  = mode;

  status = rtems_io_open (major, minor, (void *) &args);
  if (status)
    return rtems_deviceio_errno(status);

  return 0;
}
예제 #3
0
static int
rtems_rfs_rtems_chown (const rtems_filesystem_location_info_t *pathloc,
                       uid_t                                   owner,
                       gid_t                                   group)
{
  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;
#if defined (RTEMS_POSIX_API)
  uid_t                  uid;
#endif
  int                    rc;

  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_CHOWN))
    printf ("rtems-rfs-rtems: chown: in: ino:%" PRId32 " uid:%d gid:%d\n",
            ino, owner, group);

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

  /*
   *  Verify I am the owner of the node or the super user.
   */

#if defined (RTEMS_POSIX_API)
  uid = geteuid();

  if ((uid != rtems_rfs_inode_get_uid (&inode)) && (uid != 0))
  {
    rtems_rfs_inode_close (fs, &inode);
    return rtems_rfs_rtems_error ("chown: not able", EPERM);
  }
#endif

  rtems_rfs_inode_set_uid_gid (&inode, owner, group);

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

  return 0;
}
예제 #4
0
/**
 * This handler maps an open() operation onto rtems_io_open().
 *
 * @param iop
 * @param pathname
 * @param flag
 * @param mode
 * @return int
 */
static int
rtems_rfs_rtems_device_open ( rtems_libio_t *iop,
                              const char    *pathname,
                              int            oflag,
                              mode_t         mode)
{
    rtems_rfs_file_system*        fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo);
    rtems_rfs_ino                 ino = rtems_rfs_rtems_get_iop_ino (iop);
    rtems_rfs_inode_handle        inode;
    rtems_device_major_number     major;
    rtems_device_minor_number     minor;
    int                           rc;

    rtems_rfs_rtems_lock (fs);

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

    major = rtems_rfs_inode_get_block (&inode, 0);
    minor = rtems_rfs_inode_get_block (&inode, 1);

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

    rtems_rfs_rtems_unlock (fs);

    iop->data0 = major;
    iop->data1 = (void *) (uintptr_t) minor;

    return rtems_deviceio_open (iop, pathname, oflag, mode, minor, major);
}
예제 #5
0
int
rtems_rfs_fs_open (const char*             name,
                   void*                   user,
                   uint32_t                flags,
                   uint32_t                max_held_buffers,
                   rtems_rfs_file_system** fs)
{
#if UNUSED
  rtems_rfs_group*       group;
  size_t                 group_base;
#endif
  rtems_rfs_inode_handle inode;
  uint16_t               mode;
  int                    rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
    printf ("rtems-rfs: open: %s\n", name);

  *fs = malloc (sizeof (rtems_rfs_file_system));
  if (!*fs)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: open: no memory for file system data\n");
    errno = ENOMEM;
    return -1;
  }

  memset (*fs, 0, sizeof (rtems_rfs_file_system));

  (*fs)->user = user;
  rtems_chain_initialize_empty (&(*fs)->buffers);
  rtems_chain_initialize_empty (&(*fs)->release);
  rtems_chain_initialize_empty (&(*fs)->release_modified);
  rtems_chain_initialize_empty (&(*fs)->file_shares);

  (*fs)->max_held_buffers = max_held_buffers;
  (*fs)->buffers_count = 0;
  (*fs)->release_count = 0;
  (*fs)->release_modified_count = 0;
  (*fs)->flags = flags;

#if UNUSED
  group = &(*fs)->groups[0];
  group_base = 0;
#endif

  /*
   * Open the buffer interface.
   */
  rc = rtems_rfs_buffer_open (name, *fs);
  if (rc > 0)
  {
    free (*fs);
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: open: buffer open failed: %d: %s\n",
              rc, strerror (rc));
    errno = rc;
    return -1;
  }

  rc = rtems_rfs_fs_read_superblock (*fs);
  if (rc > 0)
  {
    rtems_rfs_buffer_close (*fs);
    free (*fs);
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: open: reading superblock: %d: %s\n",
              rc, strerror (rc));
    errno = rc;
    return -1;
  }

  rc = rtems_rfs_inode_open (*fs, RTEMS_RFS_ROOT_INO, &inode, true);
  if (rc > 0)
  {
    rtems_rfs_buffer_close (*fs);
    free (*fs);
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: open: reading root inode: %d: %s\n",
              rc, strerror (rc));
    errno = rc;
    return -1;
  }

  if (((*fs)->flags & RTEMS_RFS_FS_FORCE_OPEN) == 0)
  {
    mode = rtems_rfs_inode_get_mode (&inode);

    if ((mode == 0xffff) || !RTEMS_RFS_S_ISDIR (mode))
    {
      rtems_rfs_inode_close (*fs, &inode);
      rtems_rfs_buffer_close (*fs);
      free (*fs);
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
        printf ("rtems-rfs: open: invalid root inode mode\n");
      errno = EIO;
      return -1;
    }
  }

  rc = rtems_rfs_inode_close (*fs, &inode);
  if (rc > 0)
  {
    rtems_rfs_buffer_close (*fs);
    free (*fs);
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: open: closing root inode: %d: %s\n", rc, strerror (rc));
    errno = rc;
    return -1;
  }

  errno = 0;
  return 0;
}
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;
}
예제 #7
0
static int
rtems_rfs_rtems_mknod (const rtems_filesystem_location_info_t *parentloc,
                       const char                             *name,
                       size_t                                  namelen,
                       mode_t                                  mode,
                       dev_t                                   dev)
{
  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (parentloc);
  rtems_rfs_ino           parent = rtems_rfs_rtems_get_pathloc_ino (parentloc);
  rtems_rfs_ino           ino;
  rtems_rfs_inode_handle  inode;
  uid_t                   uid;
  gid_t                   gid;
  int                     rc;

#if defined(RTEMS_POSIX_API)
  uid = geteuid ();
  gid = getegid ();
#else
  uid = 0;
  gid = 0;
#endif

  rc = rtems_rfs_inode_create (fs, parent, name, namelen,
                               rtems_rfs_rtems_imode (mode),
                               1, uid, gid, &ino);
  if (rc > 0)
  {
    return rtems_rfs_rtems_error ("mknod: inode create", rc);
  }

  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
  if (rc > 0)
  {
    return rtems_rfs_rtems_error ("mknod: inode open", rc);
  }

  if (S_ISDIR(mode) || S_ISREG(mode))
  {
  }
  else if (S_ISCHR (mode) || S_ISBLK (mode))
  {
    int major;
    int minor;
    rtems_filesystem_split_dev_t (dev, major, minor);
    rtems_rfs_inode_set_block (&inode, 0, major);
    rtems_rfs_inode_set_block (&inode, 1, minor);
  }
  else
  {
    rtems_rfs_inode_close (fs, &inode);
    return rtems_rfs_rtems_error ("mknod: bad mode", EINVAL);
  }

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

  return 0;
}
예제 #8
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;
}
예제 #9
0
static rtems_filesystem_eval_path_generic_status
rtems_rfs_rtems_eval_token(
  rtems_filesystem_eval_path_context_t *ctx,
  void *arg,
  const char *token,
  size_t tokenlen
)
{
  rtems_filesystem_eval_path_generic_status status =
    RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
  rtems_rfs_inode_handle* inode = arg;
  bool access_ok = rtems_rfs_rtems_eval_perms (ctx, RTEMS_FS_PERMS_EXEC, inode);

  if (access_ok) {
    if (rtems_filesystem_is_current_directory (token, tokenlen)) {
      rtems_filesystem_eval_path_clear_token (ctx);
    } else {
      rtems_filesystem_location_info_t *currentloc =
        rtems_filesystem_eval_path_get_currentloc( ctx );
      rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (currentloc);
      rtems_rfs_ino entry_ino;
      uint32_t entry_doff;
      int rc = rtems_rfs_dir_lookup_ino (
        fs,
        inode,
        token,
        tokenlen,
        &entry_ino,
        &entry_doff
      );

      if (rc == 0) {
        rc = rtems_rfs_inode_close (fs, inode);
        if (rc == 0) {
          rc = rtems_rfs_inode_open (fs, entry_ino, inode, true);
        }

        if (rc != 0) {
          /*
           * This prevents the rtems_rfs_inode_close() from doing something in
           * rtems_rfs_rtems_eval_path().
           */
          memset (inode, 0, sizeof(*inode));
        }
      } else {
        status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
        rc = -1;
      }

      if (rc == 0) {
        bool is_sym_link = rtems_rfs_rtems_node_type_by_inode (inode)
          == RTEMS_FILESYSTEM_SYM_LINK;
        int eval_flags = rtems_filesystem_eval_path_get_flags (ctx);
        bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0;
        bool terminal = !rtems_filesystem_eval_path_has_path (ctx);

        rtems_filesystem_eval_path_clear_token (ctx);

        if (is_sym_link && (follow_sym_link || !terminal)) {
          rtems_rfs_rtems_follow_link (ctx, fs, entry_ino);
        } else {
          rc = rtems_rfs_rtems_set_handlers (currentloc, inode) ? 0 : EIO;
          if (rc == 0) {
            rtems_rfs_rtems_set_pathloc_ino (currentloc, entry_ino);
            rtems_rfs_rtems_set_pathloc_doff (currentloc, entry_doff);

            if (!terminal) {
              status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
            }
          } else {
            rtems_filesystem_eval_path_error (
              ctx,
              rtems_rfs_rtems_error ("eval_path: set handlers", rc)
            );
          }
        }
      }
    }
  }

  return status;
}
예제 #10
0
int
rtems_rfs_inode_create (rtems_rfs_file_system*  fs,
                        rtems_rfs_ino           parent,
                        const char*             name,
                        size_t                  length,
                        uint16_t                mode,
                        uint16_t                links,
                        uid_t                   uid,
                        gid_t                   gid,
                        rtems_rfs_ino*          ino)
{
  rtems_rfs_inode_handle parent_inode;
  rtems_rfs_inode_handle inode;
  int                    rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_CREATE))
  {
    const char* type = "unknown";
    int         c;
    if (RTEMS_RFS_S_ISDIR (mode))
      type = "dir";
    else if (RTEMS_RFS_S_ISCHR (mode))
      type = "char";
    else if (RTEMS_RFS_S_ISBLK (mode))
      type = "block";
    else if (RTEMS_RFS_S_ISREG (mode))
      type = "file";
    else if (RTEMS_RFS_S_ISLNK (mode))
      type = "link";
    printf("rtems-rfs: inode-create: parent:%" PRIu32 " name:", parent);
    for (c = 0; c < length; c++)
      printf ("%c", name[c]);
    printf (" type:%s mode:%04x (%03o)\n", type, mode, mode & ((1 << 10) - 1));
  }

  /*
   * The file type is field within the mode. Check we have a sane mode set.
   */
  switch (mode & RTEMS_RFS_S_IFMT)
  {
    case RTEMS_RFS_S_IFDIR:
    case RTEMS_RFS_S_IFCHR:
    case RTEMS_RFS_S_IFBLK:
    case RTEMS_RFS_S_IFREG:
    case RTEMS_RFS_S_IFLNK:
      break;
    default:
      return EINVAL;
  }

  rc = rtems_rfs_inode_alloc (fs, parent, ino);
  if (rc > 0)
    return rc;

  rc = rtems_rfs_inode_open (fs, *ino, &inode, true);
  if (rc > 0)
  {
    rtems_rfs_inode_free (fs, *ino);
    return rc;
  }

  rc = rtems_rfs_inode_initialise (&inode, links, mode, uid, gid);
  if (rc > 0)
  {
    rtems_rfs_inode_close (fs, &inode);
    rtems_rfs_inode_free (fs, *ino);
    return rc;
  }

  /*
   * Only handle the specifics of a directory. Let caller handle the others.
   *
   * The inode delete will free the inode.
   */
  if (RTEMS_RFS_S_ISDIR (mode))
  {
    rc = rtems_rfs_dir_add_entry (fs, &inode, ".", 1, *ino);
    if (rc == 0)
      rc = rtems_rfs_dir_add_entry (fs, &inode, "..", 2, parent);
    if (rc > 0)
    {
      rtems_rfs_inode_delete (fs, &inode);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }
  }

  rc = rtems_rfs_inode_open (fs, parent, &parent_inode, true);
  if (rc > 0)
  {
    rtems_rfs_inode_delete (fs, &inode);
    rtems_rfs_inode_close (fs, &inode);
    return rc;
  }

  rc = rtems_rfs_dir_add_entry (fs, &parent_inode, name, length, *ino);
  if (rc > 0)
  {
    rtems_rfs_inode_delete (fs, &inode);
    rtems_rfs_inode_close (fs, &inode);
    rtems_rfs_inode_close (fs, &parent_inode);
    return rc;
  }

  /*
   * If the node is a directory update the parent link count as the
   * new directory has the '..' link that points to the parent.
   */
  if (RTEMS_RFS_S_ISDIR (mode))
    rtems_rfs_inode_set_links (&parent_inode,
                               rtems_rfs_inode_get_links (&parent_inode) + 1);

  rc = rtems_rfs_inode_close (fs, &parent_inode);
  if (rc > 0)
  {
    rtems_rfs_inode_delete (fs, &inode);
    rtems_rfs_inode_close (fs, &inode);
    return rc;
  }

  rc = rtems_rfs_inode_close (fs, &inode);
  if (rc > 0)
  {
    rtems_rfs_inode_free (fs, *ino);
    return rc;
  }

  return 0;
}
예제 #11
0
int
rtems_rfs_symlink_read (rtems_rfs_file_system* fs,
                        rtems_rfs_ino          link,
                        char*                  path,
                        size_t                 size,
                        size_t*                length)
{
  rtems_rfs_inode_handle inode;
  int                    rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_SYMLINK_READ))
    printf ("rtems-rfs: symlink-read: link:%" PRIu32 "\n", link);

  rc = rtems_rfs_inode_open (fs, link, &inode, true);
  if (rc)
    return rc;

  if (!RTEMS_RFS_S_ISLNK (rtems_rfs_inode_get_mode (&inode)))
  {
    rtems_rfs_inode_close (fs, &inode);
    return EINVAL;
  }

  *length = rtems_rfs_inode_get_block_offset (&inode);

  if (size < *length)
  {
    *length = size;
  }

  if (rtems_rfs_inode_get_block_count (&inode) == 0)
  {
    memcpy (path, inode.node->data.name, *length);
  }
  else
  {
    rtems_rfs_block_map     map;
    rtems_rfs_block_no      block;
    rtems_rfs_buffer_handle buffer;
    char*                   data;

    rc = rtems_rfs_block_map_open (fs, &inode, &map);
    if (rc > 0)
    {
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_block_map_seek (fs, &map, 0, &block);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_buffer_handle_open (fs, &buffer);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, false);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    data = rtems_rfs_buffer_data (&buffer);
    memcpy (path, data, *length);

    rc = rtems_rfs_buffer_handle_close (fs, &buffer);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_block_map_close (fs, &map);
    if (rc > 0)
    {
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }
  }

  rc = rtems_rfs_inode_close (fs, &inode);

  return rc;
}
예제 #12
0
int
rtems_rfs_link (rtems_rfs_file_system* fs,
                const char*            name,
                int                    length,
                rtems_rfs_ino          parent,
                rtems_rfs_ino          target,
                bool                   link_dir)
{
  rtems_rfs_inode_handle parent_inode;
  rtems_rfs_inode_handle target_inode;
  uint16_t               links;
  int                    rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_LINK))
  {
    int c;
    printf ("rtems-rfs: link: parent(%" PRIu32 ") -> ", parent);
    for (c = 0; c < length; c++)
      printf ("%c", name[c]);
    printf ("(%" PRIu32 ")\n", target);
  }

  rc = rtems_rfs_inode_open (fs, target, &target_inode, true);
  if (rc)
    return rc;

  /*
   * If the target inode is a directory and we cannot link directories
   * return a not supported error code.
   */
  if (!link_dir && S_ISDIR (rtems_rfs_inode_get_mode (&target_inode)))
  {
    rtems_rfs_inode_close (fs, &target_inode);
    return ENOTSUP;
  }

  rc = rtems_rfs_inode_open (fs, parent, &parent_inode, true);
  if (rc)
  {
    rtems_rfs_inode_close (fs, &target_inode);
    return rc;
  }

  rc = rtems_rfs_dir_add_entry (fs, &parent_inode, name, length, target);
  if (rc > 0)
  {
    rtems_rfs_inode_close (fs, &parent_inode);
    rtems_rfs_inode_close (fs, &target_inode);
    return rc;
  }

  links = rtems_rfs_inode_get_links (&target_inode) + 1;
  rtems_rfs_inode_set_links (&target_inode, links);

  rc = rtems_rfs_inode_time_stamp_now (&parent_inode, true, true);
  if (rc > 0)
  {
    rtems_rfs_inode_close (fs, &parent_inode);
    rtems_rfs_inode_close (fs, &target_inode);
    return rc;
  }

  rc = rtems_rfs_inode_close (fs, &parent_inode);
  if (rc > 0)
  {
    rtems_rfs_inode_close (fs, &target_inode);
    return rc;
  }

  rc = rtems_rfs_inode_close (fs, &target_inode);

  return rc;
}
예제 #13
0
int
rtems_rfs_symlink (rtems_rfs_file_system* fs,
                   const char*            name,
                   int                    length,
                   const char*            link,
                   int                    link_length,
                   uid_t                  uid,
                   gid_t                  gid,
                   rtems_rfs_ino          parent)
{
  rtems_rfs_inode_handle inode;
  rtems_rfs_ino          ino;
  int                    rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_SYMLINK))
  {
    int c;
    printf ("rtems-rfs: symlink: parent:%" PRIu32 " name:", parent);
    for (c = 0; c < length; c++)
      printf ("%c", name[c]);
    printf (" link:");
    for (c = 0; c < link_length; c++)
      printf ("%c", link[c]);
  }

  if (link_length >= rtems_rfs_fs_block_size (fs))
    return ENAMETOOLONG;

  rc = rtems_rfs_inode_create (fs, parent, name, strlen (name),
                               RTEMS_RFS_S_SYMLINK,
                               1, uid, gid, &ino);
  if (rc > 0)
    return rc;

  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
  if (rc > 0)
    return rc;

  /*
   * If the link length is less than the length of data union in the inode
   * place the link into the data area else allocate a block and write the link
   * to that.
   */
  if (link_length < RTEMS_RFS_INODE_DATA_NAME_SIZE)
  {
    memset (inode.node->data.name, 0, RTEMS_RFS_INODE_DATA_NAME_SIZE);
    memcpy (inode.node->data.name, link, link_length);
    rtems_rfs_inode_set_block_count (&inode, 0);
  }
  else
  {
    rtems_rfs_block_map     map;
    rtems_rfs_block_no      block;
    rtems_rfs_buffer_handle buffer;
    uint8_t*                data;

    rc = rtems_rfs_block_map_open (fs, &inode, &map);
    if (rc > 0)
    {
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_block_map_grow (fs, &map, 1, &block);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_buffer_handle_open (fs, &buffer);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, false);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    data = rtems_rfs_buffer_data (&buffer);

    memset (data, 0xff, rtems_rfs_fs_block_size (fs));
    memcpy (data, link, link_length);

    rc = rtems_rfs_buffer_handle_close (fs, &buffer);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_block_map_close (fs, &map);
    if (rc > 0)
    {
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }
  }

  rtems_rfs_inode_set_block_offset (&inode, link_length);

  rc = rtems_rfs_inode_close (fs, &inode);

  return rc;
}
예제 #14
0
int
rtems_rfs_unlink (rtems_rfs_file_system* fs,
                  rtems_rfs_ino          parent,
                  rtems_rfs_ino          target,
                  uint32_t               doff,
                  rtems_rfs_unlink_dir   dir_mode)
{
  rtems_rfs_inode_handle parent_inode;
  rtems_rfs_inode_handle target_inode;
  uint16_t               links;
  bool                   dir;
  int                    rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
    printf ("rtems-rfs: unlink: parent(%" PRIu32 ") -X-> (%" PRIu32 ")\n", parent, target);

  rc = rtems_rfs_inode_open (fs, target, &target_inode, true);
  if (rc)
    return rc;

  /*
   * If a directory process the unlink mode.
   */

  dir = RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&target_inode));
  if (dir)
  {
    switch (dir_mode)
    {
      case rtems_rfs_unlink_dir_denied:
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
          printf ("rtems-rfs: link is a directory\n");
        rtems_rfs_inode_close (fs, &target_inode);
        return EISDIR;

      case rtems_rfs_unlink_dir_if_empty:
        rc = rtems_rfs_dir_empty (fs, &target_inode);
        if (rc > 0)
        {
          if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
            printf ("rtems-rfs: dir-empty: %d: %s\n", rc, strerror (rc));
          rtems_rfs_inode_close (fs, &target_inode);
          return rc;
        }
        break;

      default:
        break;
    }
  }

  rc = rtems_rfs_inode_open (fs, parent, &parent_inode, true);
  if (rc)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
      printf ("rtems-rfs: link: inode-open failed: %d: %s\n",
              rc, strerror (rc));
    rtems_rfs_inode_close (fs, &target_inode);
    return rc;
  }

  rc = rtems_rfs_dir_del_entry (fs, &parent_inode, target, doff);
  if (rc > 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
      printf ("rtems-rfs: unlink: dir-del failed: %d: %s\n",
              rc, strerror (rc));
    rtems_rfs_inode_close (fs, &parent_inode);
    rtems_rfs_inode_close (fs, &target_inode);
    return rc;
  }

  links = rtems_rfs_inode_get_links (&target_inode);

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
    printf ("rtems-rfs: unlink: target:%" PRIu32 " links:%u\n", target, links);

  if (links > 1)
  {
    links--;
    rtems_rfs_inode_set_links (&target_inode, links);
  }
  else
  {
    /*
     * Erasing the inode releases all blocks attached to it.
     */
    rc = rtems_rfs_inode_delete (fs, &target_inode);
    if (rc > 0)
    {
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
        printf ("rtems-rfs: unlink: inode-del failed: %d: %s\n",
                rc, strerror (rc));
      rtems_rfs_inode_close (fs, &parent_inode);
      rtems_rfs_inode_close (fs, &target_inode);
      return rc;
    }

    if (dir)
    {
      links = rtems_rfs_inode_get_links (&parent_inode);
      if (links > 1)
        links--;
      rtems_rfs_inode_set_links (&parent_inode, links);
    }
  }

  rc = rtems_rfs_inode_time_stamp_now (&parent_inode, true, true);
  if (rc > 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
      printf ("rtems-rfs: link: inode-time-stamp failed: %d: %s\n",
              rc, strerror (rc));
    rtems_rfs_inode_close (fs, &parent_inode);
    rtems_rfs_inode_close (fs, &target_inode);
    return rc;
  }

  rc = rtems_rfs_inode_close (fs, &parent_inode);
  if (rc > 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
      printf ("rtems-rfs: link: parent inode-close failed: %d: %s\n",
              rc, strerror (rc));
    rtems_rfs_inode_close (fs, &target_inode);
    return rc;
  }

  rc = rtems_rfs_inode_close (fs, &target_inode);

  if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
    printf ("rtems-rfs: link: target inode-close failed: %d: %s\n",
            rc, strerror (rc));

  return rc;
}
예제 #15
0
static int
rtems_rfs_shell_inode (rtems_rfs_file_system* fs, int argc, char *argv[])
{
  rtems_rfs_ino start;
  rtems_rfs_ino end;
  rtems_rfs_ino total;
  rtems_rfs_ino ino;
  bool          show_all;
  bool          error_check_only;
  bool          forced;
  bool          have_start;
  bool          have_end;
  int           arg;
  int           b;
  int           rc;

  total = fs->group_inodes * fs->group_count;
  start = RTEMS_RFS_ROOT_INO;
  end = total - 1;
  show_all = false;
  error_check_only = false;
  forced = false;
  have_start = have_end = false;

  for (arg = 1; arg < argc; arg++)
  {
    if (argv[arg][0] == '-')
    {
      switch (argv[arg][1])
      {
        case 'a':
          show_all = true;
          break;
        case 'e':
          error_check_only = true;
          break;
        case 'f':
          forced = true;
          break;
        default:
          printf ("warning: option ignored: %s\n", argv[arg]);
          break;
      }
    }
    else
    {
      if (have_end && have_start)
        printf ("warning: option ignored: %s\n", argv[arg]);
      else if (!have_start)
      {
        start = end = strtoul (argv[arg], 0, 0);
        have_start = true;
      }
      else
      {
        end = strtoul (argv[arg], 0, 0);
        have_end = true;
      }
    }
  }

  if ((start >= total) || (end >= total))
  {
    printf ("error: inode out of range (0->%" PRId32 ").\n", total - 1);
    return 1;
  }

  rtems_rfs_shell_lock_rfs (fs);
  
  for (ino = start; ino <= end; ino++)
  {
    rtems_rfs_inode_handle inode;
    bool                   allocated;

    rc = rtems_rfs_group_bitmap_test (fs, true, ino, &allocated);
    if (rc > 0)
    {
      rtems_rfs_shell_unlock_rfs (fs);
      printf ("error: testing inode state: ino=%" PRIu32 ": (%d) %s\n",
              ino, rc, strerror (rc));
      return 1;
    }

    if (show_all || allocated)
    {
      uint16_t mode;
      bool     error;

      rc = rtems_rfs_inode_open (fs, ino, &inode, true);
      if (rc > 0)
      {
        rtems_rfs_shell_unlock_rfs (fs);
        printf ("error: opening inode handle: ino=%" PRIu32 ": (%d) %s\n",
                ino, rc, strerror (rc));
        return 1;
      }

      error = false;
      
      mode = rtems_rfs_inode_get_mode (&inode);

      if (error_check_only)
      {
        if (!RTEMS_RFS_S_ISDIR (mode) &&
            !RTEMS_RFS_S_ISCHR (mode) &&
            !RTEMS_RFS_S_ISBLK (mode) &&
            !RTEMS_RFS_S_ISREG (mode) &&
            !RTEMS_RFS_S_ISLNK (mode))
          error = true;
        else
        {
#if NEED_TO_HANDLE_DIFFERENT_TYPES
          int b;
          for (b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++)
          {
            uint32_t block;
            block = rtems_rfs_inode_get_block (&inode, b);
            if ((block <= RTEMS_RFS_SUPERBLOCK_SIZE) ||
                (block >= rtems_rfs_fs_blocks (fs)))
              error = true;
          }
#endif
        }
      }

      if (!error_check_only || error)
      {
        printf (" %5" PRIu32 ": pos=%06" PRIu32 ":%04zx %c ",
                ino, rtems_rfs_buffer_bnum (&inode.buffer),
                inode.offset * RTEMS_RFS_INODE_SIZE,
                allocated ? 'A' : 'F');
    
        if (!allocated && !forced)
          printf (" --\n");
        else
        {      
          const char* type;
          type = "UKN";
          if (RTEMS_RFS_S_ISDIR (mode))
            type = "DIR";
          else if (RTEMS_RFS_S_ISCHR (mode))
            type = "CHR";
          else if (RTEMS_RFS_S_ISBLK (mode))
            type = "BLK";
          else if (RTEMS_RFS_S_ISREG (mode))
            type = "REG";
          else if (RTEMS_RFS_S_ISLNK (mode))
            type = "LNK";
          printf ("links=%03i mode=%04x (%s/%03o) bo=%04u bc=%04" PRIu32 " b=[",
                  rtems_rfs_inode_get_links (&inode),
                  mode, type, mode & ((1 << 10) - 1),
                  rtems_rfs_inode_get_block_offset (&inode),
                  rtems_rfs_inode_get_block_count (&inode));
          for (b = 0; b < (RTEMS_RFS_INODE_BLOCKS - 1); b++)
            printf ("%" PRIu32 " ", rtems_rfs_inode_get_block (&inode, b));
          printf ("%" PRIu32 "]\n", rtems_rfs_inode_get_block (&inode, b));
        }
      }
      
      rc = rtems_rfs_inode_close (fs, &inode);
      if (rc > 0)
      {
        rtems_rfs_shell_unlock_rfs (fs);
        printf ("error: closing inode handle: ino=%" PRIu32 ": (%d) %s\n",
                ino, rc, strerror (rc));
        return 1;
      }
    }
  }
  
  rtems_rfs_shell_unlock_rfs (fs);
  
  return 0;
}
예제 #16
0
static int
rtems_rfs_write_root_dir (const char* name)
{
  rtems_rfs_file_system* fs;
  rtems_rfs_inode_handle inode;
  rtems_rfs_ino          ino;
  int                    rc;

  /*
   * External API so returns -1.
   */
  rc = rtems_rfs_fs_open (name, NULL, RTEMS_RFS_FS_FORCE_OPEN, &fs);
  if (rc < 0)
  {
    printf ("rtems-rfs: format: file system open failed: %d: %s\n",
            errno, strerror (errno));
    return -1;
  }
  
  rc = rtems_rfs_inode_alloc (fs, RTEMS_RFS_ROOT_INO, &ino);
  if (rc > 0)
  {
    printf ("rtems-rfs: format: inode allocation failed: %d: %s\n",
            rc, strerror (rc));
    rtems_rfs_fs_close (fs);
    return rc;
  }

  if (ino != RTEMS_RFS_ROOT_INO)
  {
    printf ("rtems-rfs: format: allocated inode not root ino: %" PRId32 "\n", ino);
    rtems_rfs_fs_close (fs);
    return rc;
  }
  
  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
  if (rc > 0)
  {
    printf ("rtems-rfs: format: inode open failed: %d: %s\n",
            rc, strerror (rc));
    rtems_rfs_group_bitmap_free (fs, true, ino);
    rtems_rfs_fs_close (fs);
    return rc;
  }

  rc = rtems_rfs_inode_initialise (&inode, 0,
                                   (RTEMS_RFS_S_IFDIR | RTEMS_RFS_S_IRWXU |
                                    RTEMS_RFS_S_IXGRP | RTEMS_RFS_S_IXOTH),
                                   0, 0);
  if (rc > 0)
    printf ("rtems-rfs: format: inode initialise failed: %d: %s\n",
            rc, strerror (rc));
  
  rc = rtems_rfs_dir_add_entry (fs, &inode, ".", 1, ino);
  if (rc > 0)
    printf ("rtems-rfs: format: directory add failed: %d: %s\n",
            rc, strerror (rc));
  
  rc = rtems_rfs_inode_close (fs, &inode);
  if (rc > 0)
    printf ("rtems-rfs: format: inode close failed: %d: %s\n",
            rc, strerror (rc));
  
  rc = rtems_rfs_fs_close (fs);
  if (rc < 0)
    printf ("rtems-rfs: format: file system close failed: %d: %s\n",
            errno, strerror (errno));
  
  return rc;
}