/* * IMFS_skip_separator * * Skip the separator in the path. */ static void IMFS_skip_separator ( const char *path, /* IN */ size_t *len, /* IN/OUT */ int *index /* IN/OUT */ ) { while ( IMFS_is_separator( path[*index] ) && path[*index] && *len ) { ++(*index); --(*len); } }
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; }
IMFS_token_types IMFS_get_token( const char *path, int pathlen, char *token, int *token_len ) { register int i = 0; IMFS_token_types type = IMFS_NAME; register char c; /* * Copy a name into token. (Remember NULL is a token.) */ c = path[i]; while ( (!IMFS_is_separator(c)) && (i < pathlen) && (i <= IMFS_NAME_MAX) ) { token[i] = c; if ( i == IMFS_NAME_MAX ) return IMFS_INVALID_TOKEN; if ( !IMFS_is_valid_name_char(c) ) type = IMFS_INVALID_TOKEN; c = path [++i]; } /* * Copy a seperator into token. */ if ( i == 0 ) { token[i] = c; if ( (token[i] != '\0') && pathlen ) { i++; type = IMFS_CURRENT_DIR; } else { type = IMFS_NO_MORE_PATH; } } else if (token[ i-1 ] != '\0') { token[i] = '\0'; } /* * Set token_len to the number of characters copied. */ *token_len = i; /* * If we copied something that was not a seperator see if * it was a special name. */ if ( type == IMFS_NAME ) { if ( strcmp( token, "..") == 0 ) type = IMFS_UP_DIR; else if ( strcmp( token, "." ) == 0 ) type = IMFS_CURRENT_DIR; } return type; }