Esempio n. 1
0
int IMFS_evaluate_hard_link(
  rtems_filesystem_location_info_t  *node,   /* IN/OUT */
  int                                flags   /* IN     */
)
{
  IMFS_jnode_t                     *jnode  = node->node_access;
  int                               result = 0;

  /*
   * Check for things that should never happen.
   */

  if ( jnode->type != IMFS_HARD_LINK )
    rtems_fatal_error_occurred (0xABCD0000);

  /*
   * Set the hard link value and the handlers.
   */

  node->node_access = jnode->info.hard_link.link_node;

  IMFS_Set_handlers( node );

  /*
   * Verify we have the correct permissions for this node.
   */

  if ( !IMFS_evaluate_permission( node, flags ) )
    rtems_set_errno_and_return_minus_one( EACCES );

  return result;
}
Esempio n. 2
0
int IMFS_initialize_support(
  rtems_filesystem_mount_table_entry_t *mt_entry,
  const void                           *data
)
{
  const IMFS_mount_data *mount_data = data;
  IMFS_fs_info_t *fs_info = mount_data->fs_info;
  IMFS_jnode_t *root_node;

  fs_info->mknod_controls = mount_data->mknod_controls;

  root_node = IMFS_initialize_node(
    &fs_info->Root_directory.Node,
    &fs_info->mknod_controls->directory->node_control,
    "",
    0,
    (S_IFDIR | 0755),
    NULL
  );
  IMFS_assert( root_node != NULL );

  mt_entry->fs_info = fs_info;
  mt_entry->ops = mount_data->ops;
  mt_entry->pathconf_limits_and_options = &IMFS_LIMITS_AND_OPTIONS;
  mt_entry->mt_fs_root->location.node_access = root_node;
  IMFS_Set_handlers( &mt_entry->mt_fs_root->location );

  IMFS_determine_bytes_per_block(
    &imfs_memfile_bytes_per_block,
    imfs_rq_memfile_bytes_per_block,
    IMFS_MEMFILE_DEFAULT_BYTES_PER_BLOCK
  );

  return 0;
}
Esempio n. 3
0
int IMFS_unlink(
  rtems_filesystem_location_info_t  *parentloc, /* IN */
  rtems_filesystem_location_info_t  *loc        /* IN */
)
{
  IMFS_jnode_t                      *node;
  rtems_filesystem_location_info_t   the_link;
  int                                result = 0;

  node = loc->node_access;

  /*
   * Decrement the link counter of node pointed to and free the
   * space.
   */

  /*
   * If this is the last last pointer to the node
   * free the node.
   */

  if ( node->type == IMFS_HARD_LINK ) {

    if ( !node->info.hard_link.link_node )
      rtems_set_errno_and_return_minus_one( EINVAL );

    the_link = *loc;
    the_link.node_access = node->info.hard_link.link_node;
    IMFS_Set_handlers( &the_link );

    /*
     *  If removing the last hard link to a node, then we need
     *  to remove the node that is a link and the node itself.
     */

    if ( node->info.hard_link.link_node->st_nlink == 1)
    {
        result = (*the_link.handlers->rmnod_h)( parentloc, &the_link );
        if ( result != 0 )
            return -1;
    }
    else
    {
        node->info.hard_link.link_node->st_nlink --;
        IMFS_update_ctime( node->info.hard_link.link_node );
    }
  }

  /*
   *  Now actually free the node we were asked to free.
   */

  result = (*loc->handlers->rmnod_h)( parentloc, loc );

  return result;
}
Esempio n. 4
0
int IMFS_evaluate_sym_link(
  rtems_filesystem_location_info_t  *node,   /* IN/OUT */
  int                                flags   /* IN     */
)
{
  IMFS_jnode_t                     *jnode  = node->node_access;
  int                               result = 0;
  int                               i;

  /*
   * Check for things that should never happen.
   */

  if ( jnode->type != IMFS_SYM_LINK )
    rtems_fatal_error_occurred (0xABCD0000);

  if ( !jnode->Parent )
    rtems_fatal_error_occurred( 0xBAD00000 );


  /*
   * Move the node_access to either the symbolic links parent or
   * root depending on the symbolic links path.
   */

  node->node_access = jnode->Parent;

  rtems_filesystem_get_sym_start_loc(
    jnode->info.sym_link.name,
    &i,
    node
  );

  /*
   * Use eval path to evaluate the path of the symbolic link.
   */

  result = IMFS_eval_path(
    &jnode->info.sym_link.name[i],
    strlen( &jnode->info.sym_link.name[i] ),
    flags,
    node
  );

  IMFS_Set_handlers( node );

  /*
   * Verify we have the correct permissions for this node.
   */

  if ( !IMFS_evaluate_permission( node, flags ) )
    rtems_set_errno_and_return_minus_one( EACCES );

  return result;
}
Esempio n. 5
0
int IMFS_initialize_support(
  rtems_filesystem_mount_table_entry_t *mt_entry,
  const rtems_filesystem_operations_table *op_table,
  const IMFS_node_control *const node_controls [IMFS_TYPE_COUNT]
)
{
  static int imfs_instance;

  int rv = 0;
  IMFS_fs_info_t *fs_info = calloc( 1, sizeof( *fs_info ) );

  if ( fs_info != NULL ) {
    IMFS_jnode_t *root_node;

    fs_info->instance = imfs_instance++;
    memcpy(
      fs_info->node_controls,
      node_controls,
      sizeof( fs_info->node_controls )
    );

    root_node = IMFS_allocate_node(
      fs_info,
      fs_info->node_controls [IMFS_DIRECTORY],
      "",
      0,
      (S_IFDIR | 0755),
      NULL
    );
    if ( root_node != NULL ) {
      mt_entry->fs_info = fs_info;
      mt_entry->ops = op_table;
      mt_entry->pathconf_limits_and_options = &IMFS_LIMITS_AND_OPTIONS;
      mt_entry->mt_fs_root->location.node_access = root_node;
      IMFS_Set_handlers( &mt_entry->mt_fs_root->location );
    } else {
      errno = ENOMEM;
      rv = -1;
    }
  } else {
    errno = ENOMEM;
    rv = -1;
  }

  if ( rv == 0 ) {
    IMFS_determine_bytes_per_block(
      &imfs_memfile_bytes_per_block,
      imfs_rq_memfile_bytes_per_block,
      IMFS_MEMFILE_DEFAULT_BYTES_PER_BLOCK
    );
  }

  return rv;
}
Esempio n. 6
0
static int IMFS_stat_hard_link(
  const rtems_filesystem_location_info_t *loc,
  struct stat *buf
)
{
  const IMFS_link_t *hard_link = loc->node_access;
  rtems_filesystem_location_info_t targetloc = *loc;

  targetloc.node_access = hard_link->link_node;
  IMFS_Set_handlers( &targetloc );

  return (targetloc.handlers->fstat_h)( &targetloc, buf );
}
Esempio n. 7
0
void IMFS_fsunmount(
  rtems_filesystem_mount_table_entry_t *temp_mt_entry
)
{
   IMFS_jnode_t                     *jnode;
   IMFS_jnode_t                     *next;
   rtems_filesystem_location_info_t loc;
   int                              result = 0;

   /*
    * Traverse tree that starts at the mt_fs_root and deallocate memory
    * associated memory space
    */

   loc = temp_mt_entry->mt_fs_root->location;
   jnode = (IMFS_jnode_t *)loc.node_access;

   /*
    *  Set this to null to indicate that it is being unmounted.
    */

   temp_mt_entry->mt_fs_root->location.node_access = NULL;

   do {
     next = jnode->Parent;
     loc.node_access = (void *)jnode;
     IMFS_Set_handlers( &loc );

     if ( !IMFS_is_directory( jnode ) || jnode_has_no_children( jnode ) ) {
        result = IMFS_rmnod( NULL, &loc );
        if ( result != 0 )
	  rtems_fatal_error_occurred( 0xdeadbeef );
        IMFS_node_destroy( jnode );
        jnode = next;
     }
     if ( jnode != NULL ) {
       if ( IMFS_is_directory( jnode ) ) {
         if ( jnode_has_children( jnode ) )
           jnode = jnode_get_first_child( jnode );
       }
     }
   } while (jnode != NULL);
}
Esempio n. 8
0
static int IMFS_stat_link(
  const rtems_filesystem_location_info_t *loc,
  struct stat *buf
)
{
  const IMFS_jnode_t *node = loc->node_access;

  if ( IMFS_type( node ) != IMFS_HARD_LINK ) {
    buf->st_size = strlen( node->info.sym_link.name );

    return IMFS_stat( loc, buf );
  } else {
    rtems_filesystem_location_info_t targetloc = *loc;

    targetloc.node_access = node->info.hard_link.link_node;
    IMFS_Set_handlers( &targetloc );

    return (targetloc.handlers->fstat_h)( &targetloc, buf );
  }
}
Esempio n. 9
0
static rtems_filesystem_eval_path_generic_status IMFS_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_filesystem_location_info_t *currentloc =
    rtems_filesystem_eval_path_get_currentloc( ctx );
  IMFS_jnode_t *dir = currentloc->node_access;
  bool access_ok = rtems_filesystem_eval_path_check_access(
    ctx,
    RTEMS_FS_PERMS_EXEC,
    dir->st_mode,
    dir->st_uid,
    dir->st_gid
  );

  if ( access_ok ) {
    IMFS_jnode_t *entry = IMFS_search_in_directory( dir, token, tokenlen );

    if ( entry != NULL ) {
      bool terminal = !rtems_filesystem_eval_path_has_path( ctx );
      int eval_flags = rtems_filesystem_eval_path_get_flags( ctx );
      bool follow_hard_link = (eval_flags & RTEMS_FS_FOLLOW_HARD_LINK) != 0;
      bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0;
      IMFS_jnode_types_t type = IMFS_type( entry );

      rtems_filesystem_eval_path_clear_token( ctx );

      if ( type == IMFS_HARD_LINK && (follow_hard_link || !terminal)) {
        entry = entry->info.hard_link.link_node;
      }

      if ( type == IMFS_SYM_LINK && (follow_sym_link || !terminal)) {
        const char *target = entry->info.sym_link.name;

        rtems_filesystem_eval_path_recursive( ctx, target, strlen( target ) );
      } else {
        rtems_filesystem_global_location_t **fs_root_ptr =
          IMFS_is_mount_point( entry, type );

        if ( fs_root_ptr == NULL ) {
          --dir->reference_count;
          ++entry->reference_count;
          currentloc->node_access = entry;
          currentloc->node_access_2 =
            IMFS_generic_get_context_by_node( entry );
          IMFS_Set_handlers( currentloc );

          if ( !terminal ) {
            status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
          }
        } else {
          access_ok = rtems_filesystem_eval_path_check_access(
            ctx,
            RTEMS_FS_PERMS_EXEC,
            entry->st_mode,
            entry->st_uid,
            entry->st_gid
          );
          if ( access_ok ) {
            rtems_filesystem_eval_path_restart( ctx, fs_root_ptr );
          }
        }
      }
    } else {
      status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
    }
  }

  return status;
}
Esempio n. 10
0
int IMFS_eval_path(
  const char                        *pathname,     /* IN     */
  size_t                             pathnamelen,  /* IN     */
  int                                flags,        /* IN     */
  rtems_filesystem_location_info_t  *pathloc       /* IN/OUT */
                   )
{
  int               i = 0;
  int               len;
  IMFS_token_types  type = IMFS_CURRENT_DIR;
  char              token[ IMFS_NAME_MAX + 1 ];
  IMFS_jnode_t     *node;
  int               result;

  if ( !rtems_libio_is_valid_perms( flags ) ) {
    assert( 0 );
    rtems_set_errno_and_return_minus_one( EIO );
  }

  /*
   *  This was filled in by the caller and is valid in the
   *  mount table.
   */

  node = pathloc->node_access;

  /*
   *  Evaluate all tokens until we are done or an error occurs.
   */

  while( (type != IMFS_NO_MORE_PATH) && (type != IMFS_INVALID_TOKEN) ) {

    type = IMFS_get_token( &pathname[i], pathnamelen, token, &len );
    pathnamelen -= len;
    i += len;

    if ( !pathloc->node_access )
      rtems_set_errno_and_return_minus_one( ENOENT );

    /*
     * I cannot move out of this directory without execute permission.
     */
    if ( type != IMFS_NO_MORE_PATH )
      if ( node->type == IMFS_DIRECTORY )
        if ( !IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
          rtems_set_errno_and_return_minus_one( EACCES );

    node = pathloc->node_access;

    switch( type ) {
      case IMFS_UP_DIR:
        /*
         *  Am I at the root of all filesystems? (chroot'ed?)
         */

        if ( pathloc->node_access == rtems_filesystem_root.node_access )
          break;       /* Throw out the .. in this case */

        /*
         *  Am I at the root of this mounted filesystem?
         */

        if (pathloc->node_access ==
            pathloc->mt_entry->mt_fs_root.node_access) {

          /*
           *  Am I at the root of all filesystems?
           */

          if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
            break;       /* Throw out the .. in this case */
          } else {
            *pathloc = pathloc->mt_entry->mt_point_node;
            return (*pathloc->ops->evalpath_h)(&(pathname[i-len]),
                                               pathnamelen+len,
                                               flags,pathloc);
          }
        } else {
          if ( !node->Parent )
            rtems_set_errno_and_return_minus_one( ENOENT );

          node = node->Parent;
        }

        pathloc->node_access = node;
        break;

      case IMFS_NAME:
        /*
         *  If we are at a link follow it.
         */

        if ( node->type == IMFS_HARD_LINK ) {

          IMFS_evaluate_hard_link( pathloc, 0 );

          node = pathloc->node_access;
          if ( !node )
            rtems_set_errno_and_return_minus_one( ENOTDIR );

        } else if ( node->type == IMFS_SYM_LINK ) {

          result = IMFS_evaluate_sym_link( pathloc, 0 );

          node = pathloc->node_access;
          if ( result == -1 )
            return -1;
        }

        /*
         *  Only a directory can be decended into.
         */

        if ( node->type != IMFS_DIRECTORY )
          rtems_set_errno_and_return_minus_one( ENOTDIR );

        /*
         *  Find the token name in the current node.
         */

        node = IMFS_find_match_in_dir( node, token );

        if ( !node )
          rtems_set_errno_and_return_minus_one( ENOENT );

        /*
         *  If we are at a node that is a mount point so current directory
         *  actually exists on the mounted file system and not in the node that
         *  contains the mount point node. For example a stat of the mount
         *  point should return the details of the root of the mounted file
         *  system not the mount point node of parent file system.
         *
         *  If the node we have just moved to is a mount point do not loop and
         *  get the token because the token may be suitable for the mounted
         *  file system and not the IMFS. For example the IMFS length is
         *  limited. If the token is a parent directory move back up otherwise
         *  set loc to the new fs root node and let them finish evaluating the
         *  path.
         */
        if (( node->type == IMFS_DIRECTORY ) && ( node->info.directory.mt_fs != NULL )) {
          IMFS_skip_separator( pathname, &pathnamelen, &i);
          if ((pathname[i] != '.') || (pathname[i + 1] != '.')) {
            *pathloc = node->info.directory.mt_fs->mt_fs_root;
            return (*pathloc->ops->evalpath_h)( &pathname[i],
                                                pathnamelen,
                                                flags, pathloc );
          }
          i += 2;
          pathnamelen -= 2;
          node = node->Parent;
        }

        /*
         *  Set the node access to the point we have found.
         */

        pathloc->node_access = node;
        break;

      case IMFS_NO_MORE_PATH:
      case IMFS_CURRENT_DIR:
        break;

      case IMFS_INVALID_TOKEN:
        rtems_set_errno_and_return_minus_one( ENAMETOOLONG );
        break;

    }
  }

  /*
   *  Always return the root node.
   *
   *  If we are at a node that is a mount point. Set loc to the
   *  new fs root node and let let the mounted filesystem set the handlers.
   *
   *  NOTE: The behavior of stat() on a mount point appears to be questionable.
   */

  if ( node->type == IMFS_DIRECTORY ) {
    if ( node->info.directory.mt_fs != NULL ) {
      *pathloc = node->info.directory.mt_fs->mt_fs_root;
      return (*pathloc->ops->evalpath_h)( &pathname[i-len],
                                          pathnamelen+len,
                                          flags, pathloc );
    } else {
      result = IMFS_Set_handlers( pathloc );
    }
  } else {
    result = IMFS_Set_handlers( pathloc );
  }

  /*
   * Verify we have the correct permissions for this node.
   */

  if ( !IMFS_evaluate_permission( pathloc, flags ) )
    rtems_set_errno_and_return_minus_one( EACCES );

  return result;
}
Esempio n. 11
0
int IMFS_evaluate_for_make(
  const char                         *path,       /* IN     */
  rtems_filesystem_location_info_t   *pathloc,    /* IN/OUT */
  const char                        **name        /* OUT    */
                           )
{
  int               i = 0;
  int               len;
  IMFS_token_types  type;
  char              token[ IMFS_NAME_MAX + 1 ];
  IMFS_jnode_t     *node;
  bool              done = false;
  size_t            pathlen;
  int               result;

  /*
   * This was filled in by the caller and is valid in the
   * mount table.
   */
  node = pathloc->node_access;

  /*
   * Get the path length.
   */
  pathlen = strlen( path );

  /*
   *  Evaluate all tokens until we are done or an error occurs.
   */

  while( !done ) {

    type = IMFS_get_token( &path[i], pathlen, token, &len );
    pathlen -= len;
    i +=  len;

    if ( !pathloc->node_access )
      rtems_set_errno_and_return_minus_one( ENOENT );

    /*
     * I cannot move out of this directory without execute permission.
     */

    if ( type != IMFS_NO_MORE_PATH )
      if ( node->type == IMFS_DIRECTORY )
        if ( !IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
           rtems_set_errno_and_return_minus_one( EACCES );

    node = pathloc->node_access;

    switch( type ) {

      case IMFS_UP_DIR:
       /*
        *  Am I at the root of all filesystems? (chroot'ed?)
        */

       if ( pathloc->node_access == rtems_filesystem_root.node_access )
         break;       /* Throw out the .. in this case */


       /*
        * Am I at the root of this mounted filesystem?
        */

        if (pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access){

          /*
           *  Am I at the root of all filesystems?
           */

          if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
            break;

          } else {
            *pathloc = pathloc->mt_entry->mt_point_node;
            return (*pathloc->ops->evalformake_h)( &path[i-len], pathloc, name );
          }
        } else {
          if ( !node->Parent )
            rtems_set_errno_and_return_minus_one( ENOENT );

          node = node->Parent;
        }

        pathloc->node_access = node;
        break;

      case IMFS_NAME:
        /*
         *  If we are at a link follow it.
         */

        if ( node->type == IMFS_HARD_LINK ) {

          result = IMFS_evaluate_link( pathloc, 0 );
          if ( result == -1 )
            return -1;

        } else if ( node->type == IMFS_SYM_LINK ) {

          result = IMFS_evaluate_link( pathloc, 0 );

          if ( result == -1 )
            return -1;
        }

        node = pathloc->node_access;
        if ( !node )
          rtems_set_errno_and_return_minus_one( ENOTDIR );

        /*
         * Only a directory can be decended into.
         */

        if ( node->type != IMFS_DIRECTORY )
          rtems_set_errno_and_return_minus_one( ENOTDIR );

        /*
         * Find the token name in the present location.
         */

        node = IMFS_find_match_in_dir( node, token );

        /*
         * If there is no node we have found the name of the node we
         * wish to create.
         */

        if ( ! node )
          done = true;
        else {
        if (( node->type == IMFS_DIRECTORY ) && ( node->info.directory.mt_fs != NULL )) {
            IMFS_skip_separator( path, &pathlen, &i);
            if ((path[i] != '.') || (path[i + 1] != '.')) {
              *pathloc = node->info.directory.mt_fs->mt_fs_root;
              return (*pathloc->ops->evalformake_h)( &path[i],
                                                     pathloc,
                                                     name );
            }
            i += 2;
            pathlen -= 2;
            node = node->Parent;
          }
          
          pathloc->node_access = node;
        }
        break;

      case IMFS_NO_MORE_PATH:
        rtems_set_errno_and_return_minus_one( EEXIST );
        break;

      case IMFS_INVALID_TOKEN:
        rtems_set_errno_and_return_minus_one( ENAMETOOLONG );
        break;

      case IMFS_CURRENT_DIR:
        break;
    }
  }

  *name = &path[ i - len ];

  /*
   * We have evaluated the path as far as we can.
   * Verify there is not any invalid stuff at the end of the name.
   */

  for( ; path[i] != '\0'; i++) {
    if ( !IMFS_is_separator( path[ i ] ) )
      rtems_set_errno_and_return_minus_one( ENOENT );
  }

  /*
   * Verify we can execute and write to this directory.
   */

  result = IMFS_Set_handlers( pathloc );

  /*
   * The returned node must be a directory
   */
  node = pathloc->node_access;
  if ( node->type != IMFS_DIRECTORY )
    rtems_set_errno_and_return_minus_one( ENOTDIR );

  /*
   * We must have Write and execute permission on the returned node.
   */

  if ( !IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_WX ) )
    rtems_set_errno_and_return_minus_one( EACCES );

  return result;
}