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; }
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; }
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; }
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; }