Ejemplo n.º 1
0
int IMFS_symlink(
    rtems_filesystem_location_info_t  *parent_loc,
    const char                        *link_name,
    const char                        *node_name
)
{
    IMFS_types_union   info;
    IMFS_jnode_t      *new_node;
    char               new_name[ IMFS_NAME_MAX + 1 ];
    int                i;

    /*
     * Remove any separators at the end of the string.
     */
    IMFS_get_token( node_name, strlen( node_name ), new_name, &i );

    /*
     * Duplicate link name
     */
    info.sym_link.name = strdup(link_name);
    if (info.sym_link.name == NULL) {
        rtems_set_errno_and_return_minus_one(ENOMEM);
    }

    /*
     *  Create a new link node.
     *
     *  NOTE: Coverity CID 22 notes this as a resource leak.
     *        While technically not a leak, it indicated that IMFS_create_node
     *        was ONLY passed a NULL when we created the root node.  We
     *        added a new IMFS_create_root_node() so this path no longer
     *        existed.  The result was simpler code which should not have
     *        this path.
     */
    new_node = IMFS_create_node(
                   parent_loc,
                   IMFS_SYM_LINK,
                   new_name,
                   ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
                   &info
               );

    if (new_node == NULL) {
        free(info.sym_link.name);
        rtems_set_errno_and_return_minus_one(ENOMEM);
    }

    return 0;
}
Ejemplo n.º 2
0
int IMFS_mknod(
  const char                        *token,      /* IN */
  mode_t                             mode,       /* IN */
  dev_t                              dev,        /* IN */
  rtems_filesystem_location_info_t  *pathloc     /* IN/OUT */
)
{
  IMFS_token_types   type = 0;
  IMFS_jnode_t      *new_node;
  int                result;
  char               new_name[ IMFS_NAME_MAX + 1 ];
  IMFS_types_union   info;

  IMFS_get_token( token, strlen( token ), new_name, &result );

  /*
   *  Figure out what type of IMFS node this is.
   */
  if ( S_ISDIR(mode) )
    type = IMFS_DIRECTORY;
  else if ( S_ISREG(mode) )
    type = IMFS_MEMORY_FILE;
  else if ( S_ISBLK(mode) || S_ISCHR(mode) ) {
    type = IMFS_DEVICE;
    rtems_filesystem_split_dev_t( dev, info.device.major, info.device.minor );
  } else if (S_ISFIFO(mode))
    type = IMFS_FIFO;
  else 
    IMFS_assert( 0 );

  /*
   *  Allocate and fill in an IMFS jnode
   *
   *  NOTE: Coverity Id 21 reports this as a leak.
   *        While technically not a leak, it indicated that IMFS_create_node
   *        was ONLY passed a NULL when we created the root node.  We
   *        added a new IMFS_create_root_node() so this path no longer
   *        existed.  The result was simpler code which should not have
   *        this path. 
   */
  new_node = IMFS_create_node( pathloc, type, new_name, mode, &info );
  if ( !new_node )
    rtems_set_errno_and_return_minus_one( ENOMEM );

  IMFS_update_ctime(new_node->Parent);
  IMFS_update_mtime(new_node->Parent);
  return 0;
}
int IMFS_symlink(
  rtems_filesystem_location_info_t  *parent_loc,
  const char                        *link_name,
  const char                        *node_name
)
{
  IMFS_types_union   info;
  IMFS_jnode_t      *new_node;
  char               new_name[ IMFS_NAME_MAX + 1 ];
  int                i;

  /*
   * Remove any separators at the end of the string.
   */

  IMFS_get_token( node_name, new_name, &i );

  info.sym_link.name = link_name;

  /*
   *  Create a new link node.
   */

  new_node = IMFS_create_node(
    parent_loc,
    IMFS_SYM_LINK,
    new_name,
    ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
    &info
  );

  if ( !new_node )
    rtems_set_errno_and_return_minus_one( ENOMEM );

  return 0;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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;
}