summaryrefslogtreecommitdiffstats
path: root/cpukit/libfs/src/imfs/imfs_eval.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2012-03-13 11:33:51 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2012-03-13 12:23:37 +0100
commit3b7c123c8d910eb60ab3b38dec6224e2de9847c9 (patch)
treea67335010c15af5efb5e27224ae9204883c2b5b8 /cpukit/libfs/src/imfs/imfs_eval.c
parentAdd missing BSD sections. (diff)
downloadrtems-3b7c123c8d910eb60ab3b38dec6224e2de9847c9.tar.bz2
Filesystem: Reference counting for locations
o A new data structure rtems_filesystem_global_location_t was introduced to be used for o the mount point location in the mount table entry, o the file system root location in the mount table entry, o the root directory location in the user environment, and o the current directory location in the user environment. During the path evaluation global start locations are obtained to ensure that the current file system instance will be not unmounted in the meantime. o The user environment uses now reference counting and is protected from concurrent access. o The path evaluation process was completely rewritten and simplified. The IMFS, RFS, NFS, and DOSFS use now a generic path evaluation method. Recursive calls in the path evaluation have been replaced with iteration to avoid stack overflows. Only the evaluation of symbolic links is recursive. No dynamic memory allocations and intermediate buffers are used in the high level path evaluation. No global locks are held during the file system instance specific path evaluation process. o Recursive symbolic link evaluation is now limited by RTEMS_FILESYSTEM_SYMLOOP_MAX. Applications can retrieve this value via sysconf(). o The device file system (devFS) uses now no global variables and allocation from the workspace. Node names are allocated from the heap. o The upper layer lseek() performs now some parameter checks. o The upper layer ftruncate() performs now some parameter checks. o unmask() is now restricted to the RWX flags and protected from concurrent access. o The fchmod_h and rmnod_h file system node handlers are now a file system operation. o The unlink_h operation has been removed. All nodes are now destroyed with the rmnod_h operation. o New lock_h, unlock_h, clonenod_h, and are_nodes_equal_h file system operations. o The path evaluation and file system operations are now protected by per file system instance lock and unlock operations. o Fix and test file descriptor duplicate in fcntl(). o New test fstests/fsnofs01.
Diffstat (limited to 'cpukit/libfs/src/imfs/imfs_eval.c')
-rw-r--r--cpukit/libfs/src/imfs/imfs_eval.c731
1 files changed, 118 insertions, 613 deletions
diff --git a/cpukit/libfs/src/imfs/imfs_eval.c b/cpukit/libfs/src/imfs/imfs_eval.c
index 78fafca536..43f2ee40e0 100644
--- a/cpukit/libfs/src/imfs/imfs_eval.c
+++ b/cpukit/libfs/src/imfs/imfs_eval.c
@@ -4,684 +4,189 @@
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
- *
- * $Id$
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-
#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
-#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
-
-#define MAXSYMLINK 5
-
-int IMFS_Set_handlers(
- rtems_filesystem_location_info_t *loc
-)
+void IMFS_Set_handlers( rtems_filesystem_location_info_t *loc )
{
- IMFS_jnode_t *node = loc->node_access;
- IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *node = loc->node_access;
+ IMFS_fs_info_t *fs_info = loc->mt_entry->fs_info;
+ const rtems_filesystem_file_handlers_r *handlers;
- fs_info = loc->mt_entry->fs_info;
- switch( node->type ) {
+ switch ( node->type ) {
case IMFS_DIRECTORY:
- loc->handlers = fs_info->directory_handlers;
+ handlers = &IMFS_directory_handlers;
break;
case IMFS_DEVICE:
- loc->handlers = &IMFS_device_handlers;
+ handlers = &IMFS_device_handlers;
break;
- case IMFS_SYM_LINK:
case IMFS_HARD_LINK:
- loc->handlers = &IMFS_link_handlers;
- break;
- case IMFS_LINEAR_FILE:
- loc->handlers = fs_info->memfile_handlers;
+ case IMFS_SYM_LINK:
+ handlers = fs_info->link_handlers;
break;
case IMFS_MEMORY_FILE:
- loc->handlers = fs_info->memfile_handlers;
+ case IMFS_LINEAR_FILE:
+ handlers = &IMFS_memfile_handlers;
break;
case IMFS_FIFO:
- loc->handlers = fs_info->fifo_handlers;
+ handlers = fs_info->fifo_handlers;
+ break;
+ default:
+ IMFS_assert( 0 );
break;
}
- return 0;
-}
-
-/*
- * IMFS_evaluate_permission
- *
- * The following routine evaluates that we have permission
- * to do flags on the node.
- */
-static int IMFS_evaluate_permission(
- rtems_filesystem_location_info_t *node,
- int flags
-)
-{
- uid_t st_uid;
- gid_t st_gid;
- IMFS_jnode_t *jnode;
- int flags_to_test;
-
- if ( !rtems_libio_is_valid_perms( flags ) )
- rtems_set_errno_and_return_minus_one( EPERM );
-
- jnode = node->node_access;
-
-#if defined(RTEMS_POSIX_API)
- st_uid = geteuid();
- st_gid = getegid();
-#else
- st_uid = jnode->st_uid;
- st_gid = jnode->st_gid;
-#endif
-
- /*
- * Check if I am owner or a group member or someone else.
- */
-
- flags_to_test = flags;
-
- if ( st_uid == jnode->st_uid )
- flags_to_test <<= 6;
- else if ( st_gid == jnode->st_gid )
- flags_to_test <<= 3;
- else {
- /* must be other - do nothing */;
- }
-
- /*
- * If all of the flags are set we have permission
- * to do this.
- */
- if ( ( flags_to_test & jnode->st_mode) == flags_to_test )
- return 1;
-
- return 0;
+ loc->handlers = handlers;
}
-/*
- * IMFS_evaluate_hard_link
- *
- * The following routine evaluates a hardlink to the actual node.
- */
-
-static int IMFS_evaluate_hard_link(
- rtems_filesystem_location_info_t *node, /* IN/OUT */
- int flags /* IN */
+static bool IMFS_is_directory(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg
)
{
- IMFS_jnode_t *jnode = node->node_access;
- int result = 0;
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc( ctx );
+ IMFS_jnode_t *node = currentloc->node_access;
- /*
- * Check for things that should never happen.
- */
- IMFS_assert( jnode->type == IMFS_HARD_LINK );
-
- /*
- * 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;
+ return node->type == IMFS_DIRECTORY;
}
-
-/*
- * IMFS_evaluate_sym_link
- *
- * The following routine evaluates a symbolic link to the actual node.
- */
-
-static int IMFS_evaluate_sym_link(
- rtems_filesystem_location_info_t *node, /* IN/OUT */
- int flags /* IN */
+static IMFS_jnode_t *IMFS_search_in_directory(
+ IMFS_jnode_t *dir,
+ const char *token,
+ size_t tokenlen
)
{
- IMFS_jnode_t *jnode = node->node_access;
- int result = 0;
- int i;
-
- /*
- * Check for things that should never happen.
- */
- IMFS_assert( jnode->type == IMFS_SYM_LINK );
- IMFS_assert( jnode->Parent );
-
- /*
- * 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;
-}
+ if ( rtems_filesystem_is_current_directory( token, tokenlen ) ) {
+ return dir;
+ } else {
+ if ( rtems_filesystem_is_parent_directory( token, tokenlen ) ) {
+ return dir->Parent;
+ } else {
+ rtems_chain_control *entries = &dir->info.directory.Entries;
+ rtems_chain_node *current = rtems_chain_first( entries );
+ rtems_chain_node *tail = rtems_chain_tail( entries );
-/*
- * IMFS_evaluate_link
- *
- * The following routine returns the real node pointed to by a link.
- */
-int IMFS_evaluate_link(
- rtems_filesystem_location_info_t *node, /* IN/OUT */
- int flags /* IN */
-)
-{
- IMFS_jnode_t *jnode;
- int result = 0;
+ while ( current != tail ) {
+ IMFS_jnode_t *entry = (IMFS_jnode_t *) current;
+ bool match = strncmp( entry->name, token, tokenlen ) == 0
+ && entry->name [tokenlen] == '\0';
- do {
- jnode = node->node_access;
+ if ( match ) {
+ return entry;
+ }
- /*
- * Increment and check the link counter.
- */
+ current = rtems_chain_next( current );
+ }
- rtems_filesystem_link_counts ++;
- if ( rtems_filesystem_link_counts > MAXSYMLINK ) {
- rtems_filesystem_link_counts = 0;
- rtems_set_errno_and_return_minus_one( ELOOP );
+ return NULL;
}
-
- /*
- * Follow the Link node.
- */
-
- if ( jnode->type == IMFS_HARD_LINK )
- result = IMFS_evaluate_hard_link( node, flags );
-
- else if (jnode->type == IMFS_SYM_LINK )
- result = IMFS_evaluate_sym_link( node, flags );
-
- } while ( ( result == 0 ) && ( ( jnode->type == IMFS_SYM_LINK ) ||
- ( jnode->type == IMFS_HARD_LINK ) ) );
-
- /*
- * Clear link counter.
- */
-
- rtems_filesystem_link_counts = 0;
-
- return result;
-}
-
-/*
- * 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);
}
}
-/*
- * IMFS_evaluate_for_make
- *
- * The following routine evaluate path for a new node to be created.
- * pathloc is returned with a pointer to the parent of the new node.
- * name is returned with a pointer to the first character in the
- * new node name. The parent node is verified to be a directory.
- */
-
-int IMFS_evaluate_for_make(
- const char *path, /* IN */
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- const char **name /* OUT */
- )
+static rtems_filesystem_global_location_t **IMFS_is_mount_point(
+ IMFS_jnode_t *node
+)
{
- 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.
- */
+ rtems_filesystem_global_location_t **fs_root_ptr = NULL;
- 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 ( rtems_filesystem_is_root_location( pathloc ) ) {
-
- /*
- * 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 ( 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;
+ if ( node->type == IMFS_DIRECTORY ) {
+ if ( node->info.directory.mt_fs != NULL ) {
+ fs_root_ptr = &node->info.directory.mt_fs->mt_fs_root;
}
}
- *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;
+ return fs_root_ptr;
}
-/*
- * IMFS_eval_path
- *
- * The following routine evaluate path for a node that wishes to be
- * accessed with mode. pathloc is returned with a pointer to the
- * node to be accessed.
- */
-
-int IMFS_eval_path(
- const char *pathname, /* IN */
- size_t pathnamelen, /* IN */
- int flags, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
- )
+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
+)
{
- 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 ) ) {
- 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 );
+ 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_LIBIO_PERMS_SEARCH,
+ dir->st_mode,
+ dir->st_uid,
+ dir->st_gid
+ );
- /*
- * 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 );
+ if ( access_ok ) {
+ IMFS_jnode_t *entry = IMFS_search_in_directory( dir, token, tokenlen );
- node = pathloc->node_access;
+ 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_LIBIO_FOLLOW_HARD_LINK) != 0;
+ bool follow_sym_link = (eval_flags & RTEMS_LIBIO_FOLLOW_SYM_LINK) != 0;
- switch( type ) {
- case IMFS_UP_DIR:
- /*
- * Am I at the root of all filesystems? (chroot'ed?)
- */
+ rtems_filesystem_eval_path_clear_token( ctx );
- if ( pathloc->node_access == rtems_filesystem_root.node_access )
- break; /* Throw out the .. in this case */
+ if ( entry->type == IMFS_HARD_LINK && (follow_hard_link || !terminal)) {
+ entry = entry->info.hard_link.link_node;
+ }
- /*
- * Am I at the root of this mounted filesystem?
- */
+ if ( entry->type == IMFS_SYM_LINK && (follow_sym_link || !terminal)) {
+ const char *target = entry->info.sym_link.name;
- if ( rtems_filesystem_is_root_location( pathloc ) ) {
+ rtems_filesystem_eval_path_recursive( ctx, target, strlen( target ) );
+ } else {
+ rtems_filesystem_global_location_t **fs_root_ptr =
+ IMFS_is_mount_point( entry );
- /*
- * Am I at the root of all filesystems?
- */
+ if ( fs_root_ptr == NULL ) {
+ currentloc->node_access = entry;
+ IMFS_Set_handlers( currentloc );
- 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);
+ if ( !terminal ) {
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
}
} else {
-
- if ( !node->Parent )
- rtems_set_errno_and_return_minus_one( ENOENT );
-
- node = node->Parent;
- pathloc->node_access = node;
-
- }
-
- 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;
-
- /*
- * It would be a design error if we evaluated the link and
- * was broken.
- */
- IMFS_assert( node );
-
- } else if ( node->type == IMFS_SYM_LINK ) {
- result = IMFS_evaluate_sym_link( pathloc, 0 );
-
- /*
- * In contrast to a hard link, it is possible to have a broken
- * symbolic link.
- */
- 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 );
+ access_ok = rtems_filesystem_eval_path_check_access(
+ ctx,
+ RTEMS_LIBIO_PERMS_EXEC,
+ entry->st_mode,
+ entry->st_uid,
+ entry->st_gid
+ );
+ if ( access_ok ) {
+ rtems_filesystem_eval_path_restart( ctx, fs_root_ptr );
}
- 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 );
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
}
- } else {
- result = IMFS_Set_handlers( pathloc );
}
- /*
- * Verify we have the correct permissions for this node.
- */
+ return status;
+}
- if ( !IMFS_evaluate_permission( pathloc, flags ) )
- rtems_set_errno_and_return_minus_one( EACCES );
+static const rtems_filesystem_eval_path_generic_config IMFS_eval_config = {
+ .is_directory = IMFS_is_directory,
+ .eval_token = IMFS_eval_token
+};
- return result;
+void IMFS_eval_path( rtems_filesystem_eval_path_context_t *ctx )
+{
+ rtems_filesystem_eval_path_generic( ctx, NULL, &IMFS_eval_config );
}