diff options
Diffstat (limited to 'cpukit')
166 files changed, 6155 insertions, 7519 deletions
diff --git a/cpukit/include/rtems/fs.h b/cpukit/include/rtems/fs.h index 84b18370b5..bf5026f645 100644 --- a/cpukit/include/rtems/fs.h +++ b/cpukit/include/rtems/fs.h @@ -8,6 +8,9 @@ * COPYRIGHT (c) 1989-2011. * 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. @@ -18,6 +21,8 @@ #ifndef _RTEMS_FS_H #define _RTEMS_FS_H +#include <rtems/chain.h> + #ifdef __cplusplus extern "C" { #endif @@ -31,9 +36,6 @@ extern "C" { /* FIXME: shouldn't this better not be here? */ typedef struct rtems_libio_tt rtems_libio_t; -typedef struct rtems_filesystem_location_info_tt - rtems_filesystem_location_info_t; - struct rtems_filesystem_mount_table_entry_tt; typedef struct rtems_filesystem_mount_table_entry_tt rtems_filesystem_mount_table_entry_t; @@ -43,18 +45,57 @@ typedef struct _rtems_filesystem_file_handlers_r typedef struct _rtems_filesystem_operations_table rtems_filesystem_operations_table; -/* - * Structure used to determine a location/filesystem in the tree. +/** + * @brief File system location. + * + * @ingroup LibIO */ - -struct rtems_filesystem_location_info_tt -{ +typedef struct rtems_filesystem_location_info_tt { + rtems_chain_node mt_entry_node; void *node_access; void *node_access_2; const rtems_filesystem_file_handlers_r *handlers; const rtems_filesystem_operations_table *ops; rtems_filesystem_mount_table_entry_t *mt_entry; -}; +} rtems_filesystem_location_info_t; + +/** + * @brief Global file system location. + * + * @ingroup LibIO + * + * The global file system locations are used for + * - the mount point location in the mount table entry, + * - the file system root location in the mount table entry, + * - the root directory location in the user environment, and + * - the current directory location in the user environment. + * + * During the path evaluation global start locations are obtained to ensure + * that the current file system will be not unmounted in the meantime. + * + * To support a release within critical sections of the operating system a + * deferred release is supported. This is similar to malloc() and free(). + * + * @see rtems_filesystem_global_location_obtain() and + * rtems_filesystem_global_location_release(). + */ +typedef struct rtems_filesystem_global_location_t { + rtems_filesystem_location_info_t location; + int reference_count; + + /** + * A release within a critical section of the operating system will add this + * location to a list of deferred released locations. This list is processed + * in the next rtems_filesystem_global_location_obtain() in FIFO order. + */ + struct rtems_filesystem_global_location_t *deferred_released_next; + + /** + * A release within a critical section can happen multiple times. This field + * counts the deferred releases. + */ + int deferred_released_count; +} rtems_filesystem_global_location_t; /* * Return the mount table entry for a path location. diff --git a/cpukit/include/rtems/userenv.h b/cpukit/include/rtems/userenv.h index 28ac69ebd3..123da98af5 100644 --- a/cpukit/include/rtems/userenv.h +++ b/cpukit/include/rtems/userenv.h @@ -1,13 +1,16 @@ /** - * @file rtems/userenv.h + * @file * - * This file defines the interface for POSIX per-process environment. + * @ingroup LibIOEnv */ /* * COPYRIGHT (c) 1989-2011. * 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. @@ -18,6 +21,13 @@ #ifndef _RTEMS_USERENV_H #define _RTEMS_USERENV_H +/* + * According to IEEE Std 1003.1-2001, + * limits.h is supposed to provide _POSIX_LOGIN_NAME_MAX + * XXX: We do not rely on this. + */ +#include <limits.h> + #include <rtems.h> #include <rtems/fs.h> @@ -25,33 +35,30 @@ extern "C" { #endif -/* - * External structures - */ - -/* - * According to IEEE Std 1003.1-2001, - * limits.h is supposed to provide _POSIX_LOGIN_NAME_MAX - * FIXME: We should not rely on this. +/** + * @defgroup LibIOEnv User Environment + * + * @ingroup LibIO + * + * @brief Provides a POSIX like user environment for tasks. + * + * @{ */ -#include <limits.h> #ifndef LOGIN_NAME_MAX -#ifdef _POSIX_LOGIN_NAME_MAX -#define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX -#else -/* Fallback */ -#define LOGIN_NAME_MAX 9 -#endif + #ifdef _POSIX_LOGIN_NAME_MAX + #define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX + #else + /* Fallback */ + #define LOGIN_NAME_MAX 9 + #endif #endif typedef struct { - rtems_id task_id; - rtems_filesystem_location_info_t current_directory; - rtems_filesystem_location_info_t root_directory; + rtems_filesystem_global_location_t *current_directory; + rtems_filesystem_global_location_t *root_directory; /* Default mode for all files. */ mode_t umask; - nlink_t link_counts; /* _POSIX_types */ uid_t uid; gid_t gid; @@ -59,6 +66,9 @@ typedef struct { gid_t egid; char login_buffer[LOGIN_NAME_MAX]; pid_t pgrp; /* process group id */ + /* User environment maintenance */ + rtems_id task_id; + int reference_count; } rtems_user_env_t; extern rtems_user_env_t * rtems_current_user_env; @@ -66,7 +76,6 @@ extern rtems_user_env_t rtems_global_user_env; #define rtems_filesystem_current (rtems_current_user_env->current_directory) #define rtems_filesystem_root (rtems_current_user_env->root_directory) -#define rtems_filesystem_link_counts (rtems_current_user_env->link_counts) #define rtems_filesystem_umask (rtems_current_user_env->umask) #define _POSIX_types_Uid (rtems_current_user_env->uid) @@ -75,14 +84,48 @@ extern rtems_user_env_t rtems_global_user_env; #define _POSIX_types_Egid (rtems_current_user_env->egid) #define _POSIX_types_Getlogin_buffer (rtems_current_user_env->login_buffer) - -/* - * Instantiate a private copy of the per user information for the calling task. +/** + * @brief Creates a private environment. + * + * If the task has already a private environment nothing will be changed. This + * function must be called from normal thread context and may block on a mutex. + * Thread dispatching is disabled to protect some critical sections. + * + * @retval RTEMS_SUCCESSFUL Successful operation. + * @retval RTEMS_NO_MEMORY Not enough memory. + * @retval RTEMS_UNSATISFIED Cloning of the current environment failed. + * @retval RTEMS_TOO_MANY Cannot register the private environment. */ - rtems_status_code rtems_libio_set_private_env(void); + +/** + * @brief Creates a private environment shared with another task. + * + * An attempt to share the environment with itself has no effect. This + * function must be called from normal thread context and may block on a mutex. + * Thread dispatching is disabled to protect some critical sections. + * + * @param[in] task_id The private environment is shared with the task specified + * by this identifier. + * + * @retval RTEMS_SUCCESSFUL Successful operation. + * @retval RTEMS_UNSATISFIED No shared environment is available for this task + * @retval RTEMS_TOO_MANY Cannot register the shared environment. + * identifier. + */ rtems_status_code rtems_libio_share_private_env(rtems_id task_id) ; +/** + * @brief Use the global environment. + * + * A private environment will be released. This function may be called from + * every thread context. Thread dispatching is disabled to protect the + * critical sections. + */ +void rtems_libio_use_global_env(void); + +/** @} */ + #ifdef __cplusplus } #endif diff --git a/cpukit/libcsupport/Makefile.am b/cpukit/libcsupport/Makefile.am index 15e55a1e51..321eb29597 100644 --- a/cpukit/libcsupport/Makefile.am +++ b/cpukit/libcsupport/Makefile.am @@ -57,7 +57,7 @@ ASSOCIATION_C_FILES = src/assoclocalbyname.c \ BASE_FS_C_FILES = src/base_fs.c src/mount.c src/unmount.c src/libio.c \ src/mount-mgr.c src/mount-mktgt.c src/libio_init.c \ - src/eval.c src/privateenv.c \ + src/privateenv.c \ src/open_dev_console.c src/__usrenv.c src/rtems_mkdir.c if LIBNETWORKING @@ -99,7 +99,7 @@ ID_C_FILES = src/getegid.c src/geteuid.c src/getgid.c src/getgroups.c \ MALLOC_C_FILES = src/malloc_initialize.c src/calloc.c src/malloc.c \ src/realloc.c src/_calloc_r.c src/_malloc_r.c \ - src/free.c src/freenode.c src/_free_r.c \ + src/free.c src/_free_r.c \ src/_realloc_r.c src/mallocfreespace.c \ src/mallocgetheapptr.c src/mallocsetheapptr.c \ src/mallocinfo.c src/malloc_walk.c src/malloc_get_statistics.c \ @@ -127,8 +127,16 @@ BSD_LIBC_C_FILES = src/strlcpy.c src/strlcat.c src/issetugid.c libcsupport_a_SOURCES = src/gxx_wrappers.c src/getchark.c src/printk.c \ src/printk_plugin.c src/putk.c src/vprintk.c \ - src/sup_fs_is_separator.c src/sup_fs_get_start_loc.c \ - src/sup_fs_get_sym_start_loc.c \ + src/sup_fs_location.c \ + src/sup_fs_eval_path.c \ + src/sup_fs_eval_path_generic.c \ + src/sup_fs_check_permissions.c \ + src/sup_fs_next_token.c \ + src/sup_fs_exist_in_same_instance.c \ + src/sup_fs_mount_iterate.c \ + src/sup_fs_node_type.c \ + src/clonenode.c \ + src/freenode.c \ $(BSD_LIBC_C_FILES) $(BASE_FS_C_FILES) $(MALLOC_C_FILES) \ $(ERROR_C_FILES) $(ASSOCIATION_C_FILES) diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h index 661fe0bc33..4a09e0c18b 100644 --- a/cpukit/libcsupport/include/rtems/libio.h +++ b/cpukit/libcsupport/include/rtems/libio.h @@ -10,6 +10,9 @@ * COPYRIGHT (c) 1989-2008. * 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. @@ -37,20 +40,15 @@ extern "C" { #endif /** - * @defgroup LibIO IO Library + * @defgroup LibIOFSOps File System Operations * - * @brief Provides system call and file system interface definitions. + * @ingroup LibIO * - * General purpose communication channel for RTEMS to allow UNIX/POSIX - * system call behavior under RTEMS. Initially this supported only - * IO to devices but has since been enhanced to support networking - * and support for mounted file systems. + * @brief File system operations. * * @{ */ -typedef off_t rtems_off64_t __attribute__((deprecated)); - /** * @brief File system node types. */ @@ -64,974 +62,1044 @@ typedef enum { } rtems_filesystem_node_types_t; /** - * @name File System Node Operations + * @brief Locks a file system instance. * - * @{ + * This lock must allow nesting. + * + * @param[in, out] mt_entry The mount table entry of the file system instance. + * + * @see rtems_filesystem_default_lock(). */ +typedef void (*rtems_filesystem_mt_entry_lock_t)( + rtems_filesystem_mount_table_entry_t *mt_entry +); /** - * This type defines the interface to the open(2) system call - * support which is provided by a file system implementation. + * @brief Unlocks a file system instance. + * + * @param[in, out] mt_entry The mount table entry of the file system instance. + * + * @see rtems_filesystem_default_unlock(). */ -typedef int (*rtems_filesystem_open_t)( - rtems_libio_t *iop, - const char *pathname, - uint32_t flag, - uint32_t mode +typedef void (*rtems_filesystem_mt_entry_unlock_t)( + rtems_filesystem_mount_table_entry_t *mt_entry ); /** - * This type defines the interface to the close(2) system call - * support which is provided by a file system implementation. + * @brief Path evaluation context. */ -typedef int (*rtems_filesystem_close_t)( - rtems_libio_t *iop -); +typedef struct { + /** + * The contents of the remaining path to be evaluated. + */ + const char *path; + + /** + * The length of the remaining path to be evaluated. + */ + size_t pathlen; + + /** + * The contents of the token to be evaluated with respect to the current + * location. + */ + const char *token; + + /** + * The length of the token to be evaluated with respect to the current + * location. + */ + size_t tokenlen; + + /** + * The path evaluation is controlled by the following flags + * - RTEMS_LIBIO_PERMS_READ, + * - RTEMS_LIBIO_PERMS_WRITE, + * - RTEMS_LIBIO_PERMS_EXEC, + * - RTEMS_LIBIO_PERMS_SEARCH, + * - RTEMS_LIBIO_FOLLOW_HARD_LINK, + * - RTEMS_LIBIO_FOLLOW_SYM_LINK, + * - RTEMS_LIBIO_MAKE, + * - RTEMS_LIBIO_EXCLUSIVE, + * - RTEMS_LIBIO_ACCEPT_RESIDUAL_DELIMITERS, and + * - RTEMS_LIBIO_REJECT_TERMINAL_DOT. + */ + int flags; + + /** + * Symbolic link evaluation is a recursive operation. This field helps to + * limit the recursion level and thus prevents a stack overflow. The + * recursion level is limited by RTEMS_FILESYSTEM_SYMLOOP_MAX. + */ + int recursionlevel; + + /** + * This is the current file system location of the evaluation process. + * Tokens are evaluated with respect to the current location. The token + * interpretation may change the current location. The purpose of the path + * evaluation is to change the start location into a final current location + * according to the path. + */ + rtems_filesystem_location_info_t currentloc; + + /** + * The location of the root directory of the user environment during the + * evaluation start. + */ + rtems_filesystem_global_location_t *rootloc; + + /** + * The start location of the evaluation process. The start location my + * change during symbolic link evaluation. + */ + rtems_filesystem_global_location_t *startloc; +} rtems_filesystem_eval_path_context_t; /** - * This type defines the interface to the read(2) system call - * support which is provided by a file system implementation. + * @brief Path evaluation. + * + * @param[in, out] ctx The path evaluation context. + * + * @see rtems_filesystem_default_eval_path(). */ -typedef ssize_t (*rtems_filesystem_read_t)( - rtems_libio_t *iop, - void *buffer, - size_t count +typedef void (*rtems_filesystem_eval_path_t)( + rtems_filesystem_eval_path_context_t *ctx ); /** - * This type defines the interface to the write(2) system call - * support which is provided by a file system implementation. + * @brief Creates a new link for the existing file. + * + * @param[in] parentloc The location of the parent of the new link. + * @param[in] targetloc The location of the target file. + * @param[in] name Name for the new link. + * @param[in] namelen Length of the name for the new link in characters. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_link(). */ -typedef ssize_t (*rtems_filesystem_write_t)( - rtems_libio_t *iop, - const void *buffer, - size_t count +typedef int (*rtems_filesystem_link_t)( + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *targetloc, + const char *name, + size_t namelen ); /** - * This type defines the interface to the ioctl(2) system call - * support which is provided by a file system implementation. + * @brief Changes the mode of a node. + * + * @param[in] loc The location of the node. + * @param[in] mode The new mode of the node + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_fchmod(). */ -typedef int (*rtems_filesystem_ioctl_t)( - rtems_libio_t *iop, - uint32_t command, - void *buffer +typedef int (*rtems_filesystem_fchmod_t)( + const rtems_filesystem_location_info_t *loc, + mode_t mode ); /** - * This type defines the interface to the lseek(2) system call - * support which is provided by a file system implementation. + * @brief Changes owner and group of a node. + * + * @param[in] loc The location of the node. + * @param[in] owner User ID for the node. + * @param[in] group Group ID for the node. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_chown(). */ -typedef off_t (*rtems_filesystem_lseek_t)( - rtems_libio_t *iop, - off_t length, - int whence +typedef int (*rtems_filesystem_chown_t)( + const rtems_filesystem_location_info_t *loc, + uid_t owner, + gid_t group ); /** - * This type defines the interface to the fstat(2) system call - * support which is provided by a file system implementation. + * @brief Clones a location. + * + * The location is initialized with a bitwise copy of an existing location. + * The caller must ensure that this location is protected from a release during + * the clone operation. After a successful clone operation the clone will be + * added to the location chain of the corresponding mount table entry. + * + * @param[in, out] loc Location to clone. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_clonenode(). */ -typedef int (*rtems_filesystem_fstat_t)( - rtems_filesystem_location_info_t *loc, - struct stat *buf +typedef int (*rtems_filesystem_clonenode_t)( + rtems_filesystem_location_info_t *loc ); /** - * This type defines the interface to the fchmod(2) system call - * support which is provided by a file system implementation. + * @brief Frees the location of a node. + * + * @param[in] loc The location of the node. + * + * @see rtems_filesystem_default_freenode(). */ -typedef int (*rtems_filesystem_fchmod_t)( - rtems_filesystem_location_info_t *loc, - mode_t mode +typedef void (*rtems_filesystem_freenode_t)( + const rtems_filesystem_location_info_t *loc ); /** - * This type defines the interface to the ftruncate(2) system call - * support which is provided by a file system implementation. + * @brief Mounts a file system instance in a mount point (directory). + * + * The mount point belongs to the file system instance of the handler and is + * specified by a field of the mount table entry. The handler must check that + * the mount point is capable of mounting a file system instance. This is the + * last step during the mount process. The file system instance is fully + * initialized at this point. + * + * @param[in] mt_entry The mount table entry. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_mount(). */ -typedef int (*rtems_filesystem_ftruncate_t)( - rtems_libio_t *iop, - off_t length +typedef int (*rtems_filesystem_mount_t) ( + rtems_filesystem_mount_table_entry_t *mt_entry ); /** - * This type defines the interface to the fsync(2) system call - * support which is provided by a file system implementation. + * @brief Initializes a file system instance. + * + * This function must initialize the file system root node in the mount table + * entry. + * + * @param[in] mt_entry The mount table entry. + * @param[in] data The data provided by the user. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. */ -typedef int (*rtems_filesystem_fsync_t)( - rtems_libio_t *iop +typedef int (*rtems_filesystem_fsmount_me_t)( + rtems_filesystem_mount_table_entry_t *mt_entry, + const void *data ); /** - * This type defines the interface to the fdatasync(2) system call - * support which is provided by a file system implementation. + * @brief Unmounts a file system instance in a mount point (directory). + * + * In case this function is successful the file system instance will be marked + * as unmounted. The file system instance will be destroyed when the last + * reference to it vanishes. + * + * @param[in] mt_entry The mount table entry. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_unmount(). */ -typedef int (*rtems_filesystem_fdatasync_t)( - rtems_libio_t *iop +typedef int (*rtems_filesystem_unmount_t) ( + rtems_filesystem_mount_table_entry_t *mt_entry ); /** - * This type defines the interface to the fnctl(2) system call - * support which is provided by a file system implementation. + * @brief Destroys a file system instance. + * + * The mount point node location of the mount table entry is invalid. This + * handler must free the file system root location and all remaining resources + * of the file system instance. + * + * @param[in] mt_entry The mount table entry. + * + * @see rtems_filesystem_default_fsunmount(). */ -typedef int (*rtems_filesystem_fcntl_t)( - int cmd, - rtems_libio_t *iop +typedef void (*rtems_filesystem_fsunmount_me_t)( + rtems_filesystem_mount_table_entry_t *mt_entry ); -typedef int (*rtems_filesystem_rmnod_t)( - rtems_filesystem_location_info_t *parent_loc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */ +/** + * @brief Tests if the node of one location is equal to the node of the other + * location. + * + * The caller ensures that both nodes are within the same file system instance. + * + * @param[in] a The one location. + * @param[in] b The other location. + * + * @retval true The nodes of the locations are equal. + * @retval false Otherwise. + * + * @see rtems_filesystem_default_are_nodes_equal(). + */ +typedef bool (*rtems_filesystem_are_nodes_equal_t)( + const rtems_filesystem_location_info_t *a, + const rtems_filesystem_location_info_t *b ); -/** @} */ - /** - * @brief File system node operations table. + * @brief Returns the node type. + * + * @param[in] loc The location of the node. + * + * @return Type of the node. + * + * @see rtems_filesystem_default_node_type(). */ -struct _rtems_filesystem_file_handlers_r { - /** - * This field points to the file system specific implementation - * of the support routine for the open(2) system call - * - * @note This method must have a filesystem specific implementation. - * - * @note There is no default implementation. - */ - rtems_filesystem_open_t open_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the close(2) system call - * - * @note This method is REQUIRED by all file systems. - * - * @note There is no default implementation. - */ - rtems_filesystem_close_t close_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the read(2) system call - * - * @note This method must have a filesystem specific implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_read_t read_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the write(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_write_t write_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the ioctl(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_ioctl_t ioctl_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the lseek(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_lseek_t lseek_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the fstat(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_fstat_t fstat_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the fchmod(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_fchmod_t fchmod_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the ftruncate(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_ftruncate_t ftruncate_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the fsync(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_fsync_t fsync_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the fdatasync(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_fdatasync_t fdatasync_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the fcntl(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_fcntl_t fcntl_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the rmnod(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_rmnod_t rmnod_h; -}; - -extern const rtems_filesystem_file_handlers_r -rtems_filesystem_handlers_default; +typedef rtems_filesystem_node_types_t (*rtems_filesystem_node_type_t)( + const rtems_filesystem_location_info_t *loc +); /** - * This method defines the interface to the default open(2) - * system call support which is provided by a file system - * implementation. + * @brief Creates a new node. + * + * This handler should create a new node according to the parameters. + * + * @param[in] parentloc The location of the parent of the new node. + * @param[in] name Name for the new node. + * @param[in] namelen Length of the name for the new node in characters. + * @param[in] mode Mode for the new node. + * @param[in] dev Optional device identifier for the new node. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_mknod(). */ -int rtems_filesystem_default_open( - rtems_libio_t *iop, - const char *pathname, - uint32_t flag, - uint32_t mode +typedef int (*rtems_filesystem_mknod_t)( + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev ); /** - * This method defines the interface to the default close(2) - * system call support which is provided by a file system - * implementation. + * @brief Removes a node. + * + * @param[in] parentloc The location of the parent of the node. + * @param[in] loc The location of the node. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_rmnod(). */ -int rtems_filesystem_default_close( - rtems_libio_t *iop +typedef int (*rtems_filesystem_rmnod_t)( + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *loc ); - /** - * This method defines the interface to the default read(2) - * system call support which is provided by a file system - * implementation. + * @brief Set node access and modification times. + * + * @param[in] loc The location of the node. + * @param[in] actime Access time for the node. + * @param[in] modtime Modification for the node. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_utime(). */ -ssize_t rtems_filesystem_default_read( - rtems_libio_t *iop, - void *buffer, - size_t count +typedef int (*rtems_filesystem_utime_t)( + const rtems_filesystem_location_info_t *loc, + time_t actime, + time_t modtime ); /** - * This method defines the interface to the default write(2) system call - * support which is provided by a file system implementation. + * @brief Makes a symbolic link to a node. + * + * @param[in] parentloc The location of the parent of the new symbolic link. + * @param[in] name Name for the new symbolic link. + * @param[in] namelen Length of the name for the new symbolic link in + * characters. + * @param[in] target Contents for the symbolic link. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_symlink(). */ -ssize_t rtems_filesystem_default_write( - rtems_libio_t *iop, - const void *buffer, - size_t count +typedef int (*rtems_filesystem_symlink_t)( + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + const char *target ); /** - * This method defines the interface to the default ioctl(2) system call - * support which is provided by a file system implementation. + * @brief Reads the contents of a symbolic link. + * + * @param[in] loc The location of the symbolic link. + * @param[out] buf The buffer for the contents. + * @param[in] bufsize The size of the buffer in characters. + * + * @retval non-negative Size of the actual contents in characters. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_readlink(). */ -int rtems_filesystem_default_ioctl( - rtems_libio_t *iop, - uint32_t command, - void *buffer +typedef ssize_t (*rtems_filesystem_readlink_t)( + const rtems_filesystem_location_info_t *loc, + char *buf, + size_t bufsize ); /** - * This method defines the interface to the default lseek(2) system call - * support which is provided by a file system implementation. + * @brief Renames a node. + * + * @param[in] oldparentloc The location of the parent of the old node. + * @param[in] oldloc The location of the old node. + * @param[in] newparentloc The location of the parent of the new node. + * @param[in] name Name for the new node. + * @param[in] namelen Length of the name for the new node in characters. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_rename(). */ -off_t rtems_filesystem_default_lseek( - rtems_libio_t *iop, - off_t length, - int whence +typedef int (*rtems_filesystem_rename_t)( + const rtems_filesystem_location_info_t *oldparentloc, + const rtems_filesystem_location_info_t *oldloc, + const rtems_filesystem_location_info_t *newparentloc, + const char *name, + size_t namelen ); /** - * This method defines the interface to the default fstat(2) system call - * support which is provided by a file system implementation. + * @brief Gets file system information. + * + * @param[in] loc The location of a node. + * @param[out] buf Buffer for file system information. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_statvfs(). */ -int rtems_filesystem_default_fstat( - rtems_filesystem_location_info_t *loc, - struct stat *buf +typedef int (*rtems_filesystem_statvfs_t)( + const rtems_filesystem_location_info_t *loc, + struct statvfs *buf ); /** - * This method defines the interface to the default fchmod(2) system call - * support which is provided by a file system implementation. + * @brief File system operations table. */ -int rtems_filesystem_default_fchmod( - rtems_filesystem_location_info_t *loc, - mode_t mode -); +struct _rtems_filesystem_operations_table { + rtems_filesystem_mt_entry_lock_t lock_h; + rtems_filesystem_mt_entry_unlock_t unlock_h; + rtems_filesystem_eval_path_t eval_path_h; + rtems_filesystem_link_t link_h; + rtems_filesystem_are_nodes_equal_t are_nodes_equal_h; + rtems_filesystem_node_type_t node_type_h; + rtems_filesystem_mknod_t mknod_h; + rtems_filesystem_rmnod_t rmnod_h; + rtems_filesystem_fchmod_t fchmod_h; + rtems_filesystem_chown_t chown_h; + rtems_filesystem_clonenode_t clonenod_h; + rtems_filesystem_freenode_t freenod_h; + rtems_filesystem_mount_t mount_h; + rtems_filesystem_fsmount_me_t fsmount_me_h; + rtems_filesystem_unmount_t unmount_h; + rtems_filesystem_fsunmount_me_t fsunmount_me_h; + rtems_filesystem_utime_t utime_h; + rtems_filesystem_symlink_t symlink_h; + rtems_filesystem_readlink_t readlink_h; + rtems_filesystem_rename_t rename_h; + rtems_filesystem_statvfs_t statvfs_h; +}; /** - * This method defines the interface to the default ftruncate(2) system call - * support which is provided by a file system implementation. + * @brief File system operations table with default operations. */ -int rtems_filesystem_default_ftruncate( - rtems_libio_t *iop, - off_t length -); +extern const rtems_filesystem_operations_table + rtems_filesystem_operations_default; /** - * This method defines the interface to the default fsync(2) system call - * support which is provided by a file system implementation. + * @brief Obtains the IO library mutex. + * + * @see rtems_filesystem_mt_entry_lock_t. */ -int rtems_filesystem_default_fsync( - rtems_libio_t *iop +void rtems_filesystem_default_lock( + rtems_filesystem_mount_table_entry_t *mt_entry ); /** - * This method defines the interface to the default fdatasync(2) system call - * support which is provided by a file system implementation. + * @brief Releases the IO library mutex. + * + * @see rtems_filesystem_mt_entry_unlock_t. */ -int rtems_filesystem_default_fdatasync( - rtems_libio_t *iop +void rtems_filesystem_default_unlock( + rtems_filesystem_mount_table_entry_t *mt_entry ); /** - * This method defines the interface to the default fnctl(2) system call - * support which is provided by a file system implementation. + * @brief Terminates the path evaluation and replaces the current location with + * the null location. + * + * @see rtems_filesystem_eval_path_t. */ -int rtems_filesystem_default_fcntl( - int cmd, - rtems_libio_t *iop +void rtems_filesystem_default_eval_path( + rtems_filesystem_eval_path_context_t *ctx ); /** - * This method defines the interface to the default rmnod(2) system call - * support which is provided by a file system implementation. + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_link_t. */ -int rtems_filesystem_default_rmnod( - rtems_filesystem_location_info_t *parent_loc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */ +int rtems_filesystem_default_link( + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *targetloc, + const char *name, + size_t namelen ); /** - * @name File System Operations + * @brief Tests if the node access pointer of one location is equal to + * the node access pointer of the other location. * - * @{ + * @param[in] a The one location. + * @param[in] b The other location. + * + * @retval true The node access pointers of the locations are equal. + * @retval false Otherwise. + * + * @see rtems_filesystem_are_nodes_equal_t. */ +bool rtems_filesystem_default_are_nodes_equal( + const rtems_filesystem_location_info_t *a, + const rtems_filesystem_location_info_t *b +); /** - * This type defines the interface to the mknod(2) system call - * support which is provided by a file system implementation. - * - * @note This routine does not allocate any space and - * rtems_filesystem_freenode_t is not called by the generic - * after calling this routine. ie. node_access does not have - * to contain valid data when the routine returns. + * @retval RTEMS_FILESYSTEM_INVALID_NODE_TYPE Always. + * + * @see rtems_filesystem_node_type_t. */ -typedef int (*rtems_filesystem_mknod_t)( - const char *path, /* IN */ - mode_t mode, /* IN */ - dev_t dev, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN/OUT */ +rtems_filesystem_node_types_t rtems_filesystem_default_node_type( + const rtems_filesystem_location_info_t *pathloc ); /** - * This type defines the interface that allows the - * file system implementation to parse a path and - * allocate any memory necessary for tracking purposes. + * @retval -1 Always. The errno is set to ENOTSUP. * - * @note rtems_filesystem_freenode_t must be called by - * the generic after calling this routine + * @see rtems_filesystem_mknod_t. */ -typedef int (*rtems_filesystem_evalpath_t)( - const char *pathname, /* IN */ - size_t pathnamelen, /* IN */ - int flags, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN/OUT */ +int rtems_filesystem_default_mknod( + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev ); /** - * This type defines the interface that allows the - * file system implementation to parse a path with the - * intent of creating a new node and to - * allocate any memory necessary for tracking purposes. + * @retval -1 Always. The errno is set to ENOTSUP. * - * @note rtems_filesystem_freenode_t must be called by - * the generic after calling this routine + * @see rtems_filesystem_rmnod_t. */ -typedef int (*rtems_filesystem_evalmake_t)( - const char *path, /* IN */ - rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ - const char **name /* OUT */ +int rtems_filesystem_default_rmnod( + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *loc ); /** - * This type defines the interface to the link(2) system call - * support which is provided by a file system implementation. - */ -typedef int (*rtems_filesystem_link_t)( - rtems_filesystem_location_info_t *to_loc, /* IN */ - rtems_filesystem_location_info_t *parent_loc, /* IN */ - const char *name /* IN */ + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_fchmod_t. + */ +int rtems_filesystem_default_fchmod( + const rtems_filesystem_location_info_t *loc, + mode_t mode ); /** - * This type defines the interface to the unlink(2) system call - * support which is provided by a file system implementation. - */ -typedef int (*rtems_filesystem_unlink_t)( - rtems_filesystem_location_info_t *parent_pathloc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */ + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_chown_t. + */ +int rtems_filesystem_default_chown( + const rtems_filesystem_location_info_t *loc, + uid_t owner, + gid_t group ); /** - * This type defines the interface to the chown(2) system call - * support which is provided by a file system implementation. - */ -typedef int (*rtems_filesystem_chown_t)( - rtems_filesystem_location_info_t *pathloc, /* IN */ - uid_t owner, /* IN */ - gid_t group /* IN */ + * @retval 0 Always. + * + * @see rtems_filesystem_clonenode_t. + */ +int rtems_filesystem_default_clonenode( + rtems_filesystem_location_info_t *loc ); /** - * This type defines the interface to the freenod(2) system call - * support which is provided by a file system implementation. - */ -typedef int (*rtems_filesystem_freenode_t)( - rtems_filesystem_location_info_t *pathloc /* IN */ + * @see rtems_filesystem_freenode_t. + */ +void rtems_filesystem_default_freenode( + const rtems_filesystem_location_info_t *loc ); /** - * This type defines the interface that allows the implemented - * filesystem ot mount another filesystem at the given location. - */ -typedef int (* rtems_filesystem_mount_t ) ( + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_mount_t. + */ +int rtems_filesystem_default_mount ( rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ ); /** - * This type defines the interface that allows a file system - * implementation to do any necessary work that is needed when - * it is being mounted. - */ -typedef int (* rtems_filesystem_fsmount_me_t )( + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_fsmount_me_t. + */ +int rtems_filesystem_default_fsmount( rtems_filesystem_mount_table_entry_t *mt_entry, /* IN */ const void *data /* IN */ ); /** - * This type defines the interface allow the filesystem to - * unmount a filesystem that was mounted at one of its node - * locations. - */ -typedef int (* rtems_filesystem_unmount_t ) ( + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_unmount_t. + */ +int rtems_filesystem_default_unmount( rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ ); /** - * This type defines the interface that allows a file system - * implementation to do any necessary work that is needed when - * it is being unmounted. - */ -typedef int (* rtems_filesystem_fsunmount_me_t ) ( + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_fsunmount_me_t. + */ +void rtems_filesystem_default_fsunmount( rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ ); /** - * This type defines the interface that will return the - * type of a filesystem implementations node. - */ -typedef rtems_filesystem_node_types_t (* rtems_filesystem_node_type_t) ( - rtems_filesystem_location_info_t *pathloc /* IN */ + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_utime_t. + */ +int rtems_filesystem_default_utime( + const rtems_filesystem_location_info_t *loc, + time_t actime, + time_t modtime ); /** - * This type defines the interface to the time(2) system call - * support which is provided by a file system implementation. - */ -typedef int (* rtems_filesystem_utime_t)( - rtems_filesystem_location_info_t *pathloc, /* IN */ - time_t actime, /* IN */ - time_t modtime /* IN */ + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_symlink_t. + */ +int rtems_filesystem_default_symlink( + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + const char *target ); /** - * This type defines the interface to the link(2) system call - * support which is provided by a file system implementation. - */ -typedef int (*rtems_filesystem_evaluate_link_t)( - rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ - int flags /* IN */ + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_readlink_t. + */ +ssize_t rtems_filesystem_default_readlink( + const rtems_filesystem_location_info_t *loc, + char *buf, + size_t bufsize ); /** - * This type defines the interface to the symlink(2) system call - * support which is provided by a file system implementation. - */ -typedef int (*rtems_filesystem_symlink_t)( - rtems_filesystem_location_info_t *loc, /* IN */ - const char *link_name, /* IN */ - const char *node_name + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_rename_t. + */ +int rtems_filesystem_default_rename( + const rtems_filesystem_location_info_t *oldparentloc, + const rtems_filesystem_location_info_t *oldloc, + const rtems_filesystem_location_info_t *newparentloc, + const char *name, + size_t namelen ); /** - * This type defines the interface to the readlink(2) system call - * support which is provided by a file system implementation. - */ -typedef ssize_t (*rtems_filesystem_readlink_t)( - rtems_filesystem_location_info_t *loc, /* IN */ - char *buf, /* OUT */ - size_t bufsize + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_statvfs_t. + */ +int rtems_filesystem_default_statvfs( + const rtems_filesystem_location_info_t *loc, + struct statvfs *buf ); +/** @} */ + /** - * This type defines the interface to the name(2) system call - * support which is provided by a file system implementation. - */ -typedef int (*rtems_filesystem_rename_t)( - rtems_filesystem_location_info_t *old_parent_loc, /* IN */ - rtems_filesystem_location_info_t *old_loc, /* IN */ - rtems_filesystem_location_info_t *new_parent_loc, /* IN */ - const char *name /* IN */ -); + * @defgroup LibIOFSHandler File System Node Handler + * + * @ingroup LibIO + * + * @brief File system node handler. + * + * @{ + */ /** - * This type defines the interface to the statvfs(2) system call - * support which is provided by a file system implementation. - */ -typedef int (*rtems_filesystem_statvfs_t)( - rtems_filesystem_location_info_t *loc, /* IN */ - struct statvfs *buf /* OUT */ + * @brief Opens a node. + * + * @param[in, out] iop The IO pointer. + * @param[in] path The path. + * @param[in] oflag The open flags. + * @param[in] mode Optional mode for node creation. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_open(). + */ +typedef int (*rtems_filesystem_open_t)( + rtems_libio_t *iop, + const char *path, + int oflag, + mode_t mode ); -/** @} */ - /** - * @brief File system operations table. + * @brief Closes a node. + * + * @param[in, out] iop The IO pointer. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_close(). */ -struct _rtems_filesystem_operations_table { +typedef int (*rtems_filesystem_close_t)( + rtems_libio_t *iop +); - /** - * This field points to the file system specific implementation - * of the support routine that evaluates a character path and - * returns the node assocated with the last node in the path. - * - * @note This method must have a filesystem specific implementation. - * - * @note There is no default implementation. - */ - rtems_filesystem_evalpath_t evalpath_h; - - /** - * This field points to the file system specific implementation - * of the support routine that evaluates a character path and - * returns the node assocated with next to the last node in - * the path. The last node will be the new node to be created. - * - * @note This method must have a filesystem specific implementation. - * - * @note There is no default implementation. - */ - rtems_filesystem_evalmake_t evalformake_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the link(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_link_t link_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the unlink(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_unlink_t unlink_h; - - /** - * This field points to the file system specific implementation - * of a method that returns the node type of the given node. - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_node_type_t node_type_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the link(2) system call - * - * @note This method may use a mknod implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_mknod_t mknod_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the link(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_chown_t chown_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the freenod(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_freenode_t freenod_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the mount(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_mount_t mount_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the fsmount(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_fsmount_me_t fsmount_me_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the unmount(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_unmount_t unmount_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the fsunmount(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_fsunmount_me_t fsunmount_me_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the utime(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_utime_t utime_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the eval_link(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_evaluate_link_t eval_link_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the sumlink(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_symlink_t symlink_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the readlink(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_readlink_t readlink_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the rename(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_rename_t rename_h; - - /** - * This field points to the file system specific implementation - * of the support routine for the statvfs(2) system call - * - * @note This method may use a default implementation. - * - * @note The default implementation returns -1 and sets - * errno to ENOTSUP. - */ - rtems_filesystem_statvfs_t statvfs_h; -}; +/** + * @brief Reads from a node. + * + * @param[in, out] iop The IO pointer. + * @param[out] buffer The buffer for read data. + * @param[in] count The size of the buffer in characters. + * + * @retval non-negative Count of read characters. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_read(). + */ +typedef ssize_t (*rtems_filesystem_read_t)( + rtems_libio_t *iop, + void *buffer, + size_t count +); -extern const rtems_filesystem_operations_table -rtems_filesystem_operations_default; +/** + * @brief Writes to a node. + * + * @param[in, out] iop The IO pointer. + * @param[out] buffer The buffer for write data. + * @param[in] count The size of the buffer in characters. + * + * @retval non-negative Count of written characters. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_write(). + */ +typedef ssize_t (*rtems_filesystem_write_t)( + rtems_libio_t *iop, + const void *buffer, + size_t count +); /** - * @brief Provides a defualt routine for filesystem - * implementation of path evaluation. + * @brief IO control of a node. + * + * @param[in, out] iop The IO pointer. + * @param[in] request The IO control request. + * @param[in, out] buffer The buffer for IO control request data. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_ioctl(). */ -int rtems_filesystem_default_evalpath( - const char *pathname, - size_t pathnamelen, - int flags, - rtems_filesystem_location_info_t *pathloc +typedef int (*rtems_filesystem_ioctl_t)( + rtems_libio_t *iop, + uint32_t request, + void *buffer ); /** - * @brief Provides a defualt routine for filesystem - * implementation of path evaluation for make. + * @brief Moves the read/write file offset. + * + * @param[in, out] iop The IO pointer. + * @param[in] offset The new offset. + * @param[in] whence The reference position of the new offset. + * + * @retval non-negative The new offset from the beginning of the file. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_lseek(). */ -int rtems_filesystem_default_evalformake( - const char *path, - rtems_filesystem_location_info_t *pathloc, - const char **name +typedef off_t (*rtems_filesystem_lseek_t)( + rtems_libio_t *iop, + off_t offset, + int whence ); /** - * @brief Provides a defualt routine for filesystem - * implementation of a link command. + * @brief Gets a node status. + * + * @param[in, out] iop The IO pointer. + * @param[out] stat The buffer to status information. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_fstat(). */ -int rtems_filesystem_default_link( - rtems_filesystem_location_info_t *to_loc, /* IN */ - rtems_filesystem_location_info_t *parent_loc, /* IN */ - const char *name /* IN */ +typedef int (*rtems_filesystem_fstat_t)( + const rtems_filesystem_location_info_t *loc, + struct stat *buf ); /** - * @brief Provides a defualt routine for filesystem - * implementation of a unlink command. + * @brief Truncates a file to a specified length. + * + * @param[in, out] iop The IO pointer. + * @param[in] length The new length in characters. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_ftruncate() and + * rtems_filesystem_default_ftruncate_directory(). */ -int rtems_filesystem_default_unlink( - rtems_filesystem_location_info_t *parent_pathloc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */ +typedef int (*rtems_filesystem_ftruncate_t)( + rtems_libio_t *iop, + off_t length ); /** - * @brief Provides a defualt routine for filesystem - * implementation to determine the node type. + * @brief Synchronizes changes to a file. + * + * @param[in, out] iop The IO pointer. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_fsync(). */ -rtems_filesystem_node_types_t rtems_filesystem_default_node_type( - rtems_filesystem_location_info_t *pathloc +typedef int (*rtems_filesystem_fsync_t)( + rtems_libio_t *iop ); /** - * @brief Provides a defualt routine for filesystem - * implementation to create a new node. + * @brief Synchronizes the data of a file. + * + * @param[in, out] iop The IO pointer. + * + * @retval 0 Successful operation. + * @retval -1 An error occured. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_fdatasync(). */ -int rtems_filesystem_default_mknod( - const char *path, /* IN */ - mode_t mode, /* IN */ - dev_t dev, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN/OUT */ +typedef int (*rtems_filesystem_fdatasync_t)( + rtems_libio_t *iop ); /** - * @brief Provides a defualt routine for filesystem - * implementation of a chown command. + * @brief File control. + * + * @param[in, out] iop The IO pointer. + * @param[in] cmd Control command. + * + * @retval 0 Successful operation. + * @retval errno An error occured. This value is assigned to errno. + * + * @see rtems_filesystem_default_fcntl(). */ -int rtems_filesystem_default_chown( - rtems_filesystem_location_info_t *pathloc, /* IN */ - uid_t owner, /* IN */ - gid_t group /* IN */ +typedef int (*rtems_filesystem_fcntl_t)( + rtems_libio_t *iop, + int cmd ); /** - * @brief Provides a defualt routine for filesystem - * implementation of a freenode command. + * @brief File system node operations table. + */ +struct _rtems_filesystem_file_handlers_r { + rtems_filesystem_open_t open_h; + rtems_filesystem_close_t close_h; + rtems_filesystem_read_t read_h; + rtems_filesystem_write_t write_h; + rtems_filesystem_ioctl_t ioctl_h; + rtems_filesystem_lseek_t lseek_h; + rtems_filesystem_fstat_t fstat_h; + rtems_filesystem_ftruncate_t ftruncate_h; + rtems_filesystem_fsync_t fsync_h; + rtems_filesystem_fdatasync_t fdatasync_h; + rtems_filesystem_fcntl_t fcntl_h; +}; + +/** + * @brief File system node handler table with default node handlers. + */ +extern const rtems_filesystem_file_handlers_r + rtems_filesystem_handlers_default; + +/** + * @retval 0 Always. + * + * @see rtems_filesystem_open_t. */ -int rtems_filesystem_default_freenode( - rtems_filesystem_location_info_t *pathloc /* IN */ +int rtems_filesystem_default_open( + rtems_libio_t *iop, + const char *path, + int oflag, + mode_t mode ); /** - * @brief Provides a defualt routine for filesystem - * implementation of a mount command. + * @retval 0 Always. + * + * @see rtems_filesystem_close_t. */ -int rtems_filesystem_default_mount ( - rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ +int rtems_filesystem_default_close( + rtems_libio_t *iop ); /** - * @brief Provides a defualt routine for filesystem - * implementation of a fsmount command. + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_read_t. */ -int rtems_filesystem_default_fsmount( - rtems_filesystem_mount_table_entry_t *mt_entry, /* IN */ - const void *data /* IN */ +ssize_t rtems_filesystem_default_read( + rtems_libio_t *iop, + void *buffer, + size_t count ); /** - * @brief Provides a defualt routine for filesystem - * implementation of a unmount command. + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_write_t. */ -int rtems_filesystem_default_unmount( - rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ +ssize_t rtems_filesystem_default_write( + rtems_libio_t *iop, + const void *buffer, + size_t count ); /** - * @brief Provides a defualt routine for filesystem - * implementation of a fsunmount command. + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_ioctl_t. */ -int rtems_filesystem_default_fsunmount( - rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ +int rtems_filesystem_default_ioctl( + rtems_libio_t *iop, + uint32_t command, + void *buffer ); +/** + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_lseek_t. + */ +off_t rtems_filesystem_default_lseek( + rtems_libio_t *iop, + off_t length, + int whence +); /** - * @brief Provides a defualt routine for filesystem - * implementation of a utime command. + * @brief Sets the mode to S_IRWXU | S_IRWXG | S_IRWXO. + * + * @retval 0 Always. + * + * @see rtems_filesystem_fstat_t. */ -int rtems_filesystem_default_utime( - rtems_filesystem_location_info_t *pathloc, /* IN */ - time_t actime, /* IN */ - time_t modtime /* IN */ +int rtems_filesystem_default_fstat( + const rtems_filesystem_location_info_t *loc, + struct stat *buf ); /** - * @brief Provides a defualt routine for filesystem - * implementation of a link command. + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_ftruncate_t. */ -int rtems_filesystem_default_evaluate_link( - rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ - int flags /* IN */ +int rtems_filesystem_default_ftruncate( + rtems_libio_t *iop, + off_t length ); /** - * @brief Provides a defualt routine for filesystem - * implementation of a symlink command. + * @retval -1 Always. The errno is set to EISDIR. + * + * @see rtems_filesystem_ftruncate_t. */ -int rtems_filesystem_default_symlink( - rtems_filesystem_location_info_t *loc, /* IN */ - const char *link_name, /* IN */ - const char *node_name +int rtems_filesystem_default_ftruncate_directory( + rtems_libio_t *iop, + off_t length ); /** - * @brief Provides a defualt routine for filesystem - * implementation of a readlink command. + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_fsync_t. */ -ssize_t rtems_filesystem_default_readlink( - rtems_filesystem_location_info_t *loc, /* IN */ - char *buf, /* OUT */ - size_t bufsize +int rtems_filesystem_default_fsync( + rtems_libio_t *iop ); /** - * @brief Provides a defualt routine for filesystem - * implementation of a rename command. + * @retval -1 Always. The errno is set to ENOTSUP. + * + * @see rtems_filesystem_fdatasync_t. */ -int rtems_filesystem_default_rename( - rtems_filesystem_location_info_t *old_parent_loc, /* IN */ - rtems_filesystem_location_info_t *old_loc, /* IN */ - rtems_filesystem_location_info_t *new_parent_loc, /* IN */ - const char *name /* IN */ +int rtems_filesystem_default_fdatasync( + rtems_libio_t *iop ); /** - * @brief Provides a defualt routine for filesystem - * implementation of a statvfs command. + * @retval 0 Always. + * + * @see rtems_filesystem_fcntl_t. */ -int rtems_filesystem_default_statvfs( - rtems_filesystem_location_info_t *loc, /* IN */ - struct statvfs *buf /* OUT */ +int rtems_filesystem_default_fcntl( + rtems_libio_t *iop, + int cmd ); +/** @} */ + +/** + * @defgroup LibIO IO Library + * + * @brief Provides system call and file system interface definitions. + * + * General purpose communication channel for RTEMS to allow UNIX/POSIX + * system call behavior under RTEMS. Initially this supported only + * IO to devices but has since been enhanced to support networking + * and support for mounted file systems. + * + * @{ + */ + +typedef off_t rtems_off64_t __attribute__((deprecated)); + /** * @brief Gets the mount handler for the file system @a type. * @@ -1067,7 +1135,8 @@ typedef struct { * * Override in a filesystem. */ -extern const rtems_filesystem_limits_and_options_t rtems_filesystem_default_pathconf; +extern const rtems_filesystem_limits_and_options_t + rtems_filesystem_default_pathconf; /** * @brief An open file data structure. @@ -1194,12 +1263,22 @@ typedef off_t (*rtems_libio_lseek_t)( * used to check permissions. These are similar in style to the * mode_t bits and should stay compatible with them. */ -#define RTEMS_LIBIO_PERMS_READ S_IROTH -#define RTEMS_LIBIO_PERMS_WRITE S_IWOTH -#define RTEMS_LIBIO_PERMS_RDWR (S_IROTH|S_IWOTH) -#define RTEMS_LIBIO_PERMS_EXEC S_IXOTH +#define RTEMS_LIBIO_PERMS_READ 0x4 +#define RTEMS_LIBIO_PERMS_WRITE 0x2 +#define RTEMS_LIBIO_PERMS_EXEC 0x1 #define RTEMS_LIBIO_PERMS_SEARCH RTEMS_LIBIO_PERMS_EXEC -#define RTEMS_LIBIO_PERMS_RWX S_IRWXO +#define RTEMS_LIBIO_PERMS_RDWR \ + (RTEMS_LIBIO_PERMS_READ | RTEMS_LIBIO_PERMS_WRITE) +#define RTEMS_LIBIO_PERMS_RWX \ + (RTEMS_LIBIO_PERMS_RDWR | RTEMS_LIBIO_PERMS_EXEC) +#define RTEMS_LIBIO_FOLLOW_HARD_LINK 0x8 +#define RTEMS_LIBIO_FOLLOW_SYM_LINK 0x10 +#define RTEMS_LIBIO_FOLLOW_LINK \ + (RTEMS_LIBIO_FOLLOW_HARD_LINK | RTEMS_LIBIO_FOLLOW_SYM_LINK) +#define RTEMS_LIBIO_MAKE 0x20 +#define RTEMS_LIBIO_EXCLUSIVE 0x40 +#define RTEMS_LIBIO_ACCEPT_RESIDUAL_DELIMITERS 0x80 +#define RTEMS_LIBIO_REJECT_TERMINAL_DOT 0x100 /** @} */ @@ -1251,12 +1330,6 @@ static inline rtems_device_minor_number rtems_filesystem_dev_minor_t( } while(0) /* - * Verifies that the permission flag is valid. - */ -#define rtems_libio_is_valid_perms( _perm ) \ - (((~RTEMS_LIBIO_PERMS_RWX) & _perm ) == 0) - -/* * Prototypes for filesystem */ @@ -1317,12 +1390,14 @@ extern int rtems_mkdir(const char *path, mode_t mode); * @brief Mount table entry. */ struct rtems_filesystem_mount_table_entry_tt { - rtems_chain_node Node; - rtems_filesystem_location_info_t mt_point_node; - rtems_filesystem_location_info_t mt_fs_root; - int options; + rtems_chain_node mt_node; + rtems_chain_control location_chain; + rtems_filesystem_global_location_t *mt_point_node; + rtems_filesystem_global_location_t *mt_fs_root; + bool mounted; + bool writeable; void *fs_info; - + const void *immutable_fs_info; rtems_filesystem_limits_and_options_t pathconf_limits_and_options; /* @@ -1369,6 +1444,8 @@ typedef struct rtems_filesystem_table_t { */ extern const rtems_filesystem_table_t rtems_filesystem_table []; +extern rtems_chain_control rtems_filesystem_mount_table; + /** * @brief Registers a file system @a type. * @@ -1498,60 +1575,46 @@ bool rtems_filesystem_iterate( ); /** - * @brief Per file system mount routine. - * - * @see rtems_filesystem_mount_iterate(). + * @brief Mount table entry visitor. * * @retval true Stop the iteration. * @retval false Continue the iteration. + * + * @see rtems_filesystem_mount_iterate(). */ -typedef bool (*rtems_per_filesystem_mount_routine)( +typedef bool (*rtems_filesystem_mt_entry_visitor)( const rtems_filesystem_mount_table_entry_t *mt_entry, void *arg ); /** - * @brief Iterates over all file system mounts. - * - * For each file system mount the @a routine will be called with the entry and - * the @a routine_arg parameter. + * @brief Iterates over all file system mount entries. * - * Do not mount or unmount file systems in @a routine. + * The iteration is protected by the IO library mutex. Do not mount or unmount + * file systems in the visitor function. * - * The iteration is protected by the IO library mutex. + * @param[in] visitor For each file system mount entry the visitor function + * will be called with the entry and the visitor argument as parameters. + * @param[in] visitor_arg The second parameter for the visitor function. * - * @retval true Iteration stopped due to @a routine return status. + * @retval true Iteration stopped due to visitor function return status. * @retval false Iteration through all entries. */ -bool -rtems_filesystem_mount_iterate( - rtems_per_filesystem_mount_routine routine, - void *routine_arg +bool rtems_filesystem_mount_iterate( + rtems_filesystem_mt_entry_visitor visitor, + void *visitor_arg ); -/** - * @brief Boot time mount table entry. - */ typedef struct { - const char *type; - rtems_filesystem_options_t fsoptions; - const char *device; - const char *mount_point; -} rtems_filesystem_mount_table_t; - -/** - * @brief Boot time mount table. - * - * @todo Only the first entry will be evaluated. Why do we need a table? - */ -extern const rtems_filesystem_mount_table_t *rtems_filesystem_mount_table; - -/** - * @brief Boot time mount table entry count. - * - * @todo Only the first entry will be evaluated. Why do we need a table? - */ -extern const int rtems_filesystem_mount_table_size; + const char *source; + const char *target; + const char *filesystemtype; + rtems_filesystem_options_t options; + const void *data; +} rtems_filesystem_mount_configuration; + +extern const rtems_filesystem_mount_configuration + rtems_filesystem_root_configuration; /** @} */ diff --git a/cpukit/libcsupport/include/rtems/libio_.h b/cpukit/libcsupport/include/rtems/libio_.h index e0396daa24..84882908fb 100644 --- a/cpukit/libcsupport/include/rtems/libio_.h +++ b/cpukit/libcsupport/include/rtems/libio_.h @@ -8,6 +8,9 @@ * COPYRIGHT (c) 1989-2011. * 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. @@ -18,17 +21,18 @@ #ifndef _RTEMS_RTEMS_LIBIO__H #define _RTEMS_RTEMS_LIBIO__H -#include <rtems.h> -#include <rtems/libio.h> /* include before standard IO */ - -#include <sys/types.h> - #include <errno.h> +#include <rtems.h> +#include <rtems/libio.h> +#include <rtems/seterr.h> + #ifdef __cplusplus extern "C" { #endif +#define RTEMS_FILESYSTEM_SYMLOOP_MAX 32 + /* * Semaphore to protect the io table */ @@ -47,6 +51,27 @@ extern rtems_libio_t *rtems_libio_iops; extern rtems_libio_t *rtems_libio_last_iop; extern rtems_libio_t *rtems_libio_iop_freelist; +extern const rtems_filesystem_file_handlers_r rtems_filesystem_null_handlers; + +extern rtems_filesystem_mount_table_entry_t rtems_filesystem_null_mt_entry; + +/** + * @brief The global null location. + * + * Every operation and the open and fstat handlers of this location returns an + * error status. The errno is not touched by these operations and handlers. + * The purpose of this location is to deliver the error return status for a + * previous error condition which must set the errno accordingly. + * + * The usage of this null location instead of the NULL pointer eliminates a lot + * of branches. + * + * The user environment root and current directory are statically initialized + * with the null location. Due to that all file system services are in a + * defined state even if no root file system was mounted. + */ +extern rtems_filesystem_global_location_t rtems_filesystem_global_location_null; + /* * rtems_libio_iop * @@ -147,28 +172,54 @@ extern rtems_libio_t *rtems_libio_iop_freelist; #define rtems_libio_check_permissions(_iop, _flag) \ rtems_libio_check_permissions_with_error(_iop, _flag, EINVAL ) -/* - * rtems_filesystem_freenode +/** + * @brief Clones a node. * - * Macro to free a node. + * The caller must hold the file system instance lock. + * + * @param[out] clone The cloned location. + * @param[in] master The master location. + * + * @see rtems_filesystem_instance_lock(). */ +void rtems_filesystem_location_clone( + rtems_filesystem_location_info_t *clone, + const rtems_filesystem_location_info_t *master +); -void rtems_filesystem_freenode( rtems_filesystem_location_info_t* node ); - -/* - * External structures +/** + * @brief Returns the type of a node. + * + * This function obtains and releases the file system instance lock. + * + * @param[in] loc The location of the node. + * + * @return The node type. + * + * @see rtems_filesystem_instance_lock(). */ -#include <rtems/userenv.h> +rtems_filesystem_node_types_t rtems_filesystem_node_type( + const rtems_filesystem_location_info_t *loc +); -extern rtems_user_env_t * rtems_current_user_env; -extern rtems_user_env_t rtems_global_user_env; +/** + * @brief Releases all resources of a location. + * + * This function may block on a mutex and may complete an unmount process. + * + * @param[in] loc The location to free. + * + * @note The file system root location is released by the file system instance + * destruction handler (see @ref rtems_filesystem_fsunmount_me_t). + * + * @see rtems_filesystem_freenode_t. + */ +void rtems_filesystem_location_free( rtems_filesystem_location_info_t *loc ); /* - * Instantiate a private copy of the per user information for the calling task. + * External structures */ - -rtems_status_code rtems_libio_set_private_env(void); -rtems_status_code rtems_libio_share_private_env(rtems_id task_id) ; +#include <rtems/userenv.h> static inline void rtems_libio_lock( void ) { @@ -180,80 +231,569 @@ static inline void rtems_libio_unlock( void ) rtems_semaphore_release( rtems_libio_semaphore ); } +static inline void rtems_filesystem_mt_lock( void ) +{ + rtems_libio_lock(); +} + +static inline void rtems_filesystem_mt_unlock( void ) +{ + rtems_libio_unlock(); +} + +#define rtems_filesystem_mt_entry_declare_lock_context( ctx ) \ + rtems_interrupt_level ctx + +#define rtems_filesystem_mt_entry_lock( ctx ) rtems_interrupt_disable( ctx ) + +#define rtems_filesystem_mt_entry_unlock( ctx ) rtems_interrupt_enable( ctx ) + +static inline void rtems_filesystem_instance_lock( + const rtems_filesystem_location_info_t *loc +) +{ + (*loc->ops->lock_h)( loc->mt_entry ); +} + +static inline void rtems_filesystem_instance_unlock( + const rtems_filesystem_location_info_t *loc +) +{ + (*loc->ops->unlock_h)( loc->mt_entry ); +} + /* * File Descriptor Routine Prototypes */ rtems_libio_t *rtems_libio_allocate(void); -uint32_t rtems_libio_fcntl_flags( - uint32_t fcntl_flags -); +uint32_t rtems_libio_fcntl_flags( int fcntl_flags ); -uint32_t rtems_libio_to_fcntl_flags( - uint32_t flags -); +int rtems_libio_to_fcntl_flags( uint32_t flags ); void rtems_libio_free( rtems_libio_t *iop ); -int rtems_libio_is_open_files_in_fs( - rtems_filesystem_mount_table_entry_t *mt_entry +/* + * File System Routine Prototypes + */ + +rtems_filesystem_location_info_t * +rtems_filesystem_eval_path_start( + rtems_filesystem_eval_path_context_t *ctx, + const char *path, + int eval_flags ); -int rtems_libio_is_file_open( - void *node_access +rtems_filesystem_location_info_t * +rtems_filesystem_eval_path_start_with_parent( + rtems_filesystem_eval_path_context_t *ctx, + const char *path, + int eval_flags, + rtems_filesystem_location_info_t *parentloc, + int parent_eval_flags ); -/* - * File System Routine Prototypes - */ +rtems_filesystem_location_info_t * +rtems_filesystem_eval_path_start_with_root_and_current( + rtems_filesystem_eval_path_context_t *ctx, + const char *path, + int eval_flags, + rtems_filesystem_global_location_t *const *global_root_ptr, + rtems_filesystem_global_location_t *const *global_current_ptr +); + +void rtems_filesystem_eval_path_continue( + rtems_filesystem_eval_path_context_t *ctx +); -int rtems_filesystem_evaluate_relative_path( - const char *pathname, - size_t pathnamelen, - int flags, - rtems_filesystem_location_info_t *pathloc, - int follow_link +void rtems_filesystem_eval_path_cleanup( + rtems_filesystem_eval_path_context_t *ctx ); -int rtems_filesystem_evaluate_path( - const char *pathname, - size_t pathnamelen, - int flags, - rtems_filesystem_location_info_t *pathloc, - int follow_link +void rtems_filesystem_eval_path_recursive( + rtems_filesystem_eval_path_context_t *ctx, + const char *path, + size_t pathlen ); -int rtems_filesystem_dirname( - const char *pathname +void rtems_filesystem_eval_path_cleanup_with_parent( + rtems_filesystem_eval_path_context_t *ctx, + rtems_filesystem_location_info_t *parentloc ); -int rtems_filesystem_prefix_separators( - const char *pathname, - int pathnamelen +/** + * @brief Requests a path evaluation restart. + * + * Sets the start and current location to the new start location. The caller + * must terminate its current evaluation process. The path evaluation + * continues in the next loop iteration within + * rtems_filesystem_eval_path_continue(). This avoids recursive invokations. + * The function obtains the new start location and clones it to set the new + * current location. The previous start and current locations are released. + * + * @param[in, out] ctx The path evaluation context. + * @param[in, out] newstartloc_ptr Pointer to new start location. + */ +void rtems_filesystem_eval_path_restart( + rtems_filesystem_eval_path_context_t *ctx, + rtems_filesystem_global_location_t **newstartloc_ptr +); + +typedef enum { + RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE, + RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE, + RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY +} rtems_filesystem_eval_path_generic_status; + +/** + * @brief Tests if the current location is a directory. + * + * @param[in, out] ctx The path evaluation context. + * @param[in, out] arg The handler argument. + * + * @retval true The current location is a directory. + * @retval false Otherwise. + * + * @see rtems_filesystem_eval_path_generic(). + */ +typedef bool (*rtems_filesystem_eval_path_is_directory)( + rtems_filesystem_eval_path_context_t *ctx, + void *arg +); + +/** + * @brief Evaluates a token. + * + * @param[in, out] ctx The path evaluation context. + * @param[in, out] arg The handler argument. + * @param[in] token The token contents. + * @param[in] tokenlen The token length in characters. + * + * @retval status The generic path evaluation status. + * + * @see rtems_filesystem_eval_path_generic(). + */ +typedef rtems_filesystem_eval_path_generic_status +(*rtems_filesystem_eval_path_eval_token)( + rtems_filesystem_eval_path_context_t *ctx, + void *arg, + const char *token, + size_t tokenlen +); + +typedef struct { + rtems_filesystem_eval_path_is_directory is_directory; + rtems_filesystem_eval_path_eval_token eval_token; +} rtems_filesystem_eval_path_generic_config; + +void rtems_filesystem_eval_path_generic( + rtems_filesystem_eval_path_context_t *ctx, + void *arg, + const rtems_filesystem_eval_path_generic_config *config ); void rtems_filesystem_initialize(void); -int init_fs_mount_table(void); +/** + * @brief Copies a location. + * + * A bitwise copy is performed. The destination location will be added to the + * corresponding mount entry. + * + * @param[out] dst The destination location. + * @param[in] src The source location. + * + * @retval dst The destination location. + * + * @see rtems_filesystem_location_clone(). + */ +rtems_filesystem_location_info_t *rtems_filesystem_location_copy( + rtems_filesystem_location_info_t *dst, + const rtems_filesystem_location_info_t *src +); + +static inline rtems_filesystem_location_info_t * +rtems_filesystem_location_initialize_to_null( + rtems_filesystem_location_info_t *loc +) +{ + return rtems_filesystem_location_copy( + loc, + &rtems_filesystem_global_location_null.location + ); +} -int rtems_filesystem_is_separator(char ch); +rtems_filesystem_global_location_t * +rtems_filesystem_location_transform_to_global( + rtems_filesystem_location_info_t *loc +); -void rtems_filesystem_get_start_loc(const char *path, - int *index, - rtems_filesystem_location_info_t *loc); +/** + * @brief Assigns a global file system location. + * + * @param[in, out] lhs_global_loc_ptr Pointer to the global left hand side file + * system location. The current left hand side location will be released. + * @param[in] rhs_global_loc The global right hand side file system location. + */ +void rtems_filesystem_global_location_assign( + rtems_filesystem_global_location_t **lhs_global_loc_ptr, + rtems_filesystem_global_location_t *rhs_global_loc +); -void rtems_filesystem_get_sym_start_loc(const char *path, - int *index, - rtems_filesystem_location_info_t *loc); +/** + * @brief Obtains a global file system location. + * + * Deferred releases will be processed in this function. + * + * This function must be called from normal thread context and may block on a + * mutex. Thread dispatching is disabled to protect some critical sections. + * + * @param[in] global_loc_ptr Pointer to the global file system location. + * + * @return A global file system location. It returns always a valid object. + * In case of an error, the global null location will be returned. Each + * operation or handler of the null location returns an error status. The + * errno indicates the error. The NULL pointer is never returned. + * + * @see rtems_filesystem_location_transform_to_global(), + * rtems_filesystem_global_location_obtain_null(), and + * rtems_filesystem_global_location_release(). + */ +rtems_filesystem_global_location_t *rtems_filesystem_global_location_obtain( + rtems_filesystem_global_location_t *const *global_loc_ptr +); + +/** + * @brief Releases a global file system location. + * + * In case the reference count reaches zero, all associated resources will be + * released. This may include the complete unmount of the corresponding file + * system instance. + * + * This function may block on a mutex. It may be called within critical + * sections of the operating system. In this case the release will be + * deferred. The next obtain call will do the actual release. + * + * @param[in] global_loc The global file system location. It must not be NULL. + * + * @see rtems_filesystem_global_location_obtain(). + */ +void rtems_filesystem_global_location_release( + rtems_filesystem_global_location_t *global_loc +); + +void rtems_filesystem_location_detach( + rtems_filesystem_location_info_t *detach +); + +void rtems_filesystem_location_copy_and_detach( + rtems_filesystem_location_info_t *copy, + rtems_filesystem_location_info_t *detach +); + +static inline rtems_filesystem_global_location_t * +rtems_filesystem_global_location_obtain_null(void) +{ + rtems_filesystem_global_location_t *global_loc = NULL; -static inline bool rtems_filesystem_is_root_location( + return rtems_filesystem_global_location_obtain( &global_loc ); +} + +static inline bool rtems_filesystem_location_is_null( + const rtems_filesystem_location_info_t *loc +) +{ + return loc->handlers == &rtems_filesystem_null_handlers; +} + +static inline bool rtems_filesystem_global_location_is_null( + const rtems_filesystem_global_location_t *global_loc +) +{ + return rtems_filesystem_location_is_null( &global_loc->location ); +} + +static inline void rtems_filesystem_location_error( + const rtems_filesystem_location_info_t *loc, + int eno +) +{ + if ( !rtems_filesystem_location_is_null( loc ) ) { + errno = eno; + } +} + +int rtems_filesystem_mknod( + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev +); + +int rtems_filesystem_chdir( rtems_filesystem_location_info_t *loc ); + +int rtems_filesystem_chown( + const char *path, + uid_t owner, + gid_t group, + int eval_follow_link +); + +static inline bool rtems_filesystem_is_ready_for_unmount( + rtems_filesystem_mount_table_entry_t *mt_entry +) +{ + bool ready = !mt_entry->mounted + && rtems_chain_has_only_one_node( &mt_entry->location_chain ) + && mt_entry->mt_fs_root->reference_count == 1; + + if ( ready ) { + rtems_chain_initialize_empty( &mt_entry->location_chain ); + } + + return ready; +} + +static inline void rtems_filesystem_location_add_to_mt_entry( + rtems_filesystem_location_info_t *loc +) +{ + rtems_filesystem_mt_entry_declare_lock_context( lock_context ); + + rtems_filesystem_mt_entry_lock( lock_context ); + rtems_chain_append_unprotected( + &loc->mt_entry->location_chain, + &loc->mt_entry_node + ); + rtems_filesystem_mt_entry_unlock( lock_context ); +} + +void rtems_filesystem_location_remove_from_mt_entry( + rtems_filesystem_location_info_t *loc +); + +void rtems_filesystem_do_unmount( + rtems_filesystem_mount_table_entry_t *mt_entry +); + +static inline bool rtems_filesystem_location_is_root( const rtems_filesystem_location_info_t *loc ) { - return loc->mt_entry->mt_fs_root.node_access == loc->node_access; + return (*loc->ops->are_nodes_equal_h)( + loc, + &loc->mt_entry->mt_fs_root->location + ); +} + +static inline const char *rtems_filesystem_eval_path_get_path( + rtems_filesystem_eval_path_context_t *ctx +) +{ + return ctx->path; +} + +static inline size_t rtems_filesystem_eval_path_get_pathlen( + rtems_filesystem_eval_path_context_t *ctx +) +{ + return ctx->pathlen; +} + +static inline void rtems_filesystem_eval_path_set_path( + rtems_filesystem_eval_path_context_t *ctx, + const char *path, + size_t pathlen +) +{ + ctx->path = path; + ctx->pathlen = pathlen; +} + +static inline void rtems_filesystem_eval_path_clear_path( + rtems_filesystem_eval_path_context_t *ctx +) +{ + ctx->pathlen = 0; +} + +static inline const char *rtems_filesystem_eval_path_get_token( + rtems_filesystem_eval_path_context_t *ctx +) +{ + return ctx->token; +} + +static inline size_t rtems_filesystem_eval_path_get_tokenlen( + rtems_filesystem_eval_path_context_t *ctx +) +{ + return ctx->tokenlen; +} + +static inline void rtems_filesystem_eval_path_set_token( + rtems_filesystem_eval_path_context_t *ctx, + const char *token, + size_t tokenlen +) +{ + ctx->token = token; + ctx->tokenlen = tokenlen; +} + +static inline void rtems_filesystem_eval_path_clear_token( + rtems_filesystem_eval_path_context_t *ctx +) +{ + ctx->tokenlen = 0; +} + +static inline void rtems_filesystem_eval_path_put_back_token( + rtems_filesystem_eval_path_context_t *ctx +) +{ + size_t tokenlen = ctx->tokenlen; + + ctx->path -= tokenlen; + ctx->pathlen += tokenlen; + ctx->tokenlen = 0; +} + +void rtems_filesystem_eval_path_eat_delimiter( + rtems_filesystem_eval_path_context_t *ctx +); + +void rtems_filesystem_eval_path_next_token( + rtems_filesystem_eval_path_context_t *ctx +); + +static inline void rtems_filesystem_eval_path_get_next_token( + rtems_filesystem_eval_path_context_t *ctx, + const char **token, + size_t *tokenlen +) +{ + rtems_filesystem_eval_path_next_token(ctx); + *token = ctx->token; + *tokenlen = ctx->tokenlen; +} + +static inline rtems_filesystem_location_info_t * +rtems_filesystem_eval_path_get_currentloc( + rtems_filesystem_eval_path_context_t *ctx +) +{ + return &ctx->currentloc; +} + +static inline bool rtems_filesystem_eval_path_has_path( + const rtems_filesystem_eval_path_context_t *ctx +) +{ + return ctx->pathlen > 0; +} + +static inline bool rtems_filesystem_eval_path_has_token( + const rtems_filesystem_eval_path_context_t *ctx +) +{ + return ctx->tokenlen > 0; +} + +static inline int rtems_filesystem_eval_path_get_flags( + const rtems_filesystem_eval_path_context_t *ctx +) +{ + return ctx->flags; +} + +static inline void rtems_filesystem_eval_path_set_flags( + rtems_filesystem_eval_path_context_t *ctx, + int flags +) +{ + ctx->flags = flags; +} + +static inline void rtems_filesystem_eval_path_clear_and_set_flags( + rtems_filesystem_eval_path_context_t *ctx, + int clear, + int set +) +{ + int flags = ctx->flags; + + flags &= ~clear; + flags |= set; + + ctx->flags = flags; +} + +static inline void rtems_filesystem_eval_path_extract_currentloc( + rtems_filesystem_eval_path_context_t *ctx, + rtems_filesystem_location_info_t *get +) +{ + rtems_filesystem_location_copy_and_detach( + get, + &ctx->currentloc + ); +} + +void rtems_filesystem_eval_path_error( + rtems_filesystem_eval_path_context_t *ctx, + int eno +); + +/** + * @brief Checks that the locations exist in the same file system instance. + * + * @retval 0 The locations exist and are in the same file system instance. + * @retval -1 An error occured. The @c errno indicates the error. + */ +int rtems_filesystem_location_exists_in_same_fs_instance_as( + const rtems_filesystem_location_info_t *a, + const rtems_filesystem_location_info_t *b +); + +bool rtems_filesystem_check_access( + int eval_flags, + mode_t node_mode, + uid_t node_uid, + gid_t node_gid +); + +bool rtems_filesystem_eval_path_check_access( + rtems_filesystem_eval_path_context_t *ctx, + int eval_flags, + mode_t node_mode, + uid_t node_uid, + gid_t node_gid +); + +static inline bool rtems_filesystem_is_delimiter(char c) +{ + return c == '/' || c == '\\'; +} + +static inline bool rtems_filesystem_is_current_directory( + const char *token, + size_t tokenlen +) +{ + return tokenlen == 1 && token [0] == '.'; +} + +static inline bool rtems_filesystem_is_parent_directory( + const char *token, + size_t tokenlen +) +{ + return tokenlen == 2 && token [0] == '.' && token [1] == '.'; } #ifdef __cplusplus diff --git a/cpukit/libcsupport/src/__usrenv.c b/cpukit/libcsupport/src/__usrenv.c index 0b3469fa1a..d26e73658f 100644 --- a/cpukit/libcsupport/src/__usrenv.c +++ b/cpukit/libcsupport/src/__usrenv.c @@ -2,6 +2,9 @@ * COPYRIGHT (c) 1989-2008. * 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. @@ -10,18 +13,246 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <rtems.h> -#include <rtems/libio.h> +#include <sys/stat.h> + #include <rtems/libio_.h> -/* - * Global information for POSIX Process Environment Support - */ +static int null_handler_open( + rtems_libio_t *iop, + const char *path, + int oflag, + mode_t mode +) +{ + return -1; +} + +static int null_handler_fstat( + const rtems_filesystem_location_info_t *pathloc, + struct stat *buf +) +{ + return -1; +} + +const rtems_filesystem_file_handlers_r rtems_filesystem_null_handlers = { + .open_h = null_handler_open, + .close_h = rtems_filesystem_default_close, + .read_h = rtems_filesystem_default_read, + .write_h = rtems_filesystem_default_write, + .ioctl_h = rtems_filesystem_default_ioctl, + .lseek_h = rtems_filesystem_default_lseek, + .fstat_h = null_handler_fstat, + .ftruncate_h = rtems_filesystem_default_ftruncate, + .fsync_h = rtems_filesystem_default_fsync, + .fdatasync_h = rtems_filesystem_default_fdatasync, + .fcntl_h = rtems_filesystem_default_fcntl +}; + +static void null_op_lock_or_unlock( + rtems_filesystem_mount_table_entry_t *mt_entry +) +{ + /* Do nothing */ +} + +static int null_op_mknod( + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev +) +{ + return -1; +} + +static int null_op_rmnod( + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *loc +) +{ + return -1; +} + +static int null_op_link( + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *targetloc, + const char *name, + size_t namelen +) +{ + return -1; +} + +static int null_op_fchmod( + const rtems_filesystem_location_info_t *pathloc, + mode_t mode +) +{ + return -1; +} + +static int null_op_chown( + const rtems_filesystem_location_info_t *loc, + uid_t owner, + gid_t group +) +{ + return -1; +} + +static int null_op_clonenode( + rtems_filesystem_location_info_t *loc +) +{ + return -1; +} + +static int null_op_mount( + rtems_filesystem_mount_table_entry_t *mt_entry +) +{ + return -1; +} + +static int null_op_fsmount_me( + rtems_filesystem_mount_table_entry_t *mt_entry, + const void *data +) +{ + return -1; +} + +static int null_op_unmount( + rtems_filesystem_mount_table_entry_t *mt_entry +) +{ + return -1; +} + +static void null_op_fsunmount_me( + rtems_filesystem_mount_table_entry_t *mt_entry +) +{ + /* Do nothing */ +} + +static int null_op_utime( + const rtems_filesystem_location_info_t *loc, + time_t actime, + time_t modtime +) +{ + return -1; +} + +static int null_op_symlink( + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + const char *target +) +{ + return -1; +} + +static ssize_t null_op_readlink( + const rtems_filesystem_location_info_t *loc, + char *buf, + size_t bufsize +) +{ + return -1; +} + +static int null_op_rename( + const rtems_filesystem_location_info_t *oldparentloc, + const rtems_filesystem_location_info_t *oldloc, + const rtems_filesystem_location_info_t *newparentloc, + const char *name, + size_t namelen +) +{ + return -1; +} + +static int null_op_statvfs( + const rtems_filesystem_location_info_t *loc, + struct statvfs *buf +) +{ + return -1; +} + +static const rtems_filesystem_operations_table null_ops = { + .lock_h = null_op_lock_or_unlock, + .unlock_h = null_op_lock_or_unlock, + .eval_path_h = rtems_filesystem_default_eval_path, + .link_h = null_op_link, + .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal, + .node_type_h = rtems_filesystem_default_node_type, + .mknod_h = null_op_mknod, + .rmnod_h = null_op_rmnod, + .fchmod_h = null_op_fchmod, + .chown_h = null_op_chown, + .clonenod_h = null_op_clonenode, + .freenod_h = rtems_filesystem_default_freenode, + .mount_h = null_op_mount, + .fsmount_me_h = null_op_fsmount_me, + .unmount_h = null_op_unmount, + .fsunmount_me_h = null_op_fsunmount_me, + .utime_h = null_op_utime, + .symlink_h = null_op_symlink, + .readlink_h = null_op_readlink, + .rename_h = null_op_rename, + .statvfs_h = null_op_statvfs +}; + +rtems_filesystem_mount_table_entry_t rtems_filesystem_null_mt_entry = { + .location_chain = { + .Head = { + .Node = { + .next = &rtems_filesystem_global_location_null.location.mt_entry_node, + .previous = NULL + }, + .fill = &rtems_filesystem_global_location_null.location.mt_entry_node, + } + }, + .mt_point_node = &rtems_filesystem_global_location_null, + .mt_fs_root = &rtems_filesystem_global_location_null, + .mounted = false, + .writeable = false +}; + +rtems_filesystem_global_location_t rtems_filesystem_global_location_null = { + .location = { + .mt_entry_node = { + .next = &rtems_filesystem_null_mt_entry.location_chain.Tail.Node, + .previous = &rtems_filesystem_null_mt_entry.location_chain.Head.Node + }, + .handlers = &rtems_filesystem_null_handlers, + .ops = &null_ops, + .mt_entry = &rtems_filesystem_null_mt_entry + }, -rtems_user_env_t rtems_global_user_env; -rtems_user_env_t * rtems_current_user_env = &rtems_global_user_env; + /* + * The initial reference count accounts for the following references + * o the root directory of the user environment, + * o the current directory of the user environment, + * o the root node of the null file system instance, and + * o the mount point node of the null file system instance. + */ + .reference_count = 4 +}; +rtems_user_env_t rtems_global_user_env = { + .current_directory = &rtems_filesystem_global_location_null, + .root_directory = &rtems_filesystem_global_location_null, + .umask = S_IWGRP | S_IWOTH +}; +rtems_user_env_t *rtems_current_user_env = &rtems_global_user_env; diff --git a/cpukit/libcsupport/src/_rename_r.c b/cpukit/libcsupport/src/_rename_r.c index 51010df28e..7a2637aa89 100644 --- a/cpukit/libcsupport/src/_rename_r.c +++ b/cpukit/libcsupport/src/_rename_r.c @@ -4,6 +4,9 @@ * COPYRIGHT (c) 1989-2007. * 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. @@ -16,12 +19,10 @@ #endif #if defined(RTEMS_NEWLIB) && !defined(HAVE__RENAME_R) -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> + +#include <stdio.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> int _rename_r( struct _reent *ptr __attribute__((unused)), @@ -29,85 +30,47 @@ int _rename_r( const char *new ) { - int old_parent_pathlen; - rtems_filesystem_location_info_t old_loc; - rtems_filesystem_location_info_t old_parent_loc; - rtems_filesystem_location_info_t new_parent_loc; - int i; - int result; - const char *name; - bool free_old_parentloc = false; - - /* - * Get the parent node of the old path to be renamed. Find the parent path. - */ - - old_parent_pathlen = rtems_filesystem_dirname ( old ); - - if ( old_parent_pathlen == 0 ) - rtems_filesystem_get_start_loc( old, &i, &old_parent_loc ); - else { - result = rtems_filesystem_evaluate_path( old, old_parent_pathlen, - RTEMS_LIBIO_PERMS_WRITE, - &old_parent_loc, - false ); - if ( result != 0 ) - return -1; - - free_old_parentloc = true; + int rv = 0; + rtems_filesystem_eval_path_context_t old_ctx; + int old_eval_flags = 0; + rtems_filesystem_location_info_t old_parentloc; + int old_parent_eval_flags = RTEMS_LIBIO_PERMS_WRITE + | RTEMS_LIBIO_FOLLOW_HARD_LINK; + const rtems_filesystem_location_info_t *old_currentloc = + rtems_filesystem_eval_path_start_with_parent( + &old_ctx, + old, + old_eval_flags, + &old_parentloc, + old_parent_eval_flags + ); + rtems_filesystem_eval_path_context_t new_ctx; + + /* FIXME: This is not POSIX conform */ + int new_eval_flags = RTEMS_LIBIO_FOLLOW_HARD_LINK + | RTEMS_LIBIO_MAKE + | RTEMS_LIBIO_EXCLUSIVE; + + const rtems_filesystem_location_info_t *new_currentloc = + rtems_filesystem_eval_path_start( &new_ctx, new, new_eval_flags ); + + rv = rtems_filesystem_location_exists_in_same_fs_instance_as( + old_currentloc, + new_currentloc + ); + if ( rv == 0 ) { + rv = (*new_currentloc->ops->rename_h)( + &old_parentloc, + old_currentloc, + new_currentloc, + rtems_filesystem_eval_path_get_token( &new_ctx ), + rtems_filesystem_eval_path_get_tokenlen( &new_ctx ) + ); } - /* - * Start from the parent to find the node that should be under it. - */ - - old_loc = old_parent_loc; - name = old + old_parent_pathlen; - name += rtems_filesystem_prefix_separators( name, strlen( name ) ); - - result = rtems_filesystem_evaluate_relative_path( name , strlen( name ), - 0, &old_loc, false ); - if ( result != 0 ) { - if ( free_old_parentloc ) - rtems_filesystem_freenode( &old_parent_loc ); - return -1; - } - - /* - * Get the parent of the new node we are renaming to. - */ - - rtems_filesystem_get_start_loc( new, &i, &new_parent_loc ); - - result = (*new_parent_loc.ops->evalformake_h)( &new[i], &new_parent_loc, &name ); - if ( result != 0 ) { - rtems_filesystem_freenode( &new_parent_loc ); - if ( free_old_parentloc ) - rtems_filesystem_freenode( &old_parent_loc ); - rtems_filesystem_freenode( &old_loc ); - return -1; - } - - /* - * Check to see if the caller is trying to rename across file system - * boundaries. - */ - - if ( old_parent_loc.mt_entry != new_parent_loc.mt_entry ) { - rtems_filesystem_freenode( &new_parent_loc ); - if ( free_old_parentloc ) - rtems_filesystem_freenode( &old_parent_loc ); - rtems_filesystem_freenode( &old_loc ); - rtems_set_errno_and_return_minus_one( EXDEV ); - } - - result = (*new_parent_loc.ops->rename_h)( &old_parent_loc, &old_loc, &new_parent_loc, name ); - - rtems_filesystem_freenode( &new_parent_loc ); - if ( free_old_parentloc ) - rtems_filesystem_freenode( &old_parent_loc ); - rtems_filesystem_freenode( &old_loc ); + rtems_filesystem_eval_path_cleanup_with_parent( &old_ctx, &old_parentloc ); + rtems_filesystem_eval_path_cleanup( &new_ctx ); - return result; + return rv; } #endif diff --git a/cpukit/libcsupport/src/base_fs.c b/cpukit/libcsupport/src/base_fs.c index b5681eda63..bbf6d8d4be 100644 --- a/cpukit/libcsupport/src/base_fs.c +++ b/cpukit/libcsupport/src/base_fs.c @@ -4,6 +4,9 @@ * COPYRIGHT (c) 1989-2008. * 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. @@ -35,62 +38,20 @@ void rtems_filesystem_initialize( void ) { - int status; - const rtems_filesystem_mount_table_t *mt; - rtems_filesystem_location_info_t loc; - - /* - * Set the default umask to "022". - */ - - rtems_filesystem_umask = 022; - - /* - * mount the first filesystem. - */ - if ( rtems_filesystem_mount_table_size == 0 ) - rtems_fatal_error_occurred( 0xABCD0001 ); - - mt = &rtems_filesystem_mount_table[0]; - - status = mount( mt->device, mt->mount_point, mt->type, mt->fsoptions, NULL ); - if ( status == -1 ) + int rv = 0; + const rtems_filesystem_mount_configuration *root_config = + &rtems_filesystem_root_configuration; + + rv = mount( + root_config->source, + root_config->target, + root_config->filesystemtype, + root_config->options, + root_config->data + ); + if ( rv != 0 ) rtems_fatal_error_occurred( 0xABCD0002 ); - rtems_filesystem_link_counts = 0; - - /* setup the 'current' and 'root' directories - * - * NOTE: cloning the pathlocs is not strictly - * necessary. Since we implicitely let - * all threads that don't call - * libio_set_private_env() share the same - * (initial) 'root' and 'current' locs, - * we (also implicitely) assume that the - * root filesystem doesn't care about - * reference counts. - * I just inserted the code snippet below - * to remind everybody of the fact by - * making it more explicit... - * Ideally, every thread would have to - * call either share_private_env() or - * set_private_env() - but then: that's - * gonna hit performance. - * - * Till Straumann, 10/25/2002 - */ - /* Clone the root pathloc */ - rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0); - rtems_filesystem_root = loc; - /* One more clone for the current node */ - rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0); - rtems_filesystem_current = loc; - - /* Note: the global_env's refcnt doesn't matter - * as the global env is never released - */ - - /* * Traditionally RTEMS devices are under "/dev" so install this directory. * @@ -100,8 +61,8 @@ void rtems_filesystem_initialize( void ) * created that way by the IMFS. */ - status = mkdir( "/dev", 0777); - if ( status != 0 ) + rv = mkdir( "/dev", 0777); + if ( rv != 0 ) rtems_fatal_error_occurred( 0xABCD0003 ); /* diff --git a/cpukit/libcsupport/src/chdir.c b/cpukit/libcsupport/src/chdir.c index c9d05f0bef..df65170936 100644 --- a/cpukit/libcsupport/src/chdir.c +++ b/cpukit/libcsupport/src/chdir.c @@ -4,6 +4,9 @@ * COPYRIGHT (c) 1989-2010. * 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. @@ -12,46 +15,47 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <rtems.h> - #include <unistd.h> -#include <errno.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -int chdir( - const char *pathname -) +int rtems_filesystem_chdir( rtems_filesystem_location_info_t *loc ) { - rtems_filesystem_location_info_t loc; - int result; - - if ( !pathname ) - rtems_set_errno_and_return_minus_one( EFAULT ); - - /* - * Get the node where we wish to go. - */ - result = rtems_filesystem_evaluate_path( - pathname, strlen( pathname ), RTEMS_LIBIO_PERMS_SEARCH, &loc, true ); - if ( result != 0 ) - return -1; - - /* - * Verify you can change directory into this node. - */ - if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) { - rtems_filesystem_freenode( &loc ); - rtems_set_errno_and_return_minus_one( ENOTDIR ); + int rv = 0; + rtems_filesystem_global_location_t *global_loc = + rtems_filesystem_location_transform_to_global( loc ); + rtems_filesystem_node_types_t type = + rtems_filesystem_node_type( &global_loc->location ); + + if ( type == RTEMS_FILESYSTEM_DIRECTORY ) { + rtems_filesystem_global_location_assign( + &rtems_filesystem_current, + global_loc + ); + } else { + rtems_filesystem_location_error( &global_loc->location, ENOTDIR ); + rtems_filesystem_global_location_release( global_loc ); + rv = -1; } - rtems_filesystem_freenode( &rtems_filesystem_current ); - - rtems_filesystem_current = loc; + return rv; +} - return 0; +int chdir( const char *path ) +{ + int rv = 0; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_LIBIO_PERMS_EXEC + | RTEMS_LIBIO_FOLLOW_LINK; + rtems_filesystem_location_info_t pathloc; + + rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); + rtems_filesystem_eval_path_extract_currentloc( &ctx, &pathloc ); + rv = rtems_filesystem_chdir( &pathloc ); + rtems_filesystem_eval_path_cleanup( &ctx ); + + return rv; } diff --git a/cpukit/libcsupport/src/chmod.c b/cpukit/libcsupport/src/chmod.c index d1d9ae0f5f..ff3039a557 100644 --- a/cpukit/libcsupport/src/chmod.c +++ b/cpukit/libcsupport/src/chmod.c @@ -12,35 +12,24 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <rtems.h> -#include <rtems/libio.h> #include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <unistd.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -int chmod( - const char *path, - mode_t mode -) +int chmod( const char *path, mode_t mode ) { - int status; - rtems_filesystem_location_info_t loc; - int result; + int rv = 0; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_LIBIO_FOLLOW_LINK; + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); - status = rtems_filesystem_evaluate_path( path, strlen( path ), 0, &loc, true ); - if ( status != 0 ) - return -1; + rv = (*currentloc->ops->fchmod_h)( currentloc, mode ); - result = (*loc.handlers->fchmod_h)( &loc, mode ); + rtems_filesystem_eval_path_cleanup( &ctx ); - rtems_filesystem_freenode( &loc ); - - return result; + return rv; } diff --git a/cpukit/libcsupport/src/chown.c b/cpukit/libcsupport/src/chown.c index 9ecaea11f7..1d07384d7d 100644 --- a/cpukit/libcsupport/src/chown.c +++ b/cpukit/libcsupport/src/chown.c @@ -4,6 +4,9 @@ * 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. @@ -12,39 +15,38 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif #include <unistd.h> -#include <rtems.h> #include <rtems/libio_.h> -int _chown_helper( +int rtems_filesystem_chown( const char *path, - uid_t owner, - gid_t group, - int follow_link + uid_t owner, + gid_t group, + int eval_follow_link ) { - rtems_filesystem_location_info_t loc; - int result; - - if ( rtems_filesystem_evaluate_path( path, strlen( path ), 0x00, &loc, follow_link ) ) - return -1; + int rv = 0; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = eval_follow_link; + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); - result = (*loc.ops->chown_h)( &loc, owner, group ); + rv = (*currentloc->ops->chown_h)( + currentloc, + owner, + group + ); - rtems_filesystem_freenode( &loc ); + rtems_filesystem_eval_path_cleanup( &ctx ); - return result; + return rv; } -int chown( - const char *path, - uid_t owner, - gid_t group -) +int chown( const char *path, uid_t owner, gid_t group ) { - return _chown_helper( path, owner, group, true ); + return rtems_filesystem_chown( path, owner, group, RTEMS_LIBIO_FOLLOW_LINK ); } diff --git a/cpukit/libcsupport/src/chroot.c b/cpukit/libcsupport/src/chroot.c index ccda4d6d7a..fd802ff32b 100644 --- a/cpukit/libcsupport/src/chroot.c +++ b/cpukit/libcsupport/src/chroot.c @@ -5,6 +5,9 @@ * COPYRIGHT (c) 1989-2008. * 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. @@ -13,43 +16,77 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <rtems.h> - #include <unistd.h> -#include <errno.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -int chroot( - const char *pathname -) +int chroot( const char *path ) { - int result; - rtems_filesystem_location_info_t loc; - - /* an automatic call to new private env the first time */ - if (rtems_current_user_env == &rtems_global_user_env) { - rtems_libio_set_private_env(); /* try to set a new private env*/ - if (rtems_current_user_env == &rtems_global_user_env) /* not ok */ - rtems_set_errno_and_return_minus_one( ENOTSUP ); - } + int rv = 0; + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_LIBIO_PERMS_SEARCH + | RTEMS_LIBIO_FOLLOW_LINK; + rtems_filesystem_location_info_t loc; + rtems_filesystem_global_location_t *new_current_loc; + + /* + * We use the global environment for path evaluation. This makes it possible + * to escape from a chroot environment referencing an unmounted file system. + */ + rtems_filesystem_eval_path_start_with_root_and_current( + &ctx, + path, + eval_flags, + &rtems_global_user_env.root_directory, + &rtems_global_user_env.current_directory + ); - result = chdir(pathname); - if (result) { - rtems_set_errno_and_return_minus_one( errno ); + rtems_filesystem_eval_path_extract_currentloc( &ctx, &loc ); + new_current_loc = rtems_filesystem_location_transform_to_global( &loc ); + if ( !rtems_filesystem_global_location_is_null( new_current_loc ) ) { + rtems_filesystem_global_location_t *new_root_loc = + rtems_filesystem_global_location_obtain( &new_current_loc ); + rtems_filesystem_node_types_t type = + (*new_root_loc->location.ops->node_type_h)( &new_root_loc->location ); + + if ( type == RTEMS_FILESYSTEM_DIRECTORY ) { + sc = rtems_libio_set_private_env(); + if (sc == RTEMS_SUCCESSFUL) { + rtems_filesystem_global_location_assign( + &rtems_filesystem_root, + new_root_loc + ); + rtems_filesystem_global_location_assign( + &rtems_filesystem_current, + new_current_loc + ); + } else { + if (sc != RTEMS_UNSATISFIED) { + errno = ENOMEM; + } + rv = -1; + } + } else { + rtems_filesystem_location_error( &new_root_loc->location, ENOTDIR ); + rv = -1; + } + + if ( rv != 0 ) { + rtems_filesystem_global_location_release( new_root_loc ); + } + } else { + rv = -1; } - /* clone the new root location */ - if (rtems_filesystem_evaluate_path(".", 1, 0, &loc, 0)) { - /* our cwd has changed, though - but there is no easy way of return :-( */ - rtems_set_errno_and_return_minus_one( errno ); + rtems_filesystem_eval_path_cleanup( &ctx ); + + if ( rv != 0 ) { + rtems_filesystem_global_location_release( new_current_loc ); } - rtems_filesystem_freenode(&rtems_filesystem_root); - rtems_filesystem_root = loc; - return 0; + return rv; } diff --git a/cpukit/libcsupport/src/clonenode.c b/cpukit/libcsupport/src/clonenode.c new file mode 100644 index 0000000000..380ad90699 --- /dev/null +++ b/cpukit/libcsupport/src/clonenode.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> + +void rtems_filesystem_location_clone( + rtems_filesystem_location_info_t *clone, + const rtems_filesystem_location_info_t *master +) +{ + int rv = 0; + + clone = rtems_filesystem_location_copy( clone, master ); + rv = (*clone->ops->clonenod_h)( clone ); + if ( rv != 0 ) { + rtems_filesystem_location_remove_from_mt_entry( clone ); + rtems_filesystem_location_initialize_to_null( clone ); + } +} diff --git a/cpukit/libcsupport/src/close.c b/cpukit/libcsupport/src/close.c index 726bca11d9..3cdd0bffba 100644 --- a/cpukit/libcsupport/src/close.c +++ b/cpukit/libcsupport/src/close.c @@ -22,16 +22,14 @@ int close( ) { rtems_libio_t *iop; - rtems_status_code rc; + int rc; rtems_libio_check_fd(fd); iop = rtems_libio_iop(fd); rtems_libio_check_is_open(iop); - rc = RTEMS_SUCCESSFUL; rc = (*iop->pathinfo.handlers->close_h)( iop ); - rtems_filesystem_freenode( &iop->pathinfo ); rtems_libio_free( iop ); return rc; diff --git a/cpukit/libcsupport/src/eval.c b/cpukit/libcsupport/src/eval.c deleted file mode 100644 index 5a9118d3e1..0000000000 --- a/cpukit/libcsupport/src/eval.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * rtems_filesystem_evaluate_path() - * - * Routine to seed the evaluate path routine. - * - * COPYRIGHT (c) 1989-2010. - * On-Line Applications Research Corporation (OAR). - * - * 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" -#endif - -#include <rtems.h> -#include <rtems/libio_.h> -#include <rtems/seterr.h> - -int rtems_filesystem_evaluate_relative_path( - const char *pathname, - size_t pathnamelen, - int flags, - rtems_filesystem_location_info_t *pathloc, - int follow_link -) -{ - int result; - rtems_filesystem_node_types_t type; - - #if defined(RTEMS_DEBUG) - /* - * Verify Input parameters that should never be bad unless someone - * is implementing a new filesystem and has bugs. - */ - if ( !pathname ) - rtems_set_errno_and_return_minus_one( EFAULT ); - - if ( !pathloc ) - rtems_set_errno_and_return_minus_one( EIO ); - #endif - - result = (*pathloc->ops->evalpath_h)( pathname, pathnamelen, flags, pathloc ); - - /* - * Get the Node type and determine if you need to follow the link or - * not. - */ - - if ( (result == 0) && follow_link ) { - - type = (*pathloc->ops->node_type_h)( pathloc ); - - if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) || - ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) { - - /* what to do with the valid node pathloc points to - * if eval_link_h fails? - * Let the FS implementation deal with this case. It - * should probably free pathloc in either case: - * - if the link evaluation fails, it must free the - * original (valid) pathloc because we are going - * to return -1 and hence the FS generics won't - * cleanup pathloc. - * - if the link evaluation is successful, the updated - * pathloc will be passed up (and eventually released). - * Hence, the (valid) originial node that we submit to - * eval_link_h() should be released by the handler. - */ - - result = (*pathloc->ops->eval_link_h)( pathloc, flags ); - } - } - - return result; -} - -int rtems_filesystem_evaluate_path( - const char *pathname, - size_t pathnamelen, - int flags, - rtems_filesystem_location_info_t *pathloc, - int follow_link -) -{ - int i = 0; - - #if defined(RTEMS_DEBUG) - /* - * Verify Input parameters that should never be bad unless someone - * is implementing a new filesystem and has bugs. - */ - if ( !pathname ) - rtems_set_errno_and_return_minus_one( EFAULT ); - - if ( !pathloc ) - rtems_set_errno_and_return_minus_one( EIO ); - #endif - - /* - * Evaluate the path using the optable evalpath. - */ - - rtems_filesystem_get_start_loc( pathname, &i, pathloc ); - - /* - * We evaluation the path relative to the start location we get got. - */ - return rtems_filesystem_evaluate_relative_path( &pathname[i], - pathnamelen - i, - flags, - pathloc, - follow_link ); -} - -int rtems_filesystem_dirname( - const char *pathname -) -{ - int len = strlen( pathname ); - - while ( len ) { - len--; - if ( rtems_filesystem_is_separator( pathname[len] ) ) - break; - } - - return len; -} - -int rtems_filesystem_prefix_separators( - const char *pathname, - int pathnamelen -) -{ - /* - * Eat any separators at start of the path. - */ - int stripped = 0; - while ( *pathname && pathnamelen && rtems_filesystem_is_separator( *pathname ) ) - { - pathname++; - pathnamelen--; - stripped++; - } - return stripped; -} diff --git a/cpukit/libcsupport/src/fchdir.c b/cpukit/libcsupport/src/fchdir.c index c95e2b7fb3..7b64ea8f21 100644 --- a/cpukit/libcsupport/src/fchdir.c +++ b/cpukit/libcsupport/src/fchdir.c @@ -4,6 +4,9 @@ * COPYRIGHT (c) 1989-2011. * 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. @@ -12,65 +15,50 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif #include <unistd.h> -#include <sys/stat.h> -#include <errno.h> -#include <rtems.h> -#include <rtems/libio.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -int fchdir( - int fd -) +int fchdir( int fd ) { + int rv = 0; rtems_libio_t *iop; - rtems_filesystem_location_info_t loc, saved; + struct stat st; + rtems_filesystem_location_info_t loc; + + st.st_mode = 0; + st.st_uid = 0; + st.st_gid = 0; rtems_libio_check_fd( fd ); iop = rtems_libio_iop( fd ); - rtems_libio_check_is_open(iop); + rtems_libio_check_is_open( iop ); - /* - * Verify you can change directory into this node. - */ + rtems_filesystem_instance_lock( &iop->pathinfo ); + rv = (*iop->pathinfo.handlers->fstat_h)( &iop->pathinfo, &st ); + if ( rv == 0 ) { + bool access_ok = rtems_filesystem_check_access( + RTEMS_LIBIO_PERMS_EXEC, + st.st_mode, + st.st_uid, + st.st_gid + ); - if ( (*iop->pathinfo.ops->node_type_h)( &iop->pathinfo ) != - RTEMS_FILESYSTEM_DIRECTORY ) { - rtems_set_errno_and_return_minus_one( ENOTDIR ); + if ( access_ok ) { + rtems_filesystem_location_clone( &loc, &iop->pathinfo ); + } else { + errno = EACCES; + rv = -1; + } } + rtems_filesystem_instance_unlock( &iop->pathinfo ); - - /* - * FIXME : I feel there should be another call to - * actually take into account the extra reference to - * this node which we are making here. I can - * see the freenode interface but do not see - * allocnode node interface. It maybe node_type. - * - * FIXED: T.Straumann: it is evaluate_path() - * but note the race condition. Threads who - * share their rtems_filesystem_current better - * be synchronized! - */ - - saved = rtems_filesystem_current; - rtems_filesystem_current = iop->pathinfo; - - /* clone the current node */ - if (rtems_filesystem_evaluate_path(".", 1, 0, &loc, 0)) { - /* cloning failed; restore original and bail out */ - rtems_filesystem_current = saved; - return -1; + if ( rv == 0 ) { + rv = rtems_filesystem_chdir( &loc ); } - /* release the old one */ - rtems_filesystem_freenode( &saved ); - - rtems_filesystem_current = loc; - return 0; + return rv; } diff --git a/cpukit/libcsupport/src/fchmod.c b/cpukit/libcsupport/src/fchmod.c index e90a155bdb..e651066a77 100644 --- a/cpukit/libcsupport/src/fchmod.c +++ b/cpukit/libcsupport/src/fchmod.c @@ -12,31 +12,25 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <unistd.h> #include <sys/stat.h> -#include <errno.h> -#include <rtems.h> -#include <rtems/libio.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -int fchmod( - int fd, - mode_t mode -) +int fchmod( int fd, mode_t mode ) { + int rv; rtems_libio_t *iop; rtems_libio_check_fd( fd ); iop = rtems_libio_iop( fd ); rtems_libio_check_is_open(iop); - /* - * Now process the fchmod(). - */ - return (*iop->pathinfo.handlers->fchmod_h)( &iop->pathinfo, mode ); + rtems_filesystem_instance_lock( &iop->pathinfo ); + rv = (*iop->pathinfo.ops->fchmod_h)( &iop->pathinfo, mode ); + rtems_filesystem_instance_unlock( &iop->pathinfo ); + + return rv; } diff --git a/cpukit/libcsupport/src/fchown.c b/cpukit/libcsupport/src/fchown.c index 13bb2b9da0..b5891bf36d 100644 --- a/cpukit/libcsupport/src/fchown.c +++ b/cpukit/libcsupport/src/fchown.c @@ -12,24 +12,16 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <sys/stat.h> -#include <errno.h> - -#include <rtems.h> -#include <rtems/libio.h> +#include <unistd.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -int fchown( - int fd, - uid_t owner, - gid_t group -) +int fchown( int fd, uid_t owner, gid_t group ) { + int rv = 0; rtems_libio_t *iop; rtems_libio_check_fd( fd ); @@ -38,5 +30,9 @@ int fchown( rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE ); - return (*iop->pathinfo.ops->chown_h)( &iop->pathinfo, owner, group ); + rtems_filesystem_instance_lock( &iop->pathinfo ); + rv = (*iop->pathinfo.ops->chown_h)( &iop->pathinfo, owner, group ); + rtems_filesystem_instance_unlock( &iop->pathinfo ); + + return rv; } diff --git a/cpukit/libcsupport/src/fcntl.c b/cpukit/libcsupport/src/fcntl.c index 988a9414ee..10f783b910 100644 --- a/cpukit/libcsupport/src/fcntl.c +++ b/cpukit/libcsupport/src/fcntl.c @@ -12,17 +12,53 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif #include <stdarg.h> #include <unistd.h> #include <fcntl.h> -#include <errno.h> -#include <rtems.h> #include <rtems/libio_.h> +static int duplicate_iop( rtems_libio_t *iop, int fd2 ) +{ + int rv = 0; + + /* + * FIXME: We ignore the start value fd2 for the file descriptor search. This + * is not POSIX conform. + */ + rtems_libio_t *diop = rtems_libio_allocate(); + + if (diop != NULL) { + int oflag = rtems_libio_to_fcntl_flags( iop->flags ); + + oflag &= ~O_CREAT; + diop->flags |= rtems_libio_fcntl_flags( oflag ); + + rtems_filesystem_instance_lock( &iop->pathinfo ); + rtems_filesystem_location_clone( &diop->pathinfo, &iop->pathinfo ); + rtems_filesystem_instance_unlock( &iop->pathinfo ); + + /* + * XXX: We call the open handler here to have a proper open and close pair. + * + * FIXME: What to do with the path? + */ + rv = (*diop->pathinfo.handlers->open_h)( diop, NULL, oflag, 0 ); + if ( rv == 0 ) { + rv = diop - rtems_libio_iops; + } else { + rtems_libio_free( diop ); + } + } else { + rv = -1; + } + + return rv; +} + static int vfcntl( int fd, int cmd, @@ -30,7 +66,6 @@ static int vfcntl( ) { rtems_libio_t *iop; - rtems_libio_t *diop; int fd2; int flags; int mask; @@ -51,20 +86,7 @@ static int vfcntl( switch ( cmd ) { case F_DUPFD: /* dup */ fd2 = va_arg( ap, int ); - if ( fd2 ) - diop = rtems_libio_iop( fd2 ); - else { - /* allocate a file control block */ - diop = rtems_libio_allocate(); - if ( diop == 0 ) { - ret = -1; - break; - } - } - - diop->flags = iop->flags; - diop->pathinfo = iop->pathinfo; - ret = (int) (diop - rtems_libio_iops); + ret = duplicate_iop( iop, fd2 ); break; case F_GETFD: /* get f_flags */ @@ -138,7 +160,7 @@ static int vfcntl( */ if (ret >= 0) { - int err = (*iop->pathinfo.handlers->fcntl_h)( cmd, iop ); + int err = (*iop->pathinfo.handlers->fcntl_h)( iop, cmd ); if (err) { errno = err; ret = -1; diff --git a/cpukit/libcsupport/src/freenode.c b/cpukit/libcsupport/src/freenode.c index 21a9c1de91..cc05b6034a 100644 --- a/cpukit/libcsupport/src/freenode.c +++ b/cpukit/libcsupport/src/freenode.c @@ -4,6 +4,9 @@ * COPYRIGHT (c) 1989-2010. * 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. @@ -11,10 +14,16 @@ * $Id$ */ -#include <stdlib.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> -void rtems_filesystem_freenode( rtems_filesystem_location_info_t *_node ) +void rtems_filesystem_location_free( rtems_filesystem_location_info_t *loc ) { - _node->ops->freenod_h(_node ); + rtems_filesystem_instance_lock( loc ); + (*loc->ops->freenod_h)( loc ); + rtems_filesystem_instance_unlock( loc ); + rtems_filesystem_location_remove_from_mt_entry( loc ); } diff --git a/cpukit/libcsupport/src/ftruncate.c b/cpukit/libcsupport/src/ftruncate.c index 9c50ca2fbe..66c1dc0cc6 100644 --- a/cpukit/libcsupport/src/ftruncate.c +++ b/cpukit/libcsupport/src/ftruncate.c @@ -12,39 +12,30 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif #include <unistd.h> -#include <errno.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -int ftruncate( - int fd, - off_t length -) +int ftruncate( int fd, off_t length ) { - rtems_libio_t *iop; - rtems_filesystem_location_info_t loc; + int rv = 0; - rtems_libio_check_fd( fd ); - iop = rtems_libio_iop( fd ); - rtems_libio_check_is_open(iop); - rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE ); + if ( length >= 0 ) { + rtems_libio_t *iop; - /* - * Now process the ftruncate() request. - */ + rtems_libio_check_fd( fd ); + iop = rtems_libio_iop( fd ); + rtems_libio_check_is_open( iop ); + rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE ); - /* - * Make sure we are not working on a directory - */ + rv = (*iop->pathinfo.handlers->ftruncate_h)( iop, length ); + } else { + errno = EINVAL; + rv = -1; + } - loc = iop->pathinfo; - if ( (*loc.ops->node_type_h)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY ) - rtems_set_errno_and_return_minus_one( EISDIR ); - - return (*iop->pathinfo.handlers->ftruncate_h)( iop, length ); + return rv; } diff --git a/cpukit/libcsupport/src/getdents.c b/cpukit/libcsupport/src/getdents.c index d0b787cd88..82fa678978 100644 --- a/cpukit/libcsupport/src/getdents.c +++ b/cpukit/libcsupport/src/getdents.c @@ -32,8 +32,8 @@ int getdents( int dd_len ) { - rtems_libio_t *iop; - rtems_filesystem_location_info_t loc; + rtems_libio_t *iop; + rtems_filesystem_node_types_t type; /* * Get the file control block structure associated with the file descriptor @@ -43,8 +43,8 @@ int getdents( /* * Make sure we are working on a directory */ - loc = iop->pathinfo; - if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) + type = rtems_filesystem_node_type( &iop->pathinfo ); + if ( type != RTEMS_FILESYSTEM_DIRECTORY ) rtems_set_errno_and_return_minus_one( ENOTDIR ); /* diff --git a/cpukit/libcsupport/src/lchown.c b/cpukit/libcsupport/src/lchown.c index 1092f9017e..83bdf6f95c 100644 --- a/cpukit/libcsupport/src/lchown.c +++ b/cpukit/libcsupport/src/lchown.c @@ -12,20 +12,19 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif #include <unistd.h> -#include <rtems.h> +#include <rtems/libio_.h> -int _chown_helper( const char *path, uid_t owner, gid_t group, int follow_link); - -int lchown( - const char *path, - uid_t owner, - gid_t group -) +int lchown( const char *path, uid_t owner, gid_t group ) { - return _chown_helper( path, owner, group, false ); + return rtems_filesystem_chown( + path, + owner, + group, + RTEMS_LIBIO_FOLLOW_HARD_LINK + ); } diff --git a/cpukit/libcsupport/src/libio.c b/cpukit/libcsupport/src/libio.c index d080d01596..985ad8bad9 100644 --- a/cpukit/libcsupport/src/libio.c +++ b/cpukit/libcsupport/src/libio.c @@ -47,14 +47,14 @@ * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand */ -const rtems_assoc_t access_modes_assoc[] = { +static const rtems_assoc_t access_modes_assoc[] = { { "READ", LIBIO_FLAGS_READ, O_RDONLY }, { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY }, { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR }, { 0, 0, 0 }, }; -const rtems_assoc_t status_flags_assoc[] = { +static const rtems_assoc_t status_flags_assoc[] = { #ifdef ACCEPT_O_NDELAY_ALIAS { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY }, #endif @@ -64,9 +64,7 @@ const rtems_assoc_t status_flags_assoc[] = { { 0, 0, 0 }, }; -uint32_t rtems_libio_fcntl_flags( - uint32_t fcntl_flags -) +uint32_t rtems_libio_fcntl_flags( int fcntl_flags ) { uint32_t flags = 0; uint32_t access_modes; @@ -75,7 +73,7 @@ uint32_t rtems_libio_fcntl_flags( * Access mode is a small integer */ - access_modes = fcntl_flags & O_ACCMODE; + access_modes = (uint32_t) (fcntl_flags & O_ACCMODE); fcntl_flags &= ~O_ACCMODE; flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes ); @@ -83,8 +81,11 @@ uint32_t rtems_libio_fcntl_flags( * Everything else is single bits */ - flags |= - rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags); + flags |= rtems_assoc_local_by_remote_bitfield( + status_flags_assoc, + (uint32_t) fcntl_flags + ); + return flags; } @@ -94,11 +95,9 @@ uint32_t rtems_libio_fcntl_flags( * Convert RTEMS internal flags to UNIX fnctl(2) flags */ -uint32_t rtems_libio_to_fcntl_flags( - uint32_t flags -) +int rtems_libio_to_fcntl_flags( uint32_t flags ) { - uint32_t fcntl_flags = 0; + int fcntl_flags = 0; if ( (flags & LIBIO_FLAGS_READ_WRITE) == LIBIO_FLAGS_READ_WRITE ) { fcntl_flags |= O_RDWR; @@ -176,6 +175,8 @@ void rtems_libio_free( rtems_libio_t *iop ) { + rtems_filesystem_location_free( &iop->pathinfo ); + rtems_libio_lock(); if (iop->sem) @@ -187,92 +188,3 @@ void rtems_libio_free( rtems_libio_unlock(); } - -/* - * rtems_libio_is_open_files_in_fs - * - * This routine scans the entire file descriptor table to determine if the - * are any active file descriptors that refer to the at least one node in the - * file system that we are trying to dismount. - * - * If there is at least one node in the file system referenced by the mount - * table entry a 1 is returned, otherwise a 0 is returned. - */ - -int rtems_libio_is_open_files_in_fs( - rtems_filesystem_mount_table_entry_t * fs_mt_entry -) -{ - rtems_libio_t *iop; - int result = 0; - uint32_t i; - - rtems_libio_lock(); - - /* - * Look for any active file descriptor entry. - */ - - for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){ - - if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) { - - /* - * Check if this node is under the file system that we - * are trying to dismount. - */ - - if ( iop->pathinfo.mt_entry == fs_mt_entry ) { - result = 1; - break; - } - } - } - - rtems_libio_unlock(); - - return result; -} - -/* - * rtems_libio_is_file_open - * - * This routine scans the entire file descriptor table to determine if the - * given file refers to an active file descriptor. - * - * If the given file is open a 1 is returned, otherwise a 0 is returned. - */ - -int rtems_libio_is_file_open( - void *node_access -) -{ - rtems_libio_t *iop; - int result=0; - uint32_t i; - - rtems_libio_lock(); - - /* - * Look for any active file descriptor entry. - */ - - for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){ - if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) { - - /* - * Check if this node is under the file system that we - * are trying to dismount. - */ - - if ( iop->pathinfo.node_access == node_access ) { - result = 1; - break; - } - } - } - - rtems_libio_unlock(); - - return result; -} diff --git a/cpukit/libcsupport/src/libio_sockets.c b/cpukit/libcsupport/src/libio_sockets.c index c67e19d78c..ff02e0f4ea 100644 --- a/cpukit/libcsupport/src/libio_sockets.c +++ b/cpukit/libcsupport/src/libio_sockets.c @@ -18,6 +18,7 @@ #include <rtems/libio_.h> #include <rtems/seterr.h> +#include <rtems/rtems_bsdnet_internal.h> /* * Convert an RTEMS file descriptor to a BSD socket pointer. @@ -69,5 +70,7 @@ int rtems_bsdnet_makeFdForSocket( iop->data1 = so; iop->pathinfo.handlers = h; iop->pathinfo.ops = &rtems_filesystem_operations_default; + iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry; + rtems_filesystem_location_add_to_mt_entry(&iop->pathinfo); return fd; } diff --git a/cpukit/libcsupport/src/link.c b/cpukit/libcsupport/src/link.c index 11b6521dea..cf370fb9dc 100644 --- a/cpukit/libcsupport/src/link.c +++ b/cpukit/libcsupport/src/link.c @@ -12,65 +12,44 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <rtems.h> -#include <rtems/libio.h> -#include <errno.h> +#include <unistd.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -int link( - const char *existing, - const char *new -) +int link( const char *path1, const char *path2 ) { - rtems_filesystem_location_info_t existing_loc; - rtems_filesystem_location_info_t parent_loc; - int i; - int result; - const char *name_start; - - /* - * Get the node we are linking to. - */ - - result = rtems_filesystem_evaluate_path( existing, strlen( existing ), - 0, &existing_loc, true ); - if ( result != 0 ) - return -1; - - /* - * Get the parent of the node we are creating. - */ - - rtems_filesystem_get_start_loc( new, &i, &parent_loc ); - - result = (*parent_loc.ops->evalformake_h)( &new[i], &parent_loc, &name_start ); - if ( result != 0 ) { - rtems_filesystem_freenode( &existing_loc ); - return -1; + int rv = 0; + rtems_filesystem_eval_path_context_t ctx_1; + rtems_filesystem_eval_path_context_t ctx_2; + int eval_flags_1 = RTEMS_LIBIO_FOLLOW_LINK; + int eval_flags_2 = RTEMS_LIBIO_FOLLOW_LINK + | RTEMS_LIBIO_MAKE + | RTEMS_LIBIO_EXCLUSIVE; + const rtems_filesystem_location_info_t *currentloc_1 = + rtems_filesystem_eval_path_start( &ctx_1, path1, eval_flags_1 ); + const rtems_filesystem_location_info_t *currentloc_2 = + rtems_filesystem_eval_path_start( &ctx_2, path2, eval_flags_2 ); + + rv = rtems_filesystem_location_exists_in_same_fs_instance_as( + currentloc_1, + currentloc_2 + ); + if ( rv == 0 ) { + rv = (*currentloc_2->ops->link_h)( + currentloc_2, + currentloc_1, + rtems_filesystem_eval_path_get_token( &ctx_2 ), + rtems_filesystem_eval_path_get_tokenlen( &ctx_2 ) + ); } - /* - * Check to see if the caller is trying to link across file system - * boundaries. - */ - - if ( parent_loc.mt_entry != existing_loc.mt_entry ) { - rtems_filesystem_freenode( &existing_loc ); - rtems_filesystem_freenode( &parent_loc ); - rtems_set_errno_and_return_minus_one( EXDEV ); - } - - result = (*parent_loc.ops->link_h)( &existing_loc, &parent_loc, name_start ); - - rtems_filesystem_freenode( &existing_loc ); - rtems_filesystem_freenode( &parent_loc ); + rtems_filesystem_eval_path_cleanup( &ctx_1 ); + rtems_filesystem_eval_path_cleanup( &ctx_2 ); - return result; + return rv; } /* @@ -85,10 +64,10 @@ int link( int _link_r( struct _reent *ptr __attribute__((unused)), - const char *existing, - const char *new + const char *path1, + const char *path2 ) { - return link( existing, new ); + return link( path1, path2 ); } #endif diff --git a/cpukit/libcsupport/src/lseek.c b/cpukit/libcsupport/src/lseek.c index 3f37029807..7c1f76b36b 100644 --- a/cpukit/libcsupport/src/lseek.c +++ b/cpukit/libcsupport/src/lseek.c @@ -12,64 +12,74 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <stdio.h> +#include <unistd.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -off_t lseek( - int fd, - off_t offset, - int whence -) +off_t lseek( int fd, off_t offset, int whence ) { + off_t rv = 0; rtems_libio_t *iop; - off_t old_offset; - off_t status; + off_t reference_offset; + off_t old_offset; + off_t new_offset; rtems_libio_check_fd( fd ); iop = rtems_libio_iop( fd ); rtems_libio_check_is_open(iop); - /* - * Now process the lseek(). - */ - old_offset = iop->offset; switch ( whence ) { case SEEK_SET: - iop->offset = offset; + reference_offset = 0; break; - case SEEK_CUR: - iop->offset += offset; + reference_offset = old_offset; break; - case SEEK_END: - iop->offset = iop->size + offset; + reference_offset = iop->size; break; - default: - rtems_set_errno_and_return_minus_one( EINVAL ); + errno = EINVAL; + rv = (off_t) -1; + break; + } + new_offset = reference_offset + offset; + + if ( rv == 0 ) { + if ( + (reference_offset >= 0 && new_offset >= offset) + || (reference_offset < 0 && new_offset <= offset) + ) { + switch ( rtems_filesystem_node_type( &iop->pathinfo ) ) { + case RTEMS_FILESYSTEM_DIRECTORY: + case RTEMS_FILESYSTEM_MEMORY_FILE: + if ( new_offset < 0 ) { + errno = EINVAL; + rv = (off_t) -1; + } + break; + default: + break; + } + + if ( rv == 0 ) { + iop->offset = new_offset; + rv = (*iop->pathinfo.handlers->lseek_h)( iop, offset, whence ); + if ( rv == (off_t) -1 ) { + iop->offset = old_offset; + } + } + } else { + errno = EOVERFLOW; + rv = (off_t) -1; + } } - /* - * At this time, handlers assume iop->offset has the desired - * new offset. - */ - - status = (*iop->pathinfo.handlers->lseek_h)( iop, offset, whence ); - if ( status == (off_t) -1 ) - iop->offset = old_offset; - - /* - * So if the operation failed, we have to restore iop->offset. - */ - - return status; + return rv; } /* diff --git a/cpukit/libcsupport/src/lstat.c b/cpukit/libcsupport/src/lstat.c index f034f4aa76..d35713eb04 100644 --- a/cpukit/libcsupport/src/lstat.c +++ b/cpukit/libcsupport/src/lstat.c @@ -17,6 +17,6 @@ #define _STAT_NAME lstat #define _STAT_R_NAME _lstat_r -#define _STAT_FOLLOW_LINKS false +#define _STAT_FOLLOW_LINKS RTEMS_LIBIO_FOLLOW_HARD_LINK #include "stat.c" diff --git a/cpukit/libcsupport/src/mknod.c b/cpukit/libcsupport/src/mknod.c index 29aff43c31..dae2b3bf98 100644 --- a/cpukit/libcsupport/src/mknod.c +++ b/cpukit/libcsupport/src/mknod.c @@ -16,58 +16,65 @@ */ #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 <rtems/libio_.h> -#include <rtems/seterr.h> -int mknod( - const char *pathname, - mode_t mode, - dev_t dev +int rtems_filesystem_mknod( + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev ) { - rtems_filesystem_location_info_t temp_loc; - int i; - const char *name_start; - int result; + int rv = 0; - /* - * The file type is field within the mode. Check we have a sane mode set. - */ - switch (mode & S_IFMT) - { - case S_IFDIR: - case S_IFCHR: + mode &= ~rtems_filesystem_umask; + + switch (mode & S_IFMT) { case S_IFBLK: - case S_IFREG: + case S_IFCHR: + case S_IFDIR: case S_IFIFO: + case S_IFREG: break; default: - rtems_set_errno_and_return_minus_one( EINVAL ); + errno = EINVAL; + rv = -1; + break; } - rtems_filesystem_get_start_loc( pathname, &i, &temp_loc ); + if ( rv == 0 ) { + rv = (*parentloc->ops->mknod_h)( parentloc, name, namelen, mode, dev ); + } - result = (*temp_loc.ops->evalformake_h)( - &pathname[i], - &temp_loc, - &name_start - ); - if ( result != 0 ) - return -1; + return rv; +} - result = (*temp_loc.ops->mknod_h)( name_start, mode, dev, &temp_loc ); +int mknod( const char *path, mode_t mode, dev_t dev ) +{ + int rv = 0; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_LIBIO_FOLLOW_LINK + | RTEMS_LIBIO_MAKE + | RTEMS_LIBIO_EXCLUSIVE + | (S_ISDIR(mode) ? RTEMS_LIBIO_ACCEPT_RESIDUAL_DELIMITERS : 0); + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); + + rv = rtems_filesystem_mknod( + currentloc, + rtems_filesystem_eval_path_get_token( &ctx ), + rtems_filesystem_eval_path_get_tokenlen( &ctx ), + mode, + dev + ); - rtems_filesystem_freenode( &temp_loc ); + rtems_filesystem_eval_path_cleanup( &ctx ); - return result; + return rv; } diff --git a/cpukit/libcsupport/src/mount.c b/cpukit/libcsupport/src/mount.c index 00a07aab3a..47c08f7dba 100644 --- a/cpukit/libcsupport/src/mount.c +++ b/cpukit/libcsupport/src/mount.c @@ -20,22 +20,15 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <sys/types.h> -#include <sys/stat.h> -#include <rtems/chain.h> -#include <rtems/seterr.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> #include <stdlib.h> #include <string.h> #include <rtems/libio_.h> -static RTEMS_CHAIN_DEFINE_EMPTY(mount_chain); +RTEMS_CHAIN_DEFINE_EMPTY(rtems_filesystem_mount_table); /* * Default pathconfs. @@ -55,14 +48,6 @@ const rtems_filesystem_limits_and_options_t rtems_filesystem_default_pathconf = 0 /* posix_vdisable: special char processing, 0=no, 1=yes */ }; -static bool is_node_fs_root( - const rtems_filesystem_mount_table_entry_t *mt_entry, - void *arg -) -{ - return arg == mt_entry->mt_fs_root.node_access; -} - static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry( const char *source_or_null, const char *target_or_null, @@ -76,11 +61,15 @@ static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry( strlen( source_or_null ) + 1 : 0; size_t target_size = strlen( target ) + 1; size_t size = sizeof( rtems_filesystem_mount_table_entry_t ) - + filesystemtype_size + source_size + target_size; + + filesystemtype_size + source_size + target_size + + sizeof( rtems_filesystem_global_location_t ); rtems_filesystem_mount_table_entry_t *mt_entry = calloc( 1, size ); if ( mt_entry != NULL ) { - char *str = (char *) mt_entry + sizeof( *mt_entry ); + rtems_filesystem_global_location_t *mt_fs_root = + (rtems_filesystem_global_location_t *) + ((char *) mt_entry + sizeof( *mt_entry )); + char *str = (char *) mt_fs_root + sizeof( *mt_fs_root ); memcpy( str, filesystemtype, filesystemtype_size ); mt_entry->type = str; @@ -92,6 +81,23 @@ static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry( memcpy( str, target, target_size ); mt_entry->target = str; + str += target_size; + + mt_entry->mounted = true; + mt_entry->mt_fs_root = mt_fs_root; + mt_entry->pathconf_limits_and_options = rtems_filesystem_default_pathconf; + + mt_fs_root->location.mt_entry = mt_entry; + mt_fs_root->reference_count = 1; + + rtems_chain_initialize( + &mt_entry->location_chain, + mt_fs_root, + 1, + sizeof(*mt_fs_root) + ); + } else { + free( mt_entry ); } *target_length_ptr = target_size - 1; @@ -99,184 +105,140 @@ static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry( return mt_entry; } -/* - * mount - * - * This routine will attempt to mount a new file system at the specified - * mount point. A series of tests will be run to determine if any of the - * following reasons exist to prevent the mount operation: - * - * 1) The file system type or options are not valid - * 2) No new file system root node is specified - * 3) The selected file system has already been mounted - * 4) The mount point exists with the proper permissions to allow mounting - * 5) The selected mount point already has a file system mounted to it - * - */ - -int mount( - const char *source, - const char *target, - const char *filesystemtype, - rtems_filesystem_options_t options, - const void *data +static int register_subordinate_file_system( + rtems_filesystem_mount_table_entry_t *mt_entry, + const char *target ) { - rtems_filesystem_fsmount_me_t mount_h = NULL; - rtems_filesystem_location_info_t loc; - rtems_filesystem_mount_table_entry_t *mt_entry = NULL; - rtems_filesystem_location_info_t *loc_to_free = NULL; - bool has_target = target != NULL; - size_t target_length = 0; - - /* - * Are the file system options valid? - */ - - if ( options != RTEMS_FILESYSTEM_READ_ONLY && - options != RTEMS_FILESYSTEM_READ_WRITE ) - rtems_set_errno_and_return_minus_one( EINVAL ); - - /* - * Get mount handler - */ - mount_h = rtems_filesystem_get_mount_handler( filesystemtype ); - if ( !mount_h ) - rtems_set_errno_and_return_minus_one( EINVAL ); - - /* - * Allocate a mount table entry - */ - mt_entry = alloc_mount_table_entry( - source, - target, - filesystemtype, - &target_length - ); - if ( !mt_entry ) - rtems_set_errno_and_return_minus_one( ENOMEM ); - - mt_entry->mt_fs_root.mt_entry = mt_entry; - mt_entry->options = options; - mt_entry->pathconf_limits_and_options = rtems_filesystem_default_pathconf; - - /* - * The mount_point should be a directory with read/write/execute - * permissions in the existing tree. - */ - - if ( has_target ) { - if ( rtems_filesystem_evaluate_path( - target, target_length, RTEMS_LIBIO_PERMS_RWX, &loc, true ) == -1 ) - goto cleanup_and_bail; - - loc_to_free = &loc; - - /* - * Test to see if it is a directory - */ - - if ( loc.ops->node_type_h( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) { - errno = ENOTDIR; - goto cleanup_and_bail; + int rv = 0; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_LIBIO_PERMS_RWX + | RTEMS_LIBIO_FOLLOW_LINK; + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start( &ctx, target, eval_flags ); + + if ( !rtems_filesystem_location_is_root( currentloc ) ) { + rtems_filesystem_location_info_t targetloc; + rtems_filesystem_global_location_t *mt_point_node; + + rtems_filesystem_eval_path_extract_currentloc( &ctx, &targetloc ); + mt_point_node = rtems_filesystem_location_transform_to_global( &targetloc ); + mt_entry->mt_point_node = mt_point_node; + rv = (*mt_point_node->location.ops->mount_h)( mt_entry ); + if ( rv == 0 ) { + rtems_filesystem_mt_lock(); + rtems_chain_append_unprotected( + &rtems_filesystem_mount_table, + &mt_entry->mt_node + ); + rtems_filesystem_mt_unlock(); + } else { + rtems_filesystem_global_location_release( mt_point_node ); } + } else { + rtems_filesystem_eval_path_error( &ctx, EBUSY ); + rv = -1; + } - /* - * You can only mount one file system onto a single mount point. - */ + rtems_filesystem_eval_path_cleanup( &ctx ); - if ( rtems_filesystem_mount_iterate( is_node_fs_root, loc.node_access ) ) { - errno = EBUSY; - goto cleanup_and_bail; - } + return rv; +} - /* - * This must be a good mount point, so move the location information - * into the allocated mount entry. Note: the information that - * may have been allocated in loc should not be sent to freenode - * until the system is unmounted. It may be needed to correctly - * traverse the tree. - */ - - mt_entry->mt_point_node.node_access = loc.node_access; - mt_entry->mt_point_node.handlers = loc.handlers; - mt_entry->mt_point_node.ops = loc.ops; - mt_entry->mt_point_node.mt_entry = loc.mt_entry; - - /* - * This link to the parent is only done when we are dealing with system - * below the base file system - */ - - if ( loc.ops->mount_h( mt_entry ) ) { - goto cleanup_and_bail; - } +static int register_root_file_system( + rtems_filesystem_mount_table_entry_t *mt_entry +) +{ + int rv = 0; + + rtems_filesystem_mt_lock(); + if ( rtems_chain_is_empty( &rtems_filesystem_mount_table ) ) { + rtems_chain_append_unprotected( + &rtems_filesystem_mount_table, + &mt_entry->mt_node + ); } else { - /* - * Do we already have a base file system ? - */ - if ( !rtems_chain_is_empty( &mount_chain ) ) { - errno = EINVAL; - goto cleanup_and_bail; - } - - /* - * This is a mount of the base file system --> The - * mt_point_node.node_access will be left to null to indicate that this - * is the root of the entire file system. - */ + errno = EINVAL; + rv = -1; } - - if ( (*mount_h)( mt_entry, data ) ) { - /* - * Try to undo the mount operation - */ - loc.ops->unmount_h( mt_entry ); - goto cleanup_and_bail; + rtems_filesystem_mt_unlock(); + + if ( rv == 0 ) { + rtems_filesystem_global_location_t *new_fs_root = + rtems_filesystem_global_location_obtain( &mt_entry->mt_fs_root ); + rtems_filesystem_global_location_t *new_fs_current = + rtems_filesystem_global_location_obtain( &mt_entry->mt_fs_root ); + + rtems_filesystem_global_location_assign( + &rtems_filesystem_root, + new_fs_root + ); + rtems_filesystem_global_location_assign( + &rtems_filesystem_current, + new_fs_current + ); } - /* - * Add the mount table entry to the mount table chain - */ - rtems_libio_lock(); - rtems_chain_append( &mount_chain, &mt_entry->Node ); - rtems_libio_unlock(); - - if ( !has_target ) - rtems_filesystem_root = mt_entry->mt_fs_root; - - return 0; - -cleanup_and_bail: - - free( mt_entry ); - - if ( loc_to_free ) - rtems_filesystem_freenode( loc_to_free ); - - return -1; + return rv; } -bool rtems_filesystem_mount_iterate( - rtems_per_filesystem_mount_routine routine, - void *routine_arg +int mount( + const char *source, + const char *target, + const char *filesystemtype, + rtems_filesystem_options_t options, + const void *data ) { - rtems_chain_node *node = NULL; - bool stop = false; - - rtems_libio_lock(); - for ( - node = rtems_chain_first( &mount_chain ); - !rtems_chain_is_tail( &mount_chain, node ) && !stop; - node = rtems_chain_next( node ) - ) { - const rtems_filesystem_mount_table_entry_t *mt_entry = - (rtems_filesystem_mount_table_entry_t *) node; + int rv = 0; - stop = (*routine)( mt_entry, routine_arg ); + if ( + options == RTEMS_FILESYSTEM_READ_ONLY + || options == RTEMS_FILESYSTEM_READ_WRITE + ) { + rtems_filesystem_fsmount_me_t fsmount_me_h = + rtems_filesystem_get_mount_handler( filesystemtype ); + + if ( fsmount_me_h != NULL ) { + size_t target_length = 0; + rtems_filesystem_mount_table_entry_t *mt_entry = alloc_mount_table_entry( + source, + target, + filesystemtype, + &target_length + ); + + if ( mt_entry != NULL ) { + mt_entry->writeable = options == RTEMS_FILESYSTEM_READ_WRITE; + + rv = (*fsmount_me_h)( mt_entry, data ); + if ( rv == 0 ) { + if ( target != NULL ) { + rv = register_subordinate_file_system( mt_entry, target ); + } else { + rv = register_root_file_system( mt_entry ); + } + + if ( rv != 0 ) { + (*mt_entry->mt_fs_root->location.ops->fsunmount_me_h)( mt_entry ); + } + } + + if ( rv != 0 ) { + free( mt_entry ); + } + } else { + errno = ENOMEM; + rv = -1; + } + } else { + errno = EINVAL; + rv = -1; + } + } else { + errno = EINVAL; + rv = -1; } - rtems_libio_unlock(); - return stop; + return rv; } diff --git a/cpukit/libcsupport/src/open.c b/cpukit/libcsupport/src/open.c index a2e1b507e3..6fa7783322 100644 --- a/cpukit/libcsupport/src/open.c +++ b/cpukit/libcsupport/src/open.c @@ -4,6 +4,9 @@ * COPYRIGHT (c) 1989-2010. * 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. @@ -12,185 +15,135 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <stdarg.h> +#include <sys/stat.h> #include <fcntl.h> -#include <rtems/libio_.h> -#include <rtems/seterr.h> - +#include <stdarg.h> #include <unistd.h> -/* - * Returns file descriptor on success or -1 and errno set to one of the - * following: - * - * EACCESS - Seach permission is denied on a component of the path prefix, - * or the file exists and the permissions specified by the - * flags are denied, or the file does not exist and write - * permission is denied for the parent directory of the file - * to be created, or O_TRUNC is specified and write permission - * is denied. - * EEXIST - O_CREAT and O_EXCL are set and the named file exists. - * EINTR - The open( operation was interrupted by a signal. - * EINVAL - This implementation does not support synchronized IO for this - * file. - * EISDIR - The named file is a directory and the flags argument - * specified write or read/write access. - * EMFILE - Too many file descriptors are in used by this process. - * ENAMETOOLONG - - * The length of the path exceeds PATH_MAX or a pathname - * component is longer than NAME_MAX while POSIX_NO_TRUNC - * is in effect. - * ENFILE - Too many files are open in the system. - * ENOENT - O_CREAT is not set and and the anmed file does not exist, - * or O_CREAT is set and either the path prefix does not exist - * or the path argument points to an empty string. - * ENOSPC - The directory or file system that would contain the new file - * cannot be extended. - * ENOTDIR - A component of the path prefix is not a directory. - * ENXIO - O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is - * set, and no process has the file open for reading. - * EROFS - The named file resides on a read-only file system and either - * O_WRONLY, O_RDWR, O_CREAT (if the file does not exist), or - * O_TRUNC is set in the flags argument. - */ +#include <rtems/libio_.h> -int open( - const char *pathname, - int flags, - ... +static void create_regular_file( + rtems_filesystem_eval_path_context_t *ctx, + mode_t mode ) { - va_list ap; - mode_t mode; - int rc; - rtems_libio_t *iop = 0; - int status; - rtems_filesystem_location_info_t loc; - rtems_filesystem_location_info_t *loc_to_free = NULL; - int eval_flags; - - /* - * Set the Evaluation flags - */ - eval_flags = 0; - status = flags + 1; - if ( ( status & _FREAD ) == _FREAD ) - eval_flags |= RTEMS_LIBIO_PERMS_READ; - if ( ( status & _FWRITE ) == _FWRITE ) - eval_flags |= RTEMS_LIBIO_PERMS_WRITE; - - va_start(ap, flags); - - mode = va_arg( ap, mode_t ); + int rv = 0; + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc( ctx ); + const char *token = rtems_filesystem_eval_path_get_token( ctx ); + size_t tokenlen = rtems_filesystem_eval_path_get_tokenlen( ctx ); + + rv = rtems_filesystem_mknod( + currentloc, + token, + tokenlen, + S_IFREG | mode, + 0 + ); + + if ( rv == 0 ) { + /* The mode only applies to future accesses of the newly created file */ + rtems_filesystem_eval_path_set_flags( ctx, 0 ); + + rtems_filesystem_eval_path_set_path( ctx, token, tokenlen ); + rtems_filesystem_eval_path_continue( ctx ); + } else { + rtems_filesystem_eval_path_error( ctx, 0 ); + } +} - /* - * NOTE: This comment is OBSOLETE. The proper way to do this now - * would be to support a magic mounted file system. - * - * Additional external I/O handlers would be supported by adding - * code to pick apart the pathname appropriately. The networking - * code does not require changes here since network file - * descriptors are obtained using socket(), not open(). - */ - - /* allocate a file control block */ - iop = rtems_libio_allocate(); - if ( iop == 0 ) { - rc = ENFILE; - goto done; +static int do_open( + rtems_libio_t *iop, + const char *path, + int oflag, + mode_t mode +) +{ + int rv = 0; + int fd = iop - rtems_libio_iops; + int rwflag = oflag + 1; + bool read_access = (rwflag & _FREAD) == _FREAD; + bool write_access = (rwflag & _FWRITE) == _FWRITE; + bool make = (oflag & O_CREAT) == O_CREAT; + bool exclusive = (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL); + bool truncate = (oflag & O_TRUNC) == O_TRUNC; + int eval_flags = RTEMS_LIBIO_FOLLOW_LINK + | (read_access ? RTEMS_LIBIO_PERMS_READ : 0) + | (write_access ? RTEMS_LIBIO_PERMS_WRITE : 0) + | (make ? RTEMS_LIBIO_MAKE : 0) + | (exclusive ? RTEMS_LIBIO_EXCLUSIVE : 0); + rtems_filesystem_eval_path_context_t ctx; + + rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); + + if ( rtems_filesystem_eval_path_has_token( &ctx ) ) { + create_regular_file( &ctx, mode ); } - /* - * See if the file exists. - */ - status = rtems_filesystem_evaluate_path( - pathname, strlen( pathname ), eval_flags, &loc, true ); + if ( write_access ) { + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc( &ctx ); + rtems_filesystem_node_types_t type = + (*currentloc->ops->node_type_h)( currentloc ); - if ( status == -1 ) { - if ( errno != ENOENT ) { - rc = errno; - goto done; + if ( type == RTEMS_FILESYSTEM_DIRECTORY ) { + rtems_filesystem_eval_path_error( &ctx, EISDIR ); } + } - /* If the file does not exist and we are not trying to create it--> error */ - if ( !(flags & O_CREAT) ) { - rc = ENOENT; - goto done; - } + iop->flags |= rtems_libio_fcntl_flags( oflag ); + rtems_filesystem_eval_path_extract_currentloc( &ctx, &iop->pathinfo ); + rtems_filesystem_eval_path_cleanup( &ctx ); - /* Create the node for the new regular file */ - rc = mknod( pathname, S_IFREG | mode, 0LL ); - if ( rc ) { - rc = errno; - goto done; + rv = (*iop->pathinfo.handlers->open_h)( iop, path, oflag, mode ); + + if ( rv == 0 ) { + if ( truncate ) { + rv = ftruncate( fd, 0 ); + if ( rv != 0 ) { + (*iop->pathinfo.handlers->close_h)( iop ); + } } - /* - * After we do the mknod(), we have to evaluate the path to get the - * "loc" structure needed to actually have the file itself open. - * So we created it, and then we need to have "look it up." - */ - status = rtems_filesystem_evaluate_path( - pathname, strlen( pathname ), 0x0, &loc, true ); - if ( status != 0 ) { /* The file did not exist */ - rc = EACCES; - goto done; + if ( rv == 0 ) { + rv = fd; + } else { + rv = -1; } + } - } else if ((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) { - /* We were trying to create a file that already exists */ - rc = EEXIST; - loc_to_free = &loc; - goto done; + if ( rv < 0 ) { + rtems_libio_free( iop ); } - loc_to_free = &loc; + return rv; +} + +int open( const char *path, int oflag, ... ) +{ + int rv = 0; + va_list ap; + mode_t mode = 0; + rtems_libio_t *iop = NULL; - /* - * Fill in the file control block based on the loc structure - * returned by successful path evaluation. - */ - iop->flags |= rtems_libio_fcntl_flags( flags ); - iop->pathinfo = loc; + va_start( ap, oflag ); - rc = (*iop->pathinfo.handlers->open_h)( iop, pathname, flags, mode ); - if ( rc ) { - rc = errno; - goto done; - } + mode = va_arg( ap, mode_t ); - /* - * Optionally truncate the file. - */ - if ( (flags & O_TRUNC) == O_TRUNC ) { - rc = ftruncate( iop - rtems_libio_iops, 0 ); - if ( rc ) { - if(errno) rc = errno; - close( iop - rtems_libio_iops ); - /* those are released by close(): */ - iop = 0; - loc_to_free = NULL; - } + iop = rtems_libio_allocate(); + if ( iop != NULL ) { + rv = do_open( iop, path, oflag, mode ); + } else { + errno = ENFILE; + rv = -1; } - /* - * Single exit and clean up path. - */ -done: - va_end(ap); - - if ( rc ) { - if ( iop ) - rtems_libio_free( iop ); - if ( loc_to_free ) - rtems_filesystem_freenode( loc_to_free ); - rtems_set_errno_and_return_minus_one( rc ); - } + va_end( ap ); - return iop - rtems_libio_iops; + return rv; } /* @@ -206,10 +159,10 @@ done: int _open_r( struct _reent *ptr __attribute__((unused)), const char *buf, - int flags, + int oflag, int mode ) { - return open( buf, flags, mode ); + return open( buf, oflag, mode ); } #endif diff --git a/cpukit/libcsupport/src/privateenv.c b/cpukit/libcsupport/src/privateenv.c index 89137200b7..28f866272b 100644 --- a/cpukit/libcsupport/src/privateenv.c +++ b/cpukit/libcsupport/src/privateenv.c @@ -1,3 +1,9 @@ +/** + * @file + * + * @ingroup LibIOEnv + */ + /* * Instantiate a private user environment for the calling thread. * @@ -14,191 +20,148 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <stdlib.h> /* free */ +#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ + +#include <stdlib.h> -#include <rtems.h> -#include <rtems/chain.h> #include <rtems/libio_.h> +#include <rtems/score/thread.h> -/* cleanup a user environment - * NOTE: this must be called with - * thread dispatching disabled! - */ -static void -free_user_env(void *venv) +static void free_user_env(void *arg) { - rtems_user_env_t *env = (rtems_user_env_t*) venv ; - - if (env != &rtems_global_user_env - #ifdef HAVE_USERENV_REFCNT - && --env->refcnt <= 0 - #endif - ) { - rtems_filesystem_freenode( &env->current_directory); - rtems_filesystem_freenode( &env->root_directory); - free(env); + rtems_user_env_t *env = arg; + bool uses_global_env = env == &rtems_global_user_env; + + if (!uses_global_env) { + if (env->reference_count == 1) { + rtems_filesystem_global_location_release(env->current_directory); + rtems_filesystem_global_location_release(env->root_directory); + free(env); + } else { + --env->reference_count; + } } } +static void free_user_env_protected(rtems_user_env_t *env) +{ + _Thread_Disable_dispatch(); + free_user_env(env); + _Thread_Enable_dispatch(); +} + rtems_status_code rtems_libio_set_private_env(void) { rtems_status_code sc = RTEMS_SUCCESSFUL; - rtems_id task_id = rtems_task_self(); - rtems_filesystem_location_info_t root_loc; - rtems_filesystem_location_info_t current_loc; - rtems_user_env_t *new_env = NULL; - int rv = 0; - - rv = rtems_filesystem_evaluate_path("/", 1, 0, &root_loc, 0); - if (rv != 0) - goto error_0; - - rv = rtems_filesystem_evaluate_path("/", 1, 0, ¤t_loc, 0); - if (rv != 0) - goto error_1; - - /* - * Malloc is necessary whenever the current task does not - * have its own environment in place. This could be: - * a) it never had one - * OR - * b) it shared another task's environment - */ - - /* - * Bharath: I'm not sure if the check can be reduced to - * if( rtems_current_user_env->task_id != task_id ) { - */ - - if ( - rtems_current_user_env == &rtems_global_user_env - || rtems_current_user_env->task_id != task_id - ) { - new_env = malloc(sizeof(rtems_user_env_t)); - if (new_env == NULL) - goto error_2; - - #ifdef HAVE_USERENV_REFCNT - new_env->refcnt = 1; - #endif - - sc = rtems_task_variable_add( - RTEMS_SELF, - (void*)&rtems_current_user_env, - (void(*)(void *))free_user_env - ); - if (sc != RTEMS_SUCCESSFUL) - goto error_3; - - rtems_current_user_env = new_env; + rtems_id self_task_id = rtems_task_self(); + rtems_user_env_t *old_env = rtems_current_user_env; + bool uses_global_env = old_env == &rtems_global_user_env; + bool uses_shared_env = old_env->task_id != self_task_id; + + if (uses_global_env || uses_shared_env) { + rtems_user_env_t *new_env = calloc(1, sizeof(*new_env)); + + if (new_env != NULL) { + *new_env = *old_env; + new_env->reference_count = 1; + new_env->task_id = self_task_id; + new_env->root_directory = + rtems_filesystem_global_location_obtain(&old_env->root_directory); + new_env->current_directory = + rtems_filesystem_global_location_obtain(&old_env->current_directory); + + if ( + !rtems_filesystem_global_location_is_null(new_env->root_directory) + && !rtems_filesystem_global_location_is_null(new_env->current_directory) + ) { + sc = rtems_task_variable_add( + RTEMS_SELF, + (void **) &rtems_current_user_env, + free_user_env + ); + if (sc == RTEMS_SUCCESSFUL) { + free_user_env_protected(old_env); + rtems_current_user_env = new_env; + } else { + sc = RTEMS_TOO_MANY; + } + } else { + sc = RTEMS_UNSATISFIED; + } + + if (sc != RTEMS_SUCCESSFUL) { + free_user_env(new_env); + } + } else { + sc = RTEMS_NO_MEMORY; + } } - /* Inherit the global values */ - *rtems_current_user_env = rtems_global_user_env; - - rtems_current_user_env->task_id = task_id; - - /* - * Clone the pathlocs. In contrast to most other code we must _not_ free the - * original locs because what we are trying to do here is forking off clones. - * The reason is a pathloc can be allocated by the file system and needs to - * be freed when deleting the environment. - */ - rtems_filesystem_root = root_loc; - rtems_filesystem_current = current_loc; - - return RTEMS_SUCCESSFUL; - -error_3: - free(new_env); - -error_2: - rtems_filesystem_freenode(¤t_loc); - -error_1: - rtems_filesystem_freenode(&root_loc); - -error_0: - return RTEMS_NO_MEMORY; + return sc; } -/* - * Share the same private environment between two tasks: - * Task_id (remote) and RTEMS_SELF(current). - */ - -/* NOTE: - * - * THIS CODE HAS NO PROTECTION IMPLEMENTED - * - * Tasks who wish to share their environments must - * - * a) assert that no participants are concurrently - * executing - * libio_share_private_env() and/or libio_set_private_env() - * - * b) mutex access to rtems_filesystem_current, rtems_filesytem_root - * while changing any of those (chdir(), chroot()). - */ - rtems_status_code rtems_libio_share_private_env(rtems_id task_id) { - rtems_status_code sc; - rtems_user_env_t * shared_user_env; - rtems_id current_task_id; - - /* - * get current task id - */ - current_task_id = rtems_task_self(); - - /* - * If this was an attempt to share the task with self, - * if somebody wanted to do it... Lets tell them, its shared - */ - - if( task_id == current_task_id ) - return RTEMS_SUCCESSFUL; - /* - * Try to get the requested user environment - */ - sc = rtems_task_variable_get( - task_id, - (void*)&rtems_current_user_env, - (void*)&shared_user_env ); - - /* - * If it was not successful, return the error code - */ - if (sc != RTEMS_SUCCESSFUL) - return sc; - - /* - * If we are here, we have the required environment to be - * shared with the current task - */ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_id self_task_id = rtems_task_self(); + + if (task_id != RTEMS_SELF && self_task_id != task_id) { + rtems_user_env_t *env; /* - * If we have a current environment in place, we need to - * free it, since we will be sharing the variable with the - * shared_user_env + * We have to disable the thread dispatching to prevent deletion of the + * environment in the meantime. */ - - if (rtems_current_user_env->task_id==current_task_id) { - rtems_user_env_t *tmp = rtems_current_user_env; - free_user_env( tmp ); + _Thread_Disable_dispatch(); + sc = rtems_task_variable_get( + task_id, + (void *) &rtems_current_user_env, + (void *) &env + ); + if (sc == RTEMS_SUCCESSFUL) { + ++env->reference_count; + } else { + sc = RTEMS_UNSATISFIED; + } + _Thread_Enable_dispatch(); + + if (sc == RTEMS_SUCCESSFUL) { + sc = rtems_task_variable_add( + RTEMS_SELF, + (void **) &rtems_current_user_env, + free_user_env + ); + if (sc == RTEMS_SUCCESSFUL) { + free_user_env_protected(rtems_current_user_env); + rtems_current_user_env = env; + } else { + free_user_env_protected(env); + sc = RTEMS_TOO_MANY; + } + } } - /* the current_user_env is the same pointer that remote env */ - rtems_current_user_env = shared_user_env; + return sc; +} - /* increase the reference count */ -#ifdef HAVE_USERENV_REFCNT - rtems_current_user_env->refcnt++; -#endif +void rtems_libio_use_global_env(void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_user_env_t *env = rtems_current_user_env; + bool uses_private_env = env != &rtems_global_user_env; - return RTEMS_SUCCESSFUL; + if (uses_private_env) { + sc = rtems_task_variable_delete( + RTEMS_SELF, + (void **) &rtems_current_user_env + ); + if (sc != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(0xdeadbeef); + } + + rtems_current_user_env = &rtems_global_user_env; + } } diff --git a/cpukit/libcsupport/src/readlink.c b/cpukit/libcsupport/src/readlink.c index 1880ed667e..e2c88e866c 100644 --- a/cpukit/libcsupport/src/readlink.c +++ b/cpukit/libcsupport/src/readlink.c @@ -12,37 +12,31 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif +#include <unistd.h> + #include <rtems/libio_.h> -#include <rtems/seterr.h> -ssize_t readlink( - const char *pathname, - char *buf, - size_t bufsize -) +ssize_t readlink( const char *path, char *buf, size_t bufsize ) { - rtems_filesystem_location_info_t loc; - int result; - - if (!buf) - rtems_set_errno_and_return_minus_one( EFAULT ); - - result = rtems_filesystem_evaluate_path( pathname, strlen( pathname ), - 0, &loc, false ); - if ( result != 0 ) - return -1; - - if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_SYM_LINK ){ - rtems_filesystem_freenode( &loc ); - rtems_set_errno_and_return_minus_one( EINVAL ); + ssize_t rv = 0; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_LIBIO_FOLLOW_HARD_LINK; + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); + rtems_filesystem_node_types_t type = + (*currentloc->ops->node_type_h)( currentloc ); + + if ( type == RTEMS_FILESYSTEM_SYM_LINK ) { + rv = (*currentloc->ops->readlink_h)( currentloc, buf, bufsize ); + } else { + rtems_filesystem_eval_path_error( &ctx, EINVAL ); + rv = -1; } - result = (*loc.ops->readlink_h)( &loc, buf, bufsize ); - - rtems_filesystem_freenode( &loc ); + rtems_filesystem_eval_path_cleanup( &ctx ); - return result; + return rv; } diff --git a/cpukit/libcsupport/src/rmdir.c b/cpukit/libcsupport/src/rmdir.c index d7d4edf675..07ecbb3a0d 100644 --- a/cpukit/libcsupport/src/rmdir.c +++ b/cpukit/libcsupport/src/rmdir.c @@ -12,84 +12,44 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <sys/types.h> -#include <fcntl.h> #include <unistd.h> -#include <errno.h> -#include <stdlib.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -int rmdir( - const char *pathname -) +int rmdir( const char *path ) { - int parentpathlen; - const char *name; - rtems_filesystem_location_info_t parentloc; - rtems_filesystem_location_info_t loc; - int i; - int result; - bool free_parentloc = false; - - /* - * Get the parent node of the node we wish to remove. Find the parent path. - */ - - parentpathlen = rtems_filesystem_dirname ( pathname ); - - if ( parentpathlen == 0 ) - rtems_filesystem_get_start_loc( pathname, &i, &parentloc ); - else { - result = rtems_filesystem_evaluate_path(pathname, parentpathlen, - RTEMS_LIBIO_PERMS_WRITE, - &parentloc, - false ); - if ( result != 0 ) - return -1; - - free_parentloc = true; - } - - /* - * Start from the parent to find the node that should be under it. - */ - - loc = parentloc; - name = pathname + parentpathlen; - name += rtems_filesystem_prefix_separators( name, strlen( name ) ); - - result = rtems_filesystem_evaluate_relative_path( name , strlen( name ), - 0, &loc, false ); - if ( result != 0 ) { - if ( free_parentloc ) - rtems_filesystem_freenode( &parentloc ); - return -1; - } - - /* - * Verify you can remove this node as a directory. - */ - if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) { - rtems_filesystem_freenode( &loc ); - if ( free_parentloc ) - rtems_filesystem_freenode( &parentloc ); - rtems_set_errno_and_return_minus_one( ENOTDIR ); + int rv = 0; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_LIBIO_REJECT_TERMINAL_DOT; + rtems_filesystem_location_info_t parentloc; + int parent_eval_flags = RTEMS_LIBIO_PERMS_WRITE + | RTEMS_LIBIO_PERMS_SEARCH + | RTEMS_LIBIO_FOLLOW_LINK; + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start_with_parent( + &ctx, + path, + eval_flags, + &parentloc, + parent_eval_flags + ); + rtems_filesystem_node_types_t type = + (*currentloc->ops->node_type_h)( currentloc ); + + if ( type == RTEMS_FILESYSTEM_DIRECTORY ) { + rv = (*currentloc->ops->rmnod_h)( + &parentloc, + currentloc + ); + } else { + rtems_filesystem_eval_path_error( &ctx, ENOTDIR ); + rv = -1; } - /* - * Use the filesystems rmnod to remove the node. - */ - - result = (*loc.handlers->rmnod_h)( &parentloc, &loc ); - - rtems_filesystem_freenode( &loc ); - if ( free_parentloc ) - rtems_filesystem_freenode( &parentloc ); + rtems_filesystem_eval_path_cleanup_with_parent( &ctx, &parentloc ); - return result; + return rv; } diff --git a/cpukit/libcsupport/src/stat.c b/cpukit/libcsupport/src/stat.c index 9f06deaa52..af56fd87be 100644 --- a/cpukit/libcsupport/src/stat.c +++ b/cpukit/libcsupport/src/stat.c @@ -14,7 +14,7 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif /* @@ -25,55 +25,29 @@ #ifndef _STAT_NAME #define _STAT_NAME stat #define _STAT_R_NAME _stat_r -#define _STAT_FOLLOW_LINKS true +#define _STAT_FOLLOW_LINKS RTEMS_LIBIO_FOLLOW_LINK #endif - -#include <rtems.h> - -#include <rtems/libio.h> -#include <sys/types.h> #include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> #include <string.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -int _STAT_NAME( - const char *path, - struct stat *buf -) +int _STAT_NAME( const char *path, struct stat *buf ) { - int status; - rtems_filesystem_location_info_t loc; - - /* - * Check to see if we were passed a valid pointer. - */ - - if ( !buf ) - rtems_set_errno_and_return_minus_one( EFAULT ); - - status = rtems_filesystem_evaluate_path( path, strlen( path ), - 0, &loc, _STAT_FOLLOW_LINKS ); - if ( status != 0 ) - return -1; - - /* - * Zero out the stat structure so the various support - * versions of stat don't have to. - */ + int rv = 0; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = _STAT_FOLLOW_LINKS; + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); - memset( buf, 0, sizeof(struct stat) ); + memset( buf, 0, sizeof( *buf ) ); - status = (*loc.handlers->fstat_h)( &loc, buf ); + rv = (*currentloc->handlers->fstat_h)( currentloc, buf ); - rtems_filesystem_freenode( &loc ); + rtems_filesystem_eval_path_cleanup( &ctx ); - return status; + return rv; } /* diff --git a/cpukit/libcsupport/src/statvfs.c b/cpukit/libcsupport/src/statvfs.c index 599aa7edc1..61d6d8e271 100644 --- a/cpukit/libcsupport/src/statvfs.c +++ b/cpukit/libcsupport/src/statvfs.c @@ -13,40 +13,27 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <rtems/libio_.h> -#include <rtems/seterr.h> - #include <sys/statvfs.h> +#include <string.h> -int -statvfs (const char *path, struct statvfs *sb) -{ - rtems_filesystem_location_info_t loc; - rtems_filesystem_location_info_t *fs_mount_root; - rtems_filesystem_mount_table_entry_t *mt_entry; - int result; - - /* - * Get - * The root node of the mounted filesytem. - * The node for the directory that the fileystem is mounted on. - * The mount entry that is being refered to. - */ - - if ( rtems_filesystem_evaluate_path( path, strlen( path ), 0x0, &loc, true ) ) - return -1; +#include <rtems/libio_.h> - mt_entry = loc.mt_entry; - fs_mount_root = &mt_entry->mt_fs_root; +int statvfs( const char *path, struct statvfs *buf ) +{ + int rv = 0; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_LIBIO_FOLLOW_LINK; + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); - memset (sb, 0, sizeof (struct statvfs)); + memset( buf, 0, sizeof( *buf ) ); - result = ( fs_mount_root->ops->statvfs_h )( fs_mount_root, sb ); + rv = (*currentloc->ops->statvfs_h)( currentloc, buf ); - rtems_filesystem_freenode( &loc ); + rtems_filesystem_eval_path_cleanup( &ctx ); - return result; + return rv; } diff --git a/cpukit/libcsupport/src/sup_fs_check_permissions.c b/cpukit/libcsupport/src/sup_fs_check_permissions.c new file mode 100644 index 0000000000..8dcecb6119 --- /dev/null +++ b/cpukit/libcsupport/src/sup_fs_check_permissions.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> + +bool rtems_filesystem_check_access( + int eval_flags, + mode_t node_mode, + uid_t node_uid, + gid_t node_gid +) +{ + mode_t perm_flags = eval_flags & RTEMS_LIBIO_PERMS_RWX; + uid_t task_uid = geteuid(); + + if (task_uid == 0 || task_uid == node_uid) { + perm_flags <<= 6; + } else { + gid_t task_gid = getegid(); + + if (task_gid == 0 || task_gid == node_gid) { + perm_flags <<= 3; + } else { + perm_flags <<= 0; + } + } + + return (perm_flags & node_mode) == perm_flags; +} + +bool rtems_filesystem_eval_path_check_access( + rtems_filesystem_eval_path_context_t *ctx, + int eval_flags, + mode_t node_mode, + uid_t node_uid, + gid_t node_gid +) +{ + bool access_ok = rtems_filesystem_check_access( + eval_flags, + node_mode, + node_uid, + node_gid + ); + + if (!access_ok) { + rtems_filesystem_eval_path_error(ctx, EACCES); + } + + return access_ok; +} diff --git a/cpukit/libcsupport/src/sup_fs_eval_path.c b/cpukit/libcsupport/src/sup_fs_eval_path.c new file mode 100644 index 0000000000..1940cce745 --- /dev/null +++ b/cpukit/libcsupport/src/sup_fs_eval_path.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> + +static size_t get_parentpathlen(const char *path, size_t pathlen) +{ + while (pathlen > 0) { + size_t i = pathlen - 1; + + if (rtems_filesystem_is_delimiter(path [i])) { + return pathlen; + } + + pathlen = i; + } + + return 0; +} + +static void set_startloc( + rtems_filesystem_eval_path_context_t *ctx, + rtems_filesystem_global_location_t *const *global_root_ptr, + rtems_filesystem_global_location_t *const *global_current_ptr +) +{ + if (ctx->pathlen > 0) { + char c = ctx->path [0]; + + ctx->rootloc = rtems_filesystem_global_location_obtain(global_root_ptr); + + if (rtems_filesystem_is_delimiter(c)) { + ++ctx->path; + --ctx->pathlen; + ctx->startloc = rtems_filesystem_global_location_obtain( + &ctx->rootloc + ); + } else { + ctx->startloc = rtems_filesystem_global_location_obtain( + global_current_ptr + ); + } + } else { + ctx->rootloc = rtems_filesystem_global_location_obtain_null(); + ctx->startloc = rtems_filesystem_global_location_obtain_null(); + errno = ENOENT; + } +} + +static void check_access( + rtems_filesystem_eval_path_context_t *ctx, + int eval_flags +) +{ + const rtems_filesystem_location_info_t *currentloc = &ctx->currentloc; + struct stat st; + int rv; + + st.st_mode = 0; + st.st_uid = 0; + st.st_gid = 0; + rv = (*currentloc->handlers->fstat_h)(currentloc, &st); + if (rv == 0) { + bool access_ok = rtems_filesystem_check_access( + eval_flags, + st.st_mode, + st.st_uid, + st.st_gid + ); + + if (!access_ok) { + rtems_filesystem_eval_path_error(ctx, EACCES); + } + } else { + rtems_filesystem_eval_path_error(ctx, 0); + } +} + +void rtems_filesystem_eval_path_continue( + rtems_filesystem_eval_path_context_t *ctx +) +{ + int eval_flags; + + while (ctx->pathlen > 0) { + (*ctx->currentloc.ops->eval_path_h)(ctx); + } + + eval_flags = rtems_filesystem_eval_path_get_flags(ctx); + if (rtems_filesystem_eval_path_has_token(ctx)) { + bool make = (eval_flags & RTEMS_LIBIO_MAKE) != 0; + + if (make) { + check_access(ctx, RTEMS_LIBIO_PERMS_WRITE); + } else { + rtems_filesystem_eval_path_error(ctx, ENOENT); + } + } else { + bool exclusive = (eval_flags & RTEMS_LIBIO_EXCLUSIVE) != 0; + + if (!exclusive) { + check_access(ctx, ctx->flags); + } else { + rtems_filesystem_eval_path_error(ctx, EEXIST); + } + } +} + +static rtems_filesystem_location_info_t * +eval_path_start( + rtems_filesystem_eval_path_context_t *ctx, + const char *path, + size_t pathlen, + int eval_flags, + rtems_filesystem_global_location_t *const *global_root_ptr, + rtems_filesystem_global_location_t *const *global_current_ptr +) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->path = path; + ctx->pathlen = pathlen; + ctx->flags = eval_flags; + + set_startloc(ctx, global_root_ptr, global_current_ptr); + + rtems_filesystem_instance_lock(&ctx->startloc->location); + + rtems_filesystem_location_clone( + &ctx->currentloc, + &ctx->startloc->location + ); + + rtems_filesystem_eval_path_continue(ctx); + + return &ctx->currentloc; +} + +rtems_filesystem_location_info_t * +rtems_filesystem_eval_path_start_with_root_and_current( + rtems_filesystem_eval_path_context_t *ctx, + const char *path, + int eval_flags, + rtems_filesystem_global_location_t *const *global_root_ptr, + rtems_filesystem_global_location_t *const *global_current_ptr +) +{ + return eval_path_start( + ctx, + path, + strlen(path), + eval_flags, + global_root_ptr, + global_current_ptr + ); +} + +rtems_filesystem_location_info_t * +rtems_filesystem_eval_path_start( + rtems_filesystem_eval_path_context_t *ctx, + const char *path, + int eval_flags +) +{ + return rtems_filesystem_eval_path_start_with_root_and_current( + ctx, + path, + eval_flags, + &rtems_filesystem_root, + &rtems_filesystem_current + ); +} + +rtems_filesystem_location_info_t * +rtems_filesystem_eval_path_start_with_parent( + rtems_filesystem_eval_path_context_t *ctx, + const char *path, + int eval_flags, + rtems_filesystem_location_info_t *parentloc, + int parent_eval_flags +) +{ + size_t pathlen = strlen(path); + const char *parentpath = path; + size_t parentpathlen = get_parentpathlen(path, pathlen); + const char *name = NULL; + size_t namelen = 0; + const rtems_filesystem_location_info_t *currentloc = NULL; + + if (pathlen > 0) { + if (parentpathlen == 0) { + parentpath = "."; + parentpathlen = 1; + name = path; + namelen = pathlen; + } else { + name = path + parentpathlen; + namelen = pathlen - parentpathlen; + } + } + + currentloc = eval_path_start( + ctx, + parentpath, + parentpathlen, + parent_eval_flags, + &rtems_filesystem_root, + &rtems_filesystem_current + ); + + rtems_filesystem_location_clone(parentloc, currentloc); + + ctx->path = name; + ctx->pathlen = namelen; + ctx->flags = eval_flags; + + rtems_filesystem_eval_path_continue(ctx); + + return &ctx->currentloc; +} + +void rtems_filesystem_eval_path_recursive( + rtems_filesystem_eval_path_context_t *ctx, + const char *path, + size_t pathlen +) +{ + if (pathlen > 0) { + if (ctx->recursionlevel < RTEMS_FILESYSTEM_SYMLOOP_MAX) { + const char *saved_path = ctx->path; + size_t saved_pathlen = ctx->pathlen; + + if (rtems_filesystem_is_delimiter(path [0])) { + rtems_filesystem_eval_path_restart(ctx, &ctx->rootloc); + } + + ctx->path = path; + ctx->pathlen = pathlen; + + ++ctx->recursionlevel; + while (ctx->pathlen > 0) { + (*ctx->currentloc.ops->eval_path_h)(ctx); + } + --ctx->recursionlevel; + + ctx->path = saved_path; + ctx->pathlen = saved_pathlen; + } else { + rtems_filesystem_eval_path_error(ctx, ELOOP); + } + } else { + rtems_filesystem_eval_path_error(ctx, ENOENT); + } +} + +void rtems_filesystem_eval_path_error( + rtems_filesystem_eval_path_context_t *ctx, + int eno +) +{ + ctx->path = NULL; + ctx->pathlen = 0; + ctx->token = NULL; + ctx->tokenlen = 0; + + if (!rtems_filesystem_location_is_null(&ctx->currentloc)) { + if (eno != 0) { + errno = eno; + } + + rtems_filesystem_location_detach(&ctx->currentloc); + } +} + +static void free_location(rtems_filesystem_location_info_t *loc) +{ + rtems_filesystem_mt_entry_declare_lock_context(lock_context); + + (*loc->ops->freenod_h)(loc); + + rtems_filesystem_mt_entry_lock(lock_context); + rtems_chain_extract_unprotected(&loc->mt_entry_node); + rtems_filesystem_mt_entry_unlock(lock_context); +} + +void rtems_filesystem_eval_path_cleanup( + rtems_filesystem_eval_path_context_t *ctx +) +{ + free_location(&ctx->currentloc); + rtems_filesystem_instance_unlock(&ctx->startloc->location); + rtems_filesystem_global_location_release(ctx->startloc); + rtems_filesystem_global_location_release(ctx->rootloc); +} + +void rtems_filesystem_eval_path_cleanup_with_parent( + rtems_filesystem_eval_path_context_t *ctx, + rtems_filesystem_location_info_t *parentloc +) +{ + free_location(parentloc); + rtems_filesystem_eval_path_cleanup(ctx); +} + +void rtems_filesystem_eval_path_restart( + rtems_filesystem_eval_path_context_t *ctx, + rtems_filesystem_global_location_t **newstartloc_ptr +) +{ + free_location(&ctx->currentloc); + rtems_filesystem_instance_unlock(&ctx->startloc->location); + rtems_filesystem_global_location_assign( + &ctx->startloc, + rtems_filesystem_global_location_obtain(newstartloc_ptr) + ); + rtems_filesystem_instance_lock(&ctx->startloc->location); + rtems_filesystem_location_clone(&ctx->currentloc, &ctx->startloc->location); +} diff --git a/cpukit/libcsupport/src/sup_fs_eval_path_generic.c b/cpukit/libcsupport/src/sup_fs_eval_path_generic.c new file mode 100644 index 0000000000..c789ee4f64 --- /dev/null +++ b/cpukit/libcsupport/src/sup_fs_eval_path_generic.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> + +static bool is_fs_root( const rtems_filesystem_location_info_t *loc ) +{ + const rtems_filesystem_location_info_t *mt_fs_root = + &loc->mt_entry->mt_fs_root->location; + + return (*loc->ops->are_nodes_equal_h)( loc, mt_fs_root ); +} + +static bool is_eval_path_root( + const rtems_filesystem_eval_path_context_t *ctx, + const rtems_filesystem_location_info_t *loc +) +{ + const rtems_filesystem_location_info_t *rootloc = &ctx->rootloc->location; + + return loc->mt_entry == rootloc->mt_entry + && (*loc->ops->are_nodes_equal_h)( loc, rootloc ); +} + +void rtems_filesystem_eval_path_generic( + rtems_filesystem_eval_path_context_t *ctx, + void *arg, + const rtems_filesystem_eval_path_generic_config *config +) +{ + rtems_filesystem_eval_path_generic_status status = + RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; + + while (status == RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE) { + const char *token; + size_t tokenlen; + + rtems_filesystem_eval_path_get_next_token(ctx, &token, &tokenlen); + + if (tokenlen > 0) { + if ((*config->is_directory)(ctx, arg)) { + if (rtems_filesystem_is_current_directory(token, tokenlen)) { + if (rtems_filesystem_eval_path_has_path(ctx)) { + status = (*config->eval_token)(ctx, arg, ".", 1); + } else { + int eval_flags = rtems_filesystem_eval_path_get_flags(ctx); + + if ((eval_flags & RTEMS_LIBIO_REJECT_TERMINAL_DOT) == 0) { + status = (*config->eval_token)(ctx, arg, ".", 1); + } else { + rtems_filesystem_eval_path_error(ctx, EINVAL); + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE; + } + } + } else if (rtems_filesystem_is_parent_directory(token, tokenlen)) { + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc( ctx ); + + if (is_eval_path_root(ctx, currentloc)) { + /* This prevents the escape from a chroot() environment */ + status = (*config->eval_token)(ctx, arg, ".", 1); + } else if (is_fs_root(currentloc)) { + if (currentloc->mt_entry->mt_point_node != NULL) { + rtems_filesystem_eval_path_put_back_token(ctx); + rtems_filesystem_eval_path_restart( + ctx, + ¤tloc->mt_entry->mt_point_node + ); + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE; + } else { + /* This is the root file system */ + status = (*config->eval_token)(ctx, arg, ".", 1); + } + } else { + status = (*config->eval_token)(ctx, arg, "..", 2); + } + } else { + status = (*config->eval_token)(ctx, arg, token, tokenlen); + } + + if (status == RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY) { + if (rtems_filesystem_eval_path_has_path(ctx)) { + int eval_flags; + + rtems_filesystem_eval_path_eat_delimiter(ctx); + eval_flags = rtems_filesystem_eval_path_get_flags(ctx); + if ( + (eval_flags & RTEMS_LIBIO_ACCEPT_RESIDUAL_DELIMITERS) == 0 + || rtems_filesystem_eval_path_has_path(ctx) + ) { + rtems_filesystem_eval_path_error(ctx, ENOENT); + } + } + } + } else { + rtems_filesystem_eval_path_error(ctx, ENOTDIR); + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE; + } + } else { + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE; + } + } +} diff --git a/cpukit/libcsupport/src/sup_fs_exist_in_same_instance.c b/cpukit/libcsupport/src/sup_fs_exist_in_same_instance.c new file mode 100644 index 0000000000..71a4d43b7c --- /dev/null +++ b/cpukit/libcsupport/src/sup_fs_exist_in_same_instance.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> + +int rtems_filesystem_location_exists_in_same_fs_instance_as( + const rtems_filesystem_location_info_t *a, + const rtems_filesystem_location_info_t *b +) +{ + int rv = -1; + + if ( + !rtems_filesystem_location_is_null( a ) + && !rtems_filesystem_location_is_null( b ) + ) { + if ( a->mt_entry == b->mt_entry ) { + rv = 0; + } else { + errno = EXDEV; + } + } + + return rv; +} diff --git a/cpukit/libcsupport/src/sup_fs_get_start_loc.c b/cpukit/libcsupport/src/sup_fs_get_start_loc.c deleted file mode 100644 index 89f7efbb0d..0000000000 --- a/cpukit/libcsupport/src/sup_fs_get_start_loc.c +++ /dev/null @@ -1,48 +0,0 @@ - /** - * @file src/sup_fs_get_start_loc.c - */ - -/* - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * 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$ - */ - -/* - * rtems_filesystem_get_start_loc - * - * Function to determine if path is absolute or relative - * - * Parameters: - * - * path : IN - path to be checked - * index: OUT - 0, if relative, 1 if absolute - * loc : OUT - location info of root fs if absolute - * location info of current fs if relative - * - * Returns: void - */ - -/* Includes */ - -#include "rtems/libio_.h" - -void rtems_filesystem_get_start_loc(const char *path, - int *index, - rtems_filesystem_location_info_t *loc) -{ - if (rtems_filesystem_is_separator(path[0])) { - *loc = rtems_filesystem_root; - *index = 1; - } - else { - *loc = rtems_filesystem_current; - *index = 0; - } -} diff --git a/cpukit/libcsupport/src/sup_fs_get_sym_start_loc.c b/cpukit/libcsupport/src/sup_fs_get_sym_start_loc.c deleted file mode 100644 index 4bcc964a46..0000000000 --- a/cpukit/libcsupport/src/sup_fs_get_sym_start_loc.c +++ /dev/null @@ -1,47 +0,0 @@ - /** - * @file src/sup_fs_get_sym_start_loc.c - */ - -/* - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * 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$ - */ - -/* - * rtems_filesystem_get_sym_start_loc - * - * Function to determine if path is absolute or relative - * - * Parameters: - * - * path : IN - path to be checked - * index: OUT - 0, if relative, 1 if absolute - * loc : OUT - location info of root fs if absolute - * location info of current fs if relative - * - * Returns: void - */ - -/* Includes */ - -#include "rtems/libio_.h" - -void rtems_filesystem_get_sym_start_loc(const char *path, - int *index, - rtems_filesystem_location_info_t *loc) -{ - if (rtems_filesystem_is_separator(path[0])) { - *loc = rtems_filesystem_root; - *index = 1; - } - else { - *index = 0; - } -} diff --git a/cpukit/libcsupport/src/sup_fs_is_separator.c b/cpukit/libcsupport/src/sup_fs_is_separator.c deleted file mode 100644 index 2c695e0335..0000000000 --- a/cpukit/libcsupport/src/sup_fs_is_separator.c +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @file src/sup_fs_is_separator.c - */ - -/* - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * 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$ - */ - -#include <rtems/libio_.h> - -/* - * rtems_filesystem_is_separator - * - * Function to determine if a character is a path name separator. - * This was originally a macro in libio_.h - * - * NOTE: This function handles MS-DOS and UNIX style names. - */ - -int rtems_filesystem_is_separator(char ch) -{ - return ((ch == '/') || (ch == '\\') || (ch == '\0')); -} diff --git a/cpukit/libcsupport/src/sup_fs_location.c b/cpukit/libcsupport/src/sup_fs_location.c new file mode 100644 index 0000000000..5234c01ddc --- /dev/null +++ b/cpukit/libcsupport/src/sup_fs_location.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ + +#include <stdlib.h> + +#include <rtems/libio_.h> +#include <rtems/score/thread.h> + +static rtems_filesystem_global_location_t *deferred_released_global_locations; + +rtems_filesystem_location_info_t *rtems_filesystem_location_copy( + rtems_filesystem_location_info_t *dst, + const rtems_filesystem_location_info_t *src +) +{ + dst->node_access = src->node_access; + dst->node_access_2 = src->node_access_2; + dst->handlers = src->handlers; + dst->ops = src->ops; + dst->mt_entry = src->mt_entry; + rtems_filesystem_location_add_to_mt_entry(dst); + + return dst; +} + +void rtems_filesystem_location_detach( + rtems_filesystem_location_info_t *detach +) +{ + rtems_filesystem_location_free(detach); + rtems_filesystem_location_initialize_to_null(detach); +} + +void rtems_filesystem_location_copy_and_detach( + rtems_filesystem_location_info_t *copy, + rtems_filesystem_location_info_t *detach +) +{ + rtems_filesystem_location_copy(copy, detach); + rtems_filesystem_location_remove_from_mt_entry(detach); + rtems_filesystem_location_initialize_to_null(detach); +} + +rtems_filesystem_global_location_t *rtems_filesystem_location_transform_to_global( + rtems_filesystem_location_info_t *loc +) +{ + rtems_filesystem_global_location_t *global_loc = malloc(sizeof(*global_loc)); + + if (global_loc != NULL) { + global_loc->reference_count = 1; + global_loc->deferred_released_next = NULL; + global_loc->deferred_released_count = 0; + rtems_filesystem_location_copy(&global_loc->location, loc); + rtems_filesystem_location_remove_from_mt_entry(loc); + } else { + rtems_filesystem_location_free(loc); + global_loc = rtems_filesystem_global_location_obtain_null(); + errno = ENOMEM; + } + + return global_loc; +} + +void rtems_filesystem_global_location_assign( + rtems_filesystem_global_location_t **lhs_global_loc_ptr, + rtems_filesystem_global_location_t *rhs_global_loc +) +{ + rtems_filesystem_mt_entry_declare_lock_context(lock_context); + rtems_filesystem_global_location_t *lhs_global_loc; + + rtems_filesystem_mt_entry_lock(lock_context); + lhs_global_loc = *lhs_global_loc_ptr; + *lhs_global_loc_ptr = rhs_global_loc; + rtems_filesystem_mt_entry_unlock(lock_context); + + rtems_filesystem_global_location_release(lhs_global_loc); +} + +static void release_with_count( + rtems_filesystem_global_location_t *global_loc, + int count +) +{ + rtems_filesystem_mount_table_entry_t *mt_entry = + global_loc->location.mt_entry; + rtems_filesystem_mt_entry_declare_lock_context(lock_context); + bool do_free; + bool do_unmount; + + rtems_filesystem_mt_entry_lock(lock_context); + global_loc->reference_count -= count; + do_free = global_loc->reference_count == 0; + do_unmount = rtems_filesystem_is_ready_for_unmount(mt_entry); + rtems_filesystem_mt_entry_unlock(lock_context); + + if (do_free) { + rtems_filesystem_location_free(&global_loc->location); + free(global_loc); + } + + if (do_unmount) { + rtems_filesystem_do_unmount(mt_entry); + } +} + +static void deferred_release(void) +{ + rtems_filesystem_global_location_t *current = NULL; + + do { + int count = 0; + + _Thread_Disable_dispatch(); + current = deferred_released_global_locations; + if (current != NULL) { + deferred_released_global_locations = current->deferred_released_next; + count = current->deferred_released_count; + current->deferred_released_next = NULL; + current->deferred_released_count = 0; + } + _Thread_Enable_dispatch(); + + if (current != NULL) { + release_with_count(current, count); + } + } while (current != NULL); +} + +rtems_filesystem_global_location_t *rtems_filesystem_global_location_obtain( + rtems_filesystem_global_location_t *const *global_loc_ptr +) +{ + rtems_filesystem_mt_entry_declare_lock_context(lock_context); + rtems_filesystem_global_location_t *global_loc; + + if (deferred_released_global_locations != NULL) { + deferred_release(); + } + + rtems_filesystem_mt_entry_lock(lock_context); + global_loc = *global_loc_ptr; + if (global_loc == NULL || !global_loc->location.mt_entry->mounted) { + global_loc = &rtems_filesystem_global_location_null; + errno = ENXIO; + } + ++global_loc->reference_count; + rtems_filesystem_mt_entry_unlock(lock_context); + + return global_loc; +} + +void rtems_filesystem_global_location_release( + rtems_filesystem_global_location_t *global_loc +) +{ + if (!_Thread_Dispatch_in_critical_section()) { + release_with_count(global_loc, 1); + } else { + if (global_loc->deferred_released_count == 0) { + rtems_filesystem_global_location_t *head = + deferred_released_global_locations; + + global_loc->deferred_released_count = 1; + global_loc->deferred_released_next = head; + deferred_released_global_locations = global_loc; + } else { + ++global_loc->deferred_released_count; + } + } +} + +void rtems_filesystem_location_remove_from_mt_entry( + rtems_filesystem_location_info_t *loc +) +{ + rtems_filesystem_mt_entry_declare_lock_context(lock_context); + bool do_unmount; + + rtems_filesystem_mt_entry_lock(lock_context); + rtems_chain_extract_unprotected(&loc->mt_entry_node); + do_unmount = rtems_filesystem_is_ready_for_unmount(loc->mt_entry); + rtems_filesystem_mt_entry_unlock(lock_context); + + if (do_unmount) { + rtems_filesystem_do_unmount(loc->mt_entry); + } +} + +void rtems_filesystem_do_unmount( + rtems_filesystem_mount_table_entry_t *mt_entry +) +{ + rtems_filesystem_mt_lock(); + rtems_chain_extract_unprotected(&mt_entry->mt_node); + rtems_filesystem_mt_unlock(); + rtems_filesystem_global_location_release(mt_entry->mt_point_node); + (*mt_entry->mt_fs_root->location.ops->fsunmount_me_h)(mt_entry); + free(mt_entry); +} diff --git a/cpukit/libcsupport/src/sup_fs_mount_iterate.c b/cpukit/libcsupport/src/sup_fs_mount_iterate.c new file mode 100644 index 0000000000..88cfca828c --- /dev/null +++ b/cpukit/libcsupport/src/sup_fs_mount_iterate.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> + +bool rtems_filesystem_mount_iterate( + rtems_filesystem_mt_entry_visitor visitor, + void *visitor_arg +) +{ + rtems_chain_control *chain = &rtems_filesystem_mount_table; + rtems_chain_node *node = NULL; + bool stop = false; + + rtems_filesystem_mt_lock(); + for ( + node = rtems_chain_first( chain ); + !rtems_chain_is_tail( chain, node ) && !stop; + node = rtems_chain_next( node ) + ) { + const rtems_filesystem_mount_table_entry_t *mt_entry = + (rtems_filesystem_mount_table_entry_t *) node; + + stop = (*visitor)( mt_entry, visitor_arg ); + } + rtems_filesystem_mt_unlock(); + + return stop; +} diff --git a/cpukit/libcsupport/src/sup_fs_next_token.c b/cpukit/libcsupport/src/sup_fs_next_token.c new file mode 100644 index 0000000000..451d81bbfe --- /dev/null +++ b/cpukit/libcsupport/src/sup_fs_next_token.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> + +void rtems_filesystem_eval_path_eat_delimiter( + rtems_filesystem_eval_path_context_t *ctx +) +{ + const char *current = ctx->path; + const char *end = current + ctx->pathlen; + + while (current != end && rtems_filesystem_is_delimiter(*current)) { + ++current; + } + + ctx->path = current; + ctx->pathlen = (size_t) (end - current); +} + +static void next_token(rtems_filesystem_eval_path_context_t *ctx) +{ + const char *begin = ctx->path; + const char *end = begin + ctx->pathlen; + const char *current = begin; + + while (current != end && !rtems_filesystem_is_delimiter(*current)) { + ++current; + } + + ctx->path = current; + ctx->pathlen = (size_t) (end - current); + ctx->token = begin; + ctx->tokenlen = (size_t) (current - begin); +} + +void rtems_filesystem_eval_path_next_token( + rtems_filesystem_eval_path_context_t *ctx +) +{ + rtems_filesystem_eval_path_eat_delimiter(ctx); + next_token(ctx); +} diff --git a/cpukit/libcsupport/src/sup_fs_node_type.c b/cpukit/libcsupport/src/sup_fs_node_type.c new file mode 100644 index 0000000000..f78451dee1 --- /dev/null +++ b/cpukit/libcsupport/src/sup_fs_node_type.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> + +rtems_filesystem_node_types_t rtems_filesystem_node_type( + const rtems_filesystem_location_info_t *loc +) +{ + rtems_filesystem_node_types_t type; + + rtems_filesystem_instance_lock(loc); + type = (*loc->ops->node_type_h)(loc); + rtems_filesystem_instance_unlock(loc); + + return type; +} diff --git a/cpukit/libcsupport/src/symlink.c b/cpukit/libcsupport/src/symlink.c index be29980911..3a3eabc9e9 100644 --- a/cpukit/libcsupport/src/symlink.c +++ b/cpukit/libcsupport/src/symlink.c @@ -12,31 +12,31 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif +#include <unistd.h> + #include <rtems/libio_.h> -#include <rtems/seterr.h> -int symlink( - const char *actualpath, - const char *sympath -) +int symlink( const char *path1, const char *path2 ) { - rtems_filesystem_location_info_t loc; - int i; - const char *name_start; - int result; - - rtems_filesystem_get_start_loc( sympath, &i, &loc ); - - result = (*loc.ops->evalformake_h)( &sympath[i], &loc, &name_start ); - if ( result != 0 ) - return -1; - - result = (*loc.ops->symlink_h)( &loc, actualpath, name_start); - - rtems_filesystem_freenode( &loc ); - - return result; + int rv = 0; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_LIBIO_FOLLOW_HARD_LINK + | RTEMS_LIBIO_MAKE + | RTEMS_LIBIO_EXCLUSIVE; + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start( &ctx, path2, eval_flags ); + + rv = (*currentloc->ops->symlink_h)( + currentloc, + rtems_filesystem_eval_path_get_token( &ctx ), + rtems_filesystem_eval_path_get_tokenlen( &ctx ), + path1 + ); + + rtems_filesystem_eval_path_cleanup( &ctx ); + + return rv; } diff --git a/cpukit/libcsupport/src/umask.c b/cpukit/libcsupport/src/umask.c index 32bf79e2b9..1c34acf10b 100644 --- a/cpukit/libcsupport/src/umask.c +++ b/cpukit/libcsupport/src/umask.c @@ -12,22 +12,27 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <sys/types.h> +#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ + #include <sys/stat.h> #include <rtems/libio_.h> -mode_t umask( - mode_t cmask -) +mode_t umask( mode_t cmask ) { mode_t old_mask; - old_mask = rtems_filesystem_umask; - rtems_filesystem_umask = cmask; + /* + * We must use the same protection mechanism as in + * rtems_libio_set_private_env(). + */ + _Thread_Disable_dispatch(); + old_mask = rtems_filesystem_umask; + rtems_filesystem_umask = cmask & (S_IRWXU | S_IRWXG | S_IRWXO); + _Thread_Enable_dispatch(); return old_mask; } diff --git a/cpukit/libcsupport/src/unlink.c b/cpukit/libcsupport/src/unlink.c index bb28959b6d..f8f91705ca 100644 --- a/cpukit/libcsupport/src/unlink.c +++ b/cpukit/libcsupport/src/unlink.c @@ -12,75 +12,39 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> +#include <unistd.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -int unlink( - const char *path -) +int unlink( const char *path ) { - int parentpathlen; - const char *name; - rtems_filesystem_location_info_t parentloc; - rtems_filesystem_location_info_t loc; - int i; - int result; - bool free_parentloc = false; - - /* - * Get the node to be unlinked. Find the parent path first. - */ - - parentpathlen = rtems_filesystem_dirname ( path ); - - if ( parentpathlen == 0 ) - rtems_filesystem_get_start_loc( path, &i, &parentloc ); - else { - result = rtems_filesystem_evaluate_path( path, parentpathlen, - RTEMS_LIBIO_PERMS_WRITE, - &parentloc, - false ); - if ( result != 0 ) - return -1; - - free_parentloc = true; - } - - /* - * Start from the parent to find the node that should be under it. - */ - - loc = parentloc; - name = path + parentpathlen; - name += rtems_filesystem_prefix_separators( name, strlen( name ) ); - - result = rtems_filesystem_evaluate_relative_path( name , strlen( name ), - 0, &loc, false ); - if ( result != 0 ) { - if ( free_parentloc ) - rtems_filesystem_freenode( &parentloc ); - return -1; - } - - if ( (*loc.ops->node_type_h)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY ) { - rtems_filesystem_freenode( &loc ); - if ( free_parentloc ) - rtems_filesystem_freenode( &parentloc ); - rtems_set_errno_and_return_minus_one( EISDIR ); - } - - result = (*loc.ops->unlink_h)( &parentloc, &loc ); - - rtems_filesystem_freenode( &loc ); - if ( free_parentloc ) - rtems_filesystem_freenode( &parentloc ); - - return result; + int rv = 0; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_LIBIO_REJECT_TERMINAL_DOT; + rtems_filesystem_location_info_t parentloc; + int parent_eval_flags = RTEMS_LIBIO_PERMS_WRITE + | RTEMS_LIBIO_PERMS_SEARCH + | RTEMS_LIBIO_FOLLOW_LINK; + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start_with_parent( + &ctx, + path, + eval_flags, + &parentloc, + parent_eval_flags + ); + + rv = (*currentloc->ops->rmnod_h)( + &parentloc, + currentloc + ); + + rtems_filesystem_eval_path_cleanup_with_parent( &ctx, &parentloc ); + + return rv; } /* diff --git a/cpukit/libcsupport/src/unmount.c b/cpukit/libcsupport/src/unmount.c index a2c67f7098..5f65e588d0 100644 --- a/cpukit/libcsupport/src/unmount.c +++ b/cpukit/libcsupport/src/unmount.c @@ -17,146 +17,37 @@ */ #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 <string.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -#include <rtems/chain.h> -static bool is_fs_below_mount_point( - const rtems_filesystem_mount_table_entry_t *mt_entry, - void *arg -) +int unmount( const char *path ) { - return arg == mt_entry->mt_point_node.mt_entry; -} - -/* - * unmount - * - * This routine will attempt to unmount the file system that has been - * is mounted a path. If the operation is successful, 0 will - * be returned to the calling routine. Otherwise, 1 will be returned. - */ - -int unmount( - const char *path -) -{ - rtems_filesystem_location_info_t loc; - rtems_filesystem_location_info_t *fs_root_loc; - rtems_filesystem_location_info_t *fs_mount_loc; - rtems_filesystem_mount_table_entry_t *mt_entry; - - /* - * Get - * The root node of the mounted filesytem. - * The node for the directory that the fileystem is mounted on. - * The mount entry that is being refered to. - */ - - if ( rtems_filesystem_evaluate_path( path, strlen( path ), 0x0, &loc, true ) ) - return -1; - - mt_entry = loc.mt_entry; - fs_mount_loc = &mt_entry->mt_point_node; - fs_root_loc = &mt_entry->mt_fs_root; - - /* - * Verify this is the root node for the file system to be unmounted. - */ - - if ( fs_root_loc->node_access != loc.node_access ){ - rtems_filesystem_freenode( &loc ); - rtems_set_errno_and_return_minus_one( EACCES ); - } - - /* - * Free the loc node and just use the nodes from the mt_entry . - */ - - rtems_filesystem_freenode( &loc ); - - /* - * Verify the current node is not in this filesystem. - * XXX - Joel I have a question here wasn't code added - * that made the current node thread based instead - * of system based? I thought it was but it doesn't - * look like it in this version. - */ - - if ( rtems_filesystem_current.mt_entry == mt_entry ) - rtems_set_errno_and_return_minus_one( EBUSY ); - - /* - * Verify there are no file systems below the path specified - */ - - if ( rtems_filesystem_mount_iterate( is_fs_below_mount_point, - fs_root_loc->mt_entry ) ) - rtems_set_errno_and_return_minus_one( EBUSY ); - - /* - * Run the file descriptor table to determine if there are any file - * descriptors that are currently active and reference nodes in the - * file system that we are trying to unmount - */ - - if ( rtems_libio_is_open_files_in_fs( mt_entry ) == 1 ) - rtems_set_errno_and_return_minus_one( EBUSY ); - - /* - * Allow the file system being unmounted on to do its cleanup. - * If it fails it will set the errno to the approprate value - * and the fileystem will not be modified. - */ - - if (( fs_mount_loc->ops->unmount_h )( mt_entry ) != 0 ) - return -1; - - /* - * Allow the mounted filesystem to unmark the use of the root node. - * - * Run the unmount function for the subordinate file system. - * - * If we fail to unmount the filesystem remount it on the base filesystems - * directory node. - * - * NOTE: Fatal error is called in a case which should never happen - * This was response was questionable but the best we could - * come up with. - */ - - if ((fs_root_loc->ops->fsunmount_me_h )( mt_entry ) != 0){ - if (( fs_mount_loc->ops->mount_h )( mt_entry ) != 0 ) - rtems_fatal_error_occurred( 0 ); - return -1; + int rv = 0; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_LIBIO_FOLLOW_LINK; + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); + rtems_filesystem_mount_table_entry_t *mt_entry = currentloc->mt_entry; + + if ( rtems_filesystem_location_is_root( currentloc ) ) { + rv = (*mt_entry->mt_point_node->location.ops->unmount_h)( mt_entry ); + if ( rv == 0 ) { + rtems_filesystem_mt_entry_declare_lock_context( lock_context ); + + rtems_filesystem_mt_entry_lock( lock_context ); + mt_entry->mounted = false; + rtems_filesystem_mt_entry_unlock( lock_context ); + } + } else { + errno = EACCES; + rv = -1; } - /* - * Extract the mount table entry from the chain - */ - - rtems_libio_lock(); - rtems_chain_extract( &mt_entry->Node ); - rtems_libio_unlock(); - - /* - * Free the memory node that was allocated in mount - * Free the memory associated with the extracted mount table entry. - */ - - rtems_filesystem_freenode( fs_mount_loc ); - free( mt_entry ); + rtems_filesystem_eval_path_cleanup( &ctx ); - return 0; + return rv; } diff --git a/cpukit/libcsupport/src/utime.c b/cpukit/libcsupport/src/utime.c index 25bcb0761b..49158700c0 100644 --- a/cpukit/libcsupport/src/utime.c +++ b/cpukit/libcsupport/src/utime.c @@ -12,36 +12,41 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif +/* FIXME: This include is a workaround for a broken <utime.h> in Newlib */ #include <sys/types.h> + #include <utime.h> -#include <errno.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -int utime( - const char *path, - const struct utimbuf *times -) +int utime( const char *path, const struct utimbuf *times ) { - rtems_filesystem_location_info_t temp_loc; - int result; - struct utimbuf now; - - if ( rtems_filesystem_evaluate_path( path, strlen( path ), 0x00, &temp_loc, true ) ) - return -1; + int rv = 0; + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_LIBIO_FOLLOW_LINK; + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); + struct utimbuf now_times; if ( times == NULL ) { - now.actime = now.modtime = time( NULL ); - times = &now; + time_t now = time( NULL ); + + now_times.actime = now; + now_times.modtime = now; + + times = &now_times; } - result = (*temp_loc.ops->utime_h)( &temp_loc, times->actime, times->modtime ); + rv = (*currentloc->ops->utime_h)( + currentloc, + times->actime, + times->modtime + ); - rtems_filesystem_freenode( &temp_loc ); + rtems_filesystem_eval_path_cleanup( &ctx ); - return result; + return rv; } diff --git a/cpukit/libfs/Makefile.am b/cpukit/libfs/Makefile.am index 20a974c33e..ad103482ef 100644 --- a/cpukit/libfs/Makefile.am +++ b/cpukit/libfs/Makefile.am @@ -11,22 +11,27 @@ EXTRA_DIST = README noinst_LIBRARIES = libdefaultfs.a libdefaultfs_a_SOURCES = \ + src/defaults/default_clone.c \ + src/defaults/default_are_nodes_equal.c \ + src/defaults/default_lock_and_unlock.c \ + src/defaults/default_eval_path.c \ src/defaults/default_fchmod.c src/defaults/default_freenode.c \ src/defaults/default_fsync.c src/defaults/default_link.c \ src/defaults/default_read.c src/defaults/default_rmnod.c \ - src/defaults/default_unlink.c src/defaults/default_chown.c \ + src/defaults/default_chown.c \ src/defaults/default_fcntl.c src/defaults/default_fsmount.c \ src/defaults/default_ftruncate.c src/defaults/default_lseek.c \ src/defaults/default_readlink.c src/defaults/default_statvfs.c \ - src/defaults/default_utime.c src/defaults/default_evalpath.c \ + src/defaults/default_utime.c \ src/defaults/default_fdatasync.c src/defaults/default_fstat.c \ src/defaults/default_ioctl.c src/defaults/default_mount.c \ src/defaults/default_rename.c src/defaults/default_symlink.c \ src/defaults/default_write.c \ - src/defaults/default_unmount.c src/defaults/default_evaluate_link.c \ + src/defaults/default_unmount.c \ src/defaults/default_open.c src/defaults/default_close.c \ src/defaults/default_fsunmount.c src/defaults/default_mknod.c \ - src/defaults/default_node_type.c src/defaults/default_evalformake.c \ + src/defaults/default_node_type.c \ + src/defaults/default_ftruncate_directory.c \ src/defaults/default_handlers.c src/defaults/default_ops.c noinst_LIBRARIES += libimfs.a @@ -37,14 +42,14 @@ libimfs_a_SOURCES += src/imfs/deviceerrno.c src/imfs/deviceio.c \ src/imfs/imfs_creat.c src/imfs/imfs_debug.c src/imfs/imfs_directory.c \ src/imfs/imfs_eval.c src/imfs/imfs_fchmod.c \ src/imfs/imfs_fdatasync.c src/imfs/imfs_fifo.c \ - src/imfs/imfs_fsunmount.c src/imfs/imfs_getchild.c \ - src/imfs/imfs_gtkn.c src/imfs/imfs_handlers_device.c \ + src/imfs/imfs_fsunmount.c \ + src/imfs/imfs_handlers_device.c \ src/imfs/imfs_handlers_directory.c src/imfs/imfs_handlers_link.c \ src/imfs/imfs_handlers_memfile.c src/imfs/imfs_init.c \ src/imfs/imfs_initsupp.c src/imfs/imfs_link.c src/imfs/imfs_load_tar.c \ src/imfs/imfs_mknod.c src/imfs/imfs_mount.c src/imfs/imfs_ntype.c \ src/imfs/imfs_readlink.c src/imfs/imfs_rename.c src/imfs/imfs_rmnod.c \ - src/imfs/imfs_stat.c src/imfs/imfs_symlink.c src/imfs/imfs_unlink.c \ + src/imfs/imfs_stat.c src/imfs/imfs_symlink.c \ src/imfs/imfs_unmount.c src/imfs/imfs_utime.c src/imfs/ioman.c \ src/imfs/memfile.c src/imfs/miniimfs_init.c src/imfs/imfs.h @@ -74,6 +79,7 @@ libdosfs_a_SOURCES += src/dosfs/msdos_create.c src/dosfs/msdos_dir.c \ src/dosfs/msdos_handlers_file.c src/dosfs/msdos_init.c \ src/dosfs/msdos_initsupp.c src/dosfs/msdos_misc.c \ src/dosfs/msdos_mknod.c src/dosfs/msdos_node_type.c \ + src/dosfs/msdos_rmnod.c \ src/dosfs/msdos_conv.c src/dosfs/msdos.h src/dosfs/msdos_format.c \ src/dosfs/dosfs.h src/dosfs/msdos_rename.c endif diff --git a/cpukit/libfs/src/defaults/default_are_nodes_equal.c b/cpukit/libfs/src/defaults/default_are_nodes_equal.c new file mode 100644 index 0000000000..c1e7777c40 --- /dev/null +++ b/cpukit/libfs/src/defaults/default_are_nodes_equal.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> + +bool rtems_filesystem_default_are_nodes_equal( + const rtems_filesystem_location_info_t *a, + const rtems_filesystem_location_info_t *b +) +{ + return a->node_access == b->node_access; +} diff --git a/cpukit/libfs/src/defaults/default_chown.c b/cpukit/libfs/src/defaults/default_chown.c index 82cb0b694f..55c7da9d15 100644 --- a/cpukit/libfs/src/defaults/default_chown.c +++ b/cpukit/libfs/src/defaults/default_chown.c @@ -9,14 +9,17 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> #include <rtems/seterr.h> int rtems_filesystem_default_chown( - rtems_filesystem_location_info_t *pathloc, /* IN */ - uid_t owner, /* IN */ - gid_t group /* IN */ + const rtems_filesystem_location_info_t *loc, + uid_t owner, + gid_t group ) { rtems_set_errno_and_return_minus_one( ENOTSUP ); diff --git a/cpukit/libfs/src/defaults/default_clone.c b/cpukit/libfs/src/defaults/default_clone.c new file mode 100644 index 0000000000..5224b01d19 --- /dev/null +++ b/cpukit/libfs/src/defaults/default_clone.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> + +int rtems_filesystem_default_clonenode( + rtems_filesystem_location_info_t *loc +) +{ + return 0; +} diff --git a/cpukit/libfs/src/defaults/default_eval_path.c b/cpukit/libfs/src/defaults/default_eval_path.c new file mode 100644 index 0000000000..e639f9985c --- /dev/null +++ b/cpukit/libfs/src/defaults/default_eval_path.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> + +void rtems_filesystem_default_eval_path( + rtems_filesystem_eval_path_context_t *ctx +) +{ + ctx->pathlen = 0; + rtems_filesystem_location_detach(&ctx->currentloc); +} diff --git a/cpukit/libfs/src/defaults/default_evalformake.c b/cpukit/libfs/src/defaults/default_evalformake.c deleted file mode 100644 index 891d961dc1..0000000000 --- a/cpukit/libfs/src/defaults/default_evalformake.c +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @file - * - * @ingroup LibIO - * - * @brief rtems_filesystem_default_evalformake() implementation. - */ - -/* - * Copyright (c) 2010 - * embedded brains GmbH - * Obere Lagerstr. 30 - * D-82178 Puchheim - * Germany - * <rtems@embedded-brains.de> - * - * 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. - */ - -#include <rtems/libio.h> -#include <rtems/seterr.h> - -int rtems_filesystem_default_evalformake( - const char *path, - rtems_filesystem_location_info_t *pathloc, - const char **name -) -{ - rtems_set_errno_and_return_minus_one( ENOTSUP ); -} diff --git a/cpukit/libfs/src/defaults/default_evalpath.c b/cpukit/libfs/src/defaults/default_evalpath.c deleted file mode 100644 index 1e3f762cbe..0000000000 --- a/cpukit/libfs/src/defaults/default_evalpath.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * COPYRIGHT (c) 2010. - * On-Line Applications Research Corporation (OAR). - * - * 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$ - */ - -#include <rtems/libio.h> -#include <rtems/libio_.h> -#include <rtems/seterr.h> - -int rtems_filesystem_default_evalpath( - const char *pathname, /* IN */ - size_t pathnamelen, /* IN */ - int flags, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN/OUT */ -) -{ - rtems_set_errno_and_return_minus_one( ENOTSUP ); -} - diff --git a/cpukit/libfs/src/defaults/default_evaluate_link.c b/cpukit/libfs/src/defaults/default_evaluate_link.c deleted file mode 100644 index a82c73729f..0000000000 --- a/cpukit/libfs/src/defaults/default_evaluate_link.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * COPYRIGHT (c) 2010. - * On-Line Applications Research Corporation (OAR). - * - * 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$ - */ - -#include <rtems/libio.h> -#include <rtems/libio_.h> -#include <rtems/seterr.h> - -int rtems_filesystem_default_evaluate_link( - rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ - int flags /* IN */ -) -{ - rtems_set_errno_and_return_minus_one( ENOTSUP ); -} - diff --git a/cpukit/libfs/src/defaults/default_fchmod.c b/cpukit/libfs/src/defaults/default_fchmod.c index cda32c82d5..652e24322f 100644 --- a/cpukit/libfs/src/defaults/default_fchmod.c +++ b/cpukit/libfs/src/defaults/default_fchmod.c @@ -9,13 +9,16 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> #include <rtems/seterr.h> int rtems_filesystem_default_fchmod( - rtems_filesystem_location_info_t *loc, - mode_t mode + const rtems_filesystem_location_info_t *loc, + mode_t mode ) { rtems_set_errno_and_return_minus_one( ENOTSUP ); diff --git a/cpukit/libfs/src/defaults/default_fcntl.c b/cpukit/libfs/src/defaults/default_fcntl.c index d9d8602e40..0374a4f4fa 100644 --- a/cpukit/libfs/src/defaults/default_fcntl.c +++ b/cpukit/libfs/src/defaults/default_fcntl.c @@ -14,8 +14,8 @@ #include <rtems/seterr.h> int rtems_filesystem_default_fcntl( - int cmd, - rtems_libio_t *iop + rtems_libio_t *iop, + int cmd ) { return 0; diff --git a/cpukit/libfs/src/defaults/default_freenode.c b/cpukit/libfs/src/defaults/default_freenode.c index bb231d13f7..2a5f8f1338 100644 --- a/cpukit/libfs/src/defaults/default_freenode.c +++ b/cpukit/libfs/src/defaults/default_freenode.c @@ -9,14 +9,15 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> -#include <rtems/seterr.h> -int rtems_filesystem_default_freenode( - rtems_filesystem_location_info_t *pathloc /* IN */ +void rtems_filesystem_default_freenode( + const rtems_filesystem_location_info_t *loc ) { - return 0; + /* Do nothing */ } - diff --git a/cpukit/libfs/src/defaults/default_fstat.c b/cpukit/libfs/src/defaults/default_fstat.c index 6c8d501a21..564d4e6201 100644 --- a/cpukit/libfs/src/defaults/default_fstat.c +++ b/cpukit/libfs/src/defaults/default_fstat.c @@ -9,14 +9,18 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> -#include <rtems/seterr.h> int rtems_filesystem_default_fstat( - rtems_filesystem_location_info_t *loc, - struct stat *buf + const rtems_filesystem_location_info_t *loc, + struct stat *buf ) { - rtems_set_errno_and_return_minus_one( ENOTSUP ); + buf->st_mode = S_IRWXU | S_IRWXG | S_IRWXO; + + return 0; } diff --git a/cpukit/libfs/src/defaults/default_fsunmount.c b/cpukit/libfs/src/defaults/default_fsunmount.c index e879f5c2f8..ba4a0a1fa4 100644 --- a/cpukit/libfs/src/defaults/default_fsunmount.c +++ b/cpukit/libfs/src/defaults/default_fsunmount.c @@ -13,9 +13,8 @@ #include <rtems/libio_.h> #include <rtems/seterr.h> -int rtems_filesystem_default_fsunmount( +void rtems_filesystem_default_fsunmount( rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ ) { - return 0; } diff --git a/cpukit/libfs/src/defaults/default_ftruncate.c b/cpukit/libfs/src/defaults/default_ftruncate.c index b1e958f36c..ad8777487d 100644 --- a/cpukit/libfs/src/defaults/default_ftruncate.c +++ b/cpukit/libfs/src/defaults/default_ftruncate.c @@ -9,7 +9,10 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> #include <rtems/seterr.h> diff --git a/cpukit/libfs/src/defaults/default_ftruncate_directory.c b/cpukit/libfs/src/defaults/default_ftruncate_directory.c new file mode 100644 index 0000000000..e438154d77 --- /dev/null +++ b/cpukit/libfs/src/defaults/default_ftruncate_directory.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> +#include <rtems/seterr.h> + +int rtems_filesystem_default_ftruncate_directory( + rtems_libio_t *iop, + off_t length +) +{ + rtems_set_errno_and_return_minus_one( EISDIR ); +} diff --git a/cpukit/libfs/src/defaults/default_handlers.c b/cpukit/libfs/src/defaults/default_handlers.c index ce6288bbd9..286c2b4157 100644 --- a/cpukit/libfs/src/defaults/default_handlers.c +++ b/cpukit/libfs/src/defaults/default_handlers.c @@ -29,10 +29,8 @@ const rtems_filesystem_file_handlers_r rtems_filesystem_handlers_default = { .ioctl_h = rtems_filesystem_default_ioctl, .lseek_h = rtems_filesystem_default_lseek, .fstat_h = rtems_filesystem_default_fstat, - .fchmod_h = rtems_filesystem_default_fchmod, .ftruncate_h = rtems_filesystem_default_ftruncate, .fsync_h = rtems_filesystem_default_fsync, .fdatasync_h = rtems_filesystem_default_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, - .rmnod_h = rtems_filesystem_default_rmnod + .fcntl_h = rtems_filesystem_default_fcntl }; diff --git a/cpukit/libfs/src/defaults/default_link.c b/cpukit/libfs/src/defaults/default_link.c index d9bc913b27..40b70a89f8 100644 --- a/cpukit/libfs/src/defaults/default_link.c +++ b/cpukit/libfs/src/defaults/default_link.c @@ -9,16 +9,19 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> #include <rtems/seterr.h> int rtems_filesystem_default_link( - rtems_filesystem_location_info_t *to_loc, /* IN */ - rtems_filesystem_location_info_t *parent_loc, /* IN */ - const char *name /* IN */ + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *targetloc, + const char *name, + size_t namelen ) { rtems_set_errno_and_return_minus_one( ENOTSUP ); } - diff --git a/cpukit/libfs/src/defaults/default_lock_and_unlock.c b/cpukit/libfs/src/defaults/default_lock_and_unlock.c new file mode 100644 index 0000000000..de29a076f1 --- /dev/null +++ b/cpukit/libfs/src/defaults/default_lock_and_unlock.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> + +void rtems_filesystem_default_lock( + rtems_filesystem_mount_table_entry_t *mt_entry +) +{ + rtems_libio_lock(); +} + +void rtems_filesystem_default_unlock( + rtems_filesystem_mount_table_entry_t *mt_entry +) +{ + rtems_libio_unlock(); +} diff --git a/cpukit/libfs/src/defaults/default_mknod.c b/cpukit/libfs/src/defaults/default_mknod.c index fcd03be4c2..17a208a772 100644 --- a/cpukit/libfs/src/defaults/default_mknod.c +++ b/cpukit/libfs/src/defaults/default_mknod.c @@ -9,15 +9,19 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> #include <rtems/seterr.h> int rtems_filesystem_default_mknod( - const char *path, /* IN */ - mode_t mode, /* IN */ - dev_t dev, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN/OUT */ + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev ) { rtems_set_errno_and_return_minus_one( ENOTSUP ); diff --git a/cpukit/libfs/src/defaults/default_node_type.c b/cpukit/libfs/src/defaults/default_node_type.c index a118a04f72..6627fbf5dd 100644 --- a/cpukit/libfs/src/defaults/default_node_type.c +++ b/cpukit/libfs/src/defaults/default_node_type.c @@ -22,7 +22,7 @@ #include <rtems/libio.h> rtems_filesystem_node_types_t rtems_filesystem_default_node_type( - rtems_filesystem_location_info_t *pathloc + const rtems_filesystem_location_info_t *loc ) { return RTEMS_FILESYSTEM_INVALID_NODE_TYPE; diff --git a/cpukit/libfs/src/defaults/default_open.c b/cpukit/libfs/src/defaults/default_open.c index b119fbf5be..aa856bfb8f 100644 --- a/cpukit/libfs/src/defaults/default_open.c +++ b/cpukit/libfs/src/defaults/default_open.c @@ -9,16 +9,18 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> -#include <rtems/seterr.h> int rtems_filesystem_default_open( rtems_libio_t *iop, - const char *pathname, - uint32_t flag, - uint32_t mode + const char *path, + int oflag, + mode_t mode ) { - rtems_set_errno_and_return_minus_one( ENOTSUP ); + return 0; } diff --git a/cpukit/libfs/src/defaults/default_ops.c b/cpukit/libfs/src/defaults/default_ops.c index 575cf6b2d4..dfd1ba2009 100644 --- a/cpukit/libfs/src/defaults/default_ops.c +++ b/cpukit/libfs/src/defaults/default_ops.c @@ -22,20 +22,23 @@ #include <rtems/libio.h> const rtems_filesystem_operations_table rtems_filesystem_operations_default = { - .evalpath_h = rtems_filesystem_default_evalpath, - .evalformake_h = rtems_filesystem_default_evalformake, + .lock_h = rtems_filesystem_default_lock, + .unlock_h = rtems_filesystem_default_unlock, + .eval_path_h = rtems_filesystem_default_eval_path, .link_h = rtems_filesystem_default_link, - .unlink_h = rtems_filesystem_default_unlink, + .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal, .node_type_h = rtems_filesystem_default_node_type, .mknod_h = rtems_filesystem_default_mknod, + .rmnod_h = rtems_filesystem_default_rmnod, + .fchmod_h = rtems_filesystem_default_fchmod, .chown_h = rtems_filesystem_default_chown, + .clonenod_h = rtems_filesystem_default_clonenode, .freenod_h = rtems_filesystem_default_freenode, .mount_h = rtems_filesystem_default_mount, .fsmount_me_h = rtems_filesystem_default_fsmount, .unmount_h = rtems_filesystem_default_unmount, .fsunmount_me_h = rtems_filesystem_default_fsunmount, .utime_h = rtems_filesystem_default_utime, - .eval_link_h = rtems_filesystem_default_evaluate_link, .symlink_h = rtems_filesystem_default_symlink, .readlink_h = rtems_filesystem_default_readlink, .rename_h = rtems_filesystem_default_rename, diff --git a/cpukit/libfs/src/defaults/default_readlink.c b/cpukit/libfs/src/defaults/default_readlink.c index 1d07970999..028eb3f75a 100644 --- a/cpukit/libfs/src/defaults/default_readlink.c +++ b/cpukit/libfs/src/defaults/default_readlink.c @@ -9,14 +9,17 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> #include <rtems/seterr.h> ssize_t rtems_filesystem_default_readlink( - rtems_filesystem_location_info_t *loc, /* IN */ - char *buf, /* OUT */ - size_t bufsize + const rtems_filesystem_location_info_t *loc, + char *buf, + size_t bufsize ) { rtems_set_errno_and_return_minus_one( ENOTSUP ); diff --git a/cpukit/libfs/src/defaults/default_rename.c b/cpukit/libfs/src/defaults/default_rename.c index 93bf15f2e0..748d74b3ec 100644 --- a/cpukit/libfs/src/defaults/default_rename.c +++ b/cpukit/libfs/src/defaults/default_rename.c @@ -9,15 +9,19 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> #include <rtems/seterr.h> int rtems_filesystem_default_rename( - rtems_filesystem_location_info_t *old_parent_loc, /* IN */ - rtems_filesystem_location_info_t *old_loc, /* IN */ - rtems_filesystem_location_info_t *new_parent_loc, /* IN */ - const char *name /* IN */ + const rtems_filesystem_location_info_t *oldparentloc, + const rtems_filesystem_location_info_t *oldloc, + const rtems_filesystem_location_info_t *newparentloc, + const char *name, + size_t namelen ) { rtems_set_errno_and_return_minus_one( ENOTSUP ); diff --git a/cpukit/libfs/src/defaults/default_rmnod.c b/cpukit/libfs/src/defaults/default_rmnod.c index 776ee4b659..8c1014bb98 100644 --- a/cpukit/libfs/src/defaults/default_rmnod.c +++ b/cpukit/libfs/src/defaults/default_rmnod.c @@ -9,13 +9,16 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> #include <rtems/seterr.h> int rtems_filesystem_default_rmnod( - rtems_filesystem_location_info_t *parent_loc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */ + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *loc ) { rtems_set_errno_and_return_minus_one( ENOTSUP ); diff --git a/cpukit/libfs/src/defaults/default_statvfs.c b/cpukit/libfs/src/defaults/default_statvfs.c index 22d891815f..f26ecc6a7c 100644 --- a/cpukit/libfs/src/defaults/default_statvfs.c +++ b/cpukit/libfs/src/defaults/default_statvfs.c @@ -9,13 +9,16 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> #include <rtems/seterr.h> int rtems_filesystem_default_statvfs( - rtems_filesystem_location_info_t *loc, /* IN */ - struct statvfs *buf /* OUT */ + const rtems_filesystem_location_info_t *loc, + struct statvfs *buf ) { rtems_set_errno_and_return_minus_one( ENOTSUP ); diff --git a/cpukit/libfs/src/defaults/default_symlink.c b/cpukit/libfs/src/defaults/default_symlink.c index 8985d76aef..95ae455379 100644 --- a/cpukit/libfs/src/defaults/default_symlink.c +++ b/cpukit/libfs/src/defaults/default_symlink.c @@ -9,14 +9,18 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> #include <rtems/seterr.h> int rtems_filesystem_default_symlink( - rtems_filesystem_location_info_t *loc, /* IN */ - const char *link_name, /* IN */ - const char *node_name + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + const char *target ) { rtems_set_errno_and_return_minus_one( ENOTSUP ); diff --git a/cpukit/libfs/src/defaults/default_unlink.c b/cpukit/libfs/src/defaults/default_unlink.c deleted file mode 100644 index cf633c6ce1..0000000000 --- a/cpukit/libfs/src/defaults/default_unlink.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * COPYRIGHT (c) 2010. - * On-Line Applications Research Corporation (OAR). - * - * 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$ - */ - -#include <rtems/libio.h> -#include <rtems/libio_.h> -#include <rtems/seterr.h> - -int rtems_filesystem_default_unlink( - rtems_filesystem_location_info_t *parent_pathloc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */ -) -{ - rtems_set_errno_and_return_minus_one( ENOTSUP ); -} diff --git a/cpukit/libfs/src/defaults/default_utime.c b/cpukit/libfs/src/defaults/default_utime.c index 77a2f2e8d6..b1f57c7f5b 100644 --- a/cpukit/libfs/src/defaults/default_utime.c +++ b/cpukit/libfs/src/defaults/default_utime.c @@ -9,16 +9,18 @@ * $Id$ */ -#include <rtems/libio.h> +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <rtems/libio_.h> #include <rtems/seterr.h> int rtems_filesystem_default_utime( - rtems_filesystem_location_info_t *pathloc, /* IN */ - time_t actime, /* IN */ - time_t modtime /* IN */ + const rtems_filesystem_location_info_t *loc, + time_t actime, + time_t modtime ) { rtems_set_errno_and_return_minus_one( ENOTSUP ); } - diff --git a/cpukit/libfs/src/devfs/devclose.c b/cpukit/libfs/src/devfs/devclose.c index 773cade5c6..f69ac291fe 100644 --- a/cpukit/libfs/src/devfs/devclose.c +++ b/cpukit/libfs/src/devfs/devclose.c @@ -21,9 +21,7 @@ int devFS_close( { rtems_libio_open_close_args_t args; rtems_status_code status; - rtems_device_name_t *np; - - np = (rtems_device_name_t *)iop->pathinfo.node_access; + const devFS_node *np = iop->pathinfo.node_access; args.iop = iop; args.flags = 0; diff --git a/cpukit/libfs/src/devfs/devfs.h b/cpukit/libfs/src/devfs/devfs.h index 6e4f2478c7..758edf932b 100644 --- a/cpukit/libfs/src/devfs/devfs.h +++ b/cpukit/libfs/src/devfs/devfs.h @@ -17,38 +17,54 @@ extern "C" { /** * This structure define the type of device table */ - -typedef struct -{ - /** This member points to device name which is a null-terminated string */ - const char *device_name; +typedef struct { + /** This member points to device name which is not a null-terminated string */ + const char *name; /** This member is the name length of a device */ - uint32_t device_name_length; + size_t namelen; /** major number of a device */ rtems_device_major_number major; /** minor number of a device */ rtems_device_minor_number minor; /** device creation mode, only device file can be created */ mode_t mode; +} devFS_node; -} rtems_device_name_t; +typedef struct { + devFS_node *nodes; + size_t count; +} devFS_data; +/** + * The following defines the device-only filesystem operating + * operations. + */ +extern const rtems_filesystem_operations_table devFS_ops; /** - * This routine associates RTEMS status code with errno + * The following defines the device-only filesystem operating + * handlers. */ -extern int rtems_deviceio_errno(rtems_status_code code); - +extern const rtems_filesystem_file_handlers_r devFS_file_handlers; /** - * The following defines the device table size. This values - * is configured during application configuration time by - * the user. The default value is set to 4. + * This routine associates RTEMS status code with errno */ -extern uint32_t rtems_device_table_size; +extern int rtems_deviceio_errno(rtems_status_code code); + +static inline const devFS_data *devFS_get_data( + const rtems_filesystem_location_info_t *loc +) +{ + return loc->mt_entry->immutable_fs_info; +} + +extern void devFS_eval_path( + rtems_filesystem_eval_path_context_t *ctx +); /** * This handler maps open operation to rtems_io_open. @@ -62,8 +78,8 @@ extern uint32_t rtems_device_table_size; extern int devFS_open( rtems_libio_t *iop, const char *pathname, - uint32_t flag, - uint32_t mode + int oflag, + mode_t mode ); @@ -142,8 +158,8 @@ extern int devFS_ioctl( */ extern int devFS_stat( - rtems_filesystem_location_info_t *loc, - struct stat *buf + const rtems_filesystem_location_info_t *loc, + struct stat *buf ); @@ -153,63 +169,15 @@ extern int devFS_stat( * Since this is a device-only filesystem, so there is only * one node type in the system. * - * @param pathloc contains filesytem access information, this + * @param loc contains filesytem access information, this * parameter is ignored * @retval always returns RTEMS_FILESYSTEM_DEVICE */ extern rtems_filesystem_node_types_t devFS_node_type( - rtems_filesystem_location_info_t *pathloc + const rtems_filesystem_location_info_t*loc ); - - -/** - * This routine is invoked to determine if 'pathname' exists. - * This routine first check access flags, then it searches - * the device table to get the information. - * - * @param pathname device name to be searched - * @param flags access flags - * @param pathloc contains filesystem access information - * @retval upon success(pathname exists), this routines - * returns 0; if 'flag' is invalid, it returns -1 and errno - * is set to EIO; otherwise, it returns -1 and errno is set to ENOENT - */ - -extern int devFS_evaluate_path( - const char *pathname, - size_t pathnamelen, - int flags, - rtems_filesystem_location_info_t *pathloc -); - - -/** - * This routine is given a path to evaluate and a valid start - * location. It is responsible for finding the parent node for - * a requested make command, setting pathloc information to - * identify the parent node, and setting the name pointer to - * the first character of the name of the new node. In device - * only filesystem, devices do not has a tree hierarchy, there - * are no parent-child relationship. So this routine is rather - * simple, it just set *name to path and returns - * - * @param path device path to be evaluated - * @param pathloc contains filesystem access information, this - * parameter is ignored - * @param name - * @retval always returns 0 - */ - -extern int devFS_evaluate_for_make( - const char *path, - rtems_filesystem_location_info_t *pathloc, - const char **name -); - - - /** * This routine is invoked upon registration of a new device * file. It is responsible for creating a item in the main @@ -217,21 +185,15 @@ extern int devFS_evaluate_for_make( * sequential order, when found a empty slot, it fills the slot * with proper values. * - * @param path the device file name to be registered - * @param mode file mode, this parameter is ignored - * @param dev device major and minor number - * @param pathloc contains filesystem access information - * @retval upon success, this routine returns 0; if 'path' - * already exist, it returns -1 and errno is set to EEXIST; - * if device table is full, it returns -1 and errno is set - * to ENOMEM + * @see rtems_filesystem_mknod_t. */ extern int devFS_mknod( - const char *path, - mode_t mode, - dev_t dev, - rtems_filesystem_location_info_t *pathloc + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev ); @@ -266,11 +228,9 @@ extern int devFS_initialize( * * This routine is intended for debugging, and can be used by shell * program to provide user with the system information. - * - * @retval 0 */ -extern int devFS_Show(void); +extern void devFS_Show(void); #ifdef __cplusplus } diff --git a/cpukit/libfs/src/devfs/devfs_eval.c b/cpukit/libfs/src/devfs/devfs_eval.c index a3169fb3fa..b7a31ee921 100644 --- a/cpukit/libfs/src/devfs/devfs_eval.c +++ b/cpukit/libfs/src/devfs/devfs_eval.c @@ -7,79 +7,84 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <rtems/seterr.h> -#include <fcntl.h> -#include <assert.h> -#include "devfs.h" - -/** - * The following defines the device-only filesystem operating - * handlers. - */ +#include <string.h> -extern rtems_filesystem_operations_table devFS_ops; - -/** - * The following defines the device-only filesystem operating - * handlers. - */ - -extern rtems_filesystem_file_handlers_r devFS_file_handlers; +#include "devfs.h" -int devFS_evaluate_path( - const char *pathname, - size_t pathnamelen, - int flags, - rtems_filesystem_location_info_t *pathloc +static devFS_node *devFS_search_node( + const devFS_data *data, + const char *path, + size_t pathlen, + devFS_node **free_node_ptr ) { - int i; - rtems_device_name_t *device_name_table; - - /* see if 'flags' is valid */ - if ( !rtems_libio_is_valid_perms( flags ) ) - rtems_set_errno_and_return_minus_one( EPERM ); - - /* get the device name table */ - device_name_table = (rtems_device_name_t *)pathloc->node_access; - if (!device_name_table) - rtems_set_errno_and_return_minus_one( EFAULT ); - - for (i = 0; i < rtems_device_table_size; i++) { - if (!device_name_table[i].device_name) - continue; - - if (strncmp(pathname, device_name_table[i].device_name, pathnamelen) != 0) - continue; - - if (device_name_table[i].device_name[pathnamelen] != '\0') - continue; - - /* find the device, set proper values */ - pathloc->node_access = (void *)&device_name_table[i]; - pathloc->handlers = &devFS_file_handlers; - pathloc->ops = &devFS_ops; - pathloc->mt_entry = rtems_filesystem_root.mt_entry; - return 0; + size_t i = 0; + size_t n = data->count; + devFS_node *nodes = data->nodes; + devFS_node *node = NULL; + devFS_node *free_node = NULL; + + for (i = 0; (free_node == NULL || node == NULL) && i < n; ++i) { + devFS_node *current = nodes + i; + + if (current->name != NULL) { + if ( + current->namelen == pathlen + && memcmp(current->name, path, pathlen) == 0 + ) { + node = current; + } + } else { + free_node = current; + } } - /* no such file or directory */ - rtems_set_errno_and_return_minus_one( ENOENT ); -} - + *free_node_ptr = free_node; + return node; +} -int devFS_evaluate_for_make( - const char *path, - rtems_filesystem_location_info_t *pathloc, - const char **name +void devFS_eval_path( + rtems_filesystem_eval_path_context_t *ctx ) { - /* we do nothing, just set name to path */ - *name = path; - return 0; + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc(ctx); + devFS_node *free_node; + devFS_node *node = devFS_search_node( + devFS_get_data(currentloc), + rtems_filesystem_eval_path_get_path(ctx), + rtems_filesystem_eval_path_get_pathlen(ctx), + &free_node + ); + int eval_flags = rtems_filesystem_eval_path_get_flags(ctx); + + if (node != NULL) { + if ((eval_flags & RTEMS_LIBIO_EXCLUSIVE) == 0) { + currentloc->node_access = node; + rtems_filesystem_eval_path_clear_path(ctx); + } else { + rtems_filesystem_eval_path_error(ctx, EEXIST); + } + } else { + if ((eval_flags & RTEMS_LIBIO_MAKE) != 0) { + if (free_node != NULL) { + free_node->mode = S_IRWXU | S_IRWXG | S_IRWXO; + currentloc->node_access = free_node; + rtems_filesystem_eval_path_set_token( + ctx, + rtems_filesystem_eval_path_get_path(ctx), + rtems_filesystem_eval_path_get_pathlen(ctx) + ); + rtems_filesystem_eval_path_clear_path(ctx); + } else { + rtems_filesystem_eval_path_error(ctx, ENOSPC); + } + } else { + rtems_filesystem_eval_path_error(ctx, ENOENT); + } + } } - diff --git a/cpukit/libfs/src/devfs/devfs_init.c b/cpukit/libfs/src/devfs/devfs_init.c index bd741e41a2..070aced2a4 100644 --- a/cpukit/libfs/src/devfs/devfs_init.c +++ b/cpukit/libfs/src/devfs/devfs_init.c @@ -7,85 +7,65 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <stdlib.h> -#include <rtems.h> -#include <rtems/seterr.h> -#include <rtems/score/wkspace.h> #include "devfs.h" -rtems_filesystem_operations_table devFS_ops = -{ - devFS_evaluate_path, - devFS_evaluate_for_make, - rtems_filesystem_default_link, - rtems_filesystem_default_unlink, - devFS_node_type, - devFS_mknod, - rtems_filesystem_default_chown, - rtems_filesystem_default_freenode, - rtems_filesystem_default_mount, - devFS_initialize, - rtems_filesystem_default_unmount, - rtems_filesystem_default_fsunmount, - rtems_filesystem_default_utime, - rtems_filesystem_default_evaluate_link, - rtems_filesystem_default_symlink, - rtems_filesystem_default_readlink, - rtems_filesystem_default_rename, - rtems_filesystem_default_statvfs +const rtems_filesystem_operations_table devFS_ops = { + .lock_h = rtems_filesystem_default_lock, + .unlock_h = rtems_filesystem_default_unlock, + .eval_path_h = devFS_eval_path, + .link_h = rtems_filesystem_default_link, + .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal, + .node_type_h = devFS_node_type, + .mknod_h = devFS_mknod, + .rmnod_h = rtems_filesystem_default_rmnod, + .fchmod_h = rtems_filesystem_default_fchmod, + .chown_h = rtems_filesystem_default_chown, + .clonenod_h = rtems_filesystem_default_clonenode, + .freenod_h = rtems_filesystem_default_freenode, + .mount_h = rtems_filesystem_default_mount, + .fsmount_me_h = devFS_initialize, + .unmount_h = rtems_filesystem_default_unmount, + .fsunmount_me_h = rtems_filesystem_default_fsunmount, + .utime_h = rtems_filesystem_default_utime, + .symlink_h = rtems_filesystem_default_symlink, + .readlink_h = rtems_filesystem_default_readlink, + .rename_h = rtems_filesystem_default_rename, + .statvfs_h = rtems_filesystem_default_statvfs }; - -rtems_filesystem_file_handlers_r devFS_file_handlers = -{ - devFS_open, - devFS_close, - devFS_read, - devFS_write, - devFS_ioctl, - rtems_filesystem_default_lseek, - devFS_stat, - rtems_filesystem_default_fchmod, - rtems_filesystem_default_ftruncate, - rtems_filesystem_default_fsync, - rtems_filesystem_default_fdatasync, - rtems_filesystem_default_fcntl, - rtems_filesystem_default_rmnod +const rtems_filesystem_file_handlers_r devFS_file_handlers = { + .open_h = devFS_open, + .close_h = devFS_close, + .read_h = devFS_read, + .write_h = devFS_write, + .ioctl_h = devFS_ioctl, + .lseek_h = rtems_filesystem_default_lseek, + .fstat_h = devFS_stat, + .ftruncate_h = rtems_filesystem_default_ftruncate, + .fsync_h = rtems_filesystem_default_fsync, + .fdatasync_h = rtems_filesystem_default_fdatasync, + .fcntl_h = rtems_filesystem_default_fcntl }; - - int devFS_initialize( - rtems_filesystem_mount_table_entry_t *temp_mt_entry, - const void *data + rtems_filesystem_mount_table_entry_t *mt_entry, + const void *data ) { - rtems_device_name_t *device_name_table; - - /* allocate device only filesystem name table */ - device_name_table = (rtems_device_name_t *)_Workspace_Allocate( - sizeof( rtems_device_name_t ) * ( rtems_device_table_size ) - ); - - /* no memory for device filesystem */ - if (!device_name_table) - rtems_set_errno_and_return_minus_one( ENOMEM ); - - memset( - device_name_table, 0, - sizeof( rtems_device_name_t ) * ( rtems_device_table_size ) - ); - - /* set file handlers */ - temp_mt_entry->mt_fs_root.handlers = &devFS_file_handlers; - temp_mt_entry->mt_fs_root.ops = &devFS_ops; + int rv = 0; - /* Set the node_access to device name table */ - temp_mt_entry->mt_fs_root.node_access = (void *)device_name_table; + if (data != NULL) { + mt_entry->immutable_fs_info = data; + mt_entry->mt_fs_root->location.handlers = &devFS_file_handlers; + mt_entry->mt_fs_root->location.ops = &devFS_ops; + } else { + errno = EINVAL; + rv = -1; + } - return 0; + return rv; } diff --git a/cpukit/libfs/src/devfs/devfs_mknod.c b/cpukit/libfs/src/devfs/devfs_mknod.c index 4a8b8b3523..9760c5e5c7 100644 --- a/cpukit/libfs/src/devfs/devfs_mknod.c +++ b/cpukit/libfs/src/devfs/devfs_mknod.c @@ -7,75 +7,52 @@ */ #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 <string.h> -#include <rtems/seterr.h> #include "devfs.h" int devFS_mknod( - const char *path, - mode_t mode, - dev_t dev, - rtems_filesystem_location_info_t *pathloc + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev ) { - int i; - int slot; - rtems_device_name_t *device_name_table; - rtems_device_major_number major; - rtems_device_minor_number minor; - ISR_Level level; - - /* - * This is a special case. In rtems_filesystem_initialize, - * a special device '/dev' will be created. We check this - * condition and do not create the '/dev' and the 'path' - * actually passed in is 'dev', not '/dev'. Just return 0 to - * indicate we are OK. - */ - - if ((path[0] == 'd') && (path[1] == 'e') && - (path[2] == 'v') && (path[3] == '\0')) - return 0; - - /* must be a character device or a block device */ - if (!S_ISBLK(mode) && !S_ISCHR(mode)) - rtems_set_errno_and_return_minus_one( EINVAL ); - else - rtems_filesystem_split_dev_t(dev, major, minor); - - /* Find an empty slot in device name table */ - device_name_table = (rtems_device_name_t *)pathloc->node_access; - if (!device_name_table) - rtems_set_errno_and_return_minus_one( EFAULT ); - - for (slot = -1, i = 0; i < rtems_device_table_size; i++){ - if (device_name_table[i].device_name == NULL) - slot = i; - else - if (strcmp(path, device_name_table[i].device_name) == 0) - rtems_set_errno_and_return_minus_one( EEXIST ); + int rv = 0; + + if (namelen != 3 || name [0] != 'd' || name [1] != 'e' || name [2] != 'v') { + if (S_ISBLK(mode) || S_ISCHR(mode)) { + char *dupname = malloc(namelen); + + if (dupname != NULL) { + devFS_node *node = parentloc->node_access; + + node->name = dupname; + node->namelen = namelen; + node->major = rtems_filesystem_dev_major_t(dev); + node->minor = rtems_filesystem_dev_minor_t(dev); + node->mode = mode; + memcpy(dupname, name, namelen); + } else { + errno = ENOMEM; + rv = -1; + } + } else { + errno = ENOTSUP; + rv = -1; + } + } else { + if (!S_ISDIR(mode)) { + errno = ENOTSUP; + rv = -1; + } } - if (slot == -1) - rtems_set_errno_and_return_minus_one( ENOMEM ); - - _ISR_Disable(level); - device_name_table[slot].device_name = path; - device_name_table[slot].device_name_length = strlen(path); - device_name_table[slot].major = major; - device_name_table[slot].minor = minor; - device_name_table[slot].mode = mode; - _ISR_Enable(level); - - return 0; + return rv; } - diff --git a/cpukit/libfs/src/devfs/devfs_node_type.c b/cpukit/libfs/src/devfs/devfs_node_type.c index 0bede52d2d..c4bd488680 100644 --- a/cpukit/libfs/src/devfs/devfs_node_type.c +++ b/cpukit/libfs/src/devfs/devfs_node_type.c @@ -13,7 +13,7 @@ #include "devfs.h" rtems_filesystem_node_types_t devFS_node_type( - rtems_filesystem_location_info_t *pathloc + const rtems_filesystem_location_info_t *loc ) { /* diff --git a/cpukit/libfs/src/devfs/devfs_show.c b/cpukit/libfs/src/devfs/devfs_show.c index e449caf49f..6d30d3f5d6 100644 --- a/cpukit/libfs/src/devfs/devfs_show.c +++ b/cpukit/libfs/src/devfs/devfs_show.c @@ -7,30 +7,38 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <rtems/seterr.h> #include "devfs.h" -int devFS_Show(void) +void devFS_Show(void) { - int i; - rtems_filesystem_location_info_t *temp_loc; - rtems_device_name_t *device_name_table; + rtems_filesystem_location_info_t *rootloc = &rtems_filesystem_root->location; - temp_loc = &rtems_filesystem_root; - device_name_table = (rtems_device_name_t *)temp_loc->node_access; - if (!device_name_table) - rtems_set_errno_and_return_minus_one( EFAULT ); + if (rootloc->ops == &devFS_ops) { + const devFS_data *data = devFS_get_data(rootloc); + size_t i = 0; + size_t n = data->count; + devFS_node *nodes = data->nodes; - for (i = 0; i < rtems_device_table_size; i++){ - if (device_name_table[i].device_name){ - printk("/%s %d %d\n", device_name_table[i].device_name, - device_name_table[i].major, device_name_table[i].minor); + for (i = 0; i < n; ++i) { + devFS_node *current = nodes + i; + + if (current->name != NULL) { + size_t j = 0; + size_t m = current->namelen; + + printk("/"); + for (j = 0; j < m; ++j) { + printk("%c", current->name [j]); + } + printk( + " %lu %lu\n", + (unsigned long) current->major, + (unsigned long) current->minor + ); + } } } - return 0; } - - diff --git a/cpukit/libfs/src/devfs/devioctl.c b/cpukit/libfs/src/devfs/devioctl.c index 15965b8c0e..457596fdc4 100644 --- a/cpukit/libfs/src/devfs/devioctl.c +++ b/cpukit/libfs/src/devfs/devioctl.c @@ -23,9 +23,7 @@ int devFS_ioctl( { rtems_libio_ioctl_args_t args; rtems_status_code status; - rtems_device_name_t *np; - - np = (rtems_device_name_t *)iop->pathinfo.node_access; + const devFS_node *np = iop->pathinfo.node_access; args.iop = iop; args.command = command; diff --git a/cpukit/libfs/src/devfs/devopen.c b/cpukit/libfs/src/devfs/devopen.c index 67be3678e1..1b100e1cc7 100644 --- a/cpukit/libfs/src/devfs/devopen.c +++ b/cpukit/libfs/src/devfs/devopen.c @@ -18,15 +18,13 @@ int devFS_open( rtems_libio_t *iop, const char *pathname, - uint32_t flag, - uint32_t mode + int oflag, + mode_t mode ) { rtems_libio_open_close_args_t args; rtems_status_code status; - rtems_device_name_t *np; - - np = (rtems_device_name_t *)iop->pathinfo.node_access; + const devFS_node *np = iop->pathinfo.node_access; args.iop = iop; args.flags = iop->flags; diff --git a/cpukit/libfs/src/devfs/devread.c b/cpukit/libfs/src/devfs/devread.c index 10f74e81c9..31d3f35db9 100644 --- a/cpukit/libfs/src/devfs/devread.c +++ b/cpukit/libfs/src/devfs/devread.c @@ -23,9 +23,7 @@ ssize_t devFS_read( { rtems_libio_rw_args_t args; rtems_status_code status; - rtems_device_name_t *np; - - np = (rtems_device_name_t *)iop->pathinfo.node_access; + const devFS_node *np = iop->pathinfo.node_access; args.iop = iop; args.offset = iop->offset; diff --git a/cpukit/libfs/src/devfs/devstat.c b/cpukit/libfs/src/devfs/devstat.c index e0c52b8b3d..1b780cc58b 100644 --- a/cpukit/libfs/src/devfs/devstat.c +++ b/cpukit/libfs/src/devfs/devstat.c @@ -7,40 +7,25 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <rtems.h> -#include <rtems/io.h> -#include <rtems/seterr.h> -#include <rtems/libio.h> -#include <sys/stat.h> -#include <sys/types.h> - #include "devfs.h" int devFS_stat( - rtems_filesystem_location_info_t *loc, - struct stat *buf + const rtems_filesystem_location_info_t *loc, + struct stat *buf ) { - rtems_device_name_t *the_dev; - - the_dev = (rtems_device_name_t *)loc->node_access; + int rv = 0; + const devFS_node *the_dev = loc->node_access; - /* - * stat() invokes devFS_evaluate_path() which checks that node_access - * is not NULL. So this should NEVER be NULL unless someone breaks - * other code in this filesystem. - */ - #if defined(RTEMS_DEBUG) - if (!the_dev) - rtems_set_errno_and_return_minus_one( EFAULT ); - #endif + if (the_dev != NULL) { + buf->st_rdev = rtems_filesystem_make_dev_t( the_dev->major, the_dev->minor ); + buf->st_mode = the_dev->mode; + } else { + rv = rtems_filesystem_default_fstat(loc, buf); + } - buf->st_rdev = rtems_filesystem_make_dev_t( the_dev->major, the_dev->minor ); - buf->st_mode = the_dev->mode; - return 0; + return rv; } - - diff --git a/cpukit/libfs/src/devfs/devwrite.c b/cpukit/libfs/src/devfs/devwrite.c index 5389c69bc5..2b3aac412b 100644 --- a/cpukit/libfs/src/devfs/devwrite.c +++ b/cpukit/libfs/src/devfs/devwrite.c @@ -23,9 +23,7 @@ ssize_t devFS_write( { rtems_libio_rw_args_t args; rtems_status_code status; - rtems_device_name_t *np; - - np = (rtems_device_name_t *)iop->pathinfo.node_access; + const devFS_node *np = iop->pathinfo.node_access; args.iop = iop; args.offset = iop->offset; diff --git a/cpukit/libfs/src/dosfs/msdos.h b/cpukit/libfs/src/dosfs/msdos.h index 5e24d6ad1d..9bdfd881ec 100644 --- a/cpukit/libfs/src/dosfs/msdos.h +++ b/cpukit/libfs/src/dosfs/msdos.h @@ -168,7 +168,6 @@ typedef rtems_filesystem_node_types_t msdos_node_type_t; /* * Macros for names parsing and formatting */ -#define msdos_is_separator(_ch) rtems_filesystem_is_separator(_ch) #define MSDOS_SHORT_BASE_LEN 8 /* 8 characters */ #define MSDOS_SHORT_EXT_LEN 3 /* 3 characters */ @@ -224,44 +223,40 @@ typedef enum msdos_token_types_e #define MSDOS_DPS512_NUM 16 /* Prototypes */ -int msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry); +void msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry); -int msdos_eval_path( - const char *pathname, /* IN */ - size_t pathnamelen, /* IN */ - int flags, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN/OUT */ -); - -int msdos_eval4make( - const char *path, /* IN */ - rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ - const char **name /* OUT */ -); +void msdos_eval_path(rtems_filesystem_eval_path_context_t *ctx); -int msdos_unlink(rtems_filesystem_location_info_t *pathloc /* IN */); +void msdos_free_node_info(const rtems_filesystem_location_info_t *pathloc); -int msdos_free_node_info(rtems_filesystem_location_info_t *pathloc /* IN */); - -rtems_filesystem_node_types_t msdos_node_type(rtems_filesystem_location_info_t *pathloc); +rtems_filesystem_node_types_t msdos_node_type( + const rtems_filesystem_location_info_t *loc +); int msdos_mknod( - const char *path, /* IN */ - mode_t mode, /* IN */ - dev_t dev, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN/OUT */ + const rtems_filesystem_location_info_t *loc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev ); -int msdos_utime( - rtems_filesystem_location_info_t *pathloc, /* IN */ - time_t actime, /* IN */ - time_t modtime /* IN */ +int msdos_rmnod( + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *loc ); -int msdos_rename(rtems_filesystem_location_info_t *old_parent_loc, - rtems_filesystem_location_info_t *old_loc, - rtems_filesystem_location_info_t *new_parent_loc, - const char *new_name); +int msdos_rename( + const rtems_filesystem_location_info_t *old_parent_loc, + const rtems_filesystem_location_info_t *old_loc, + const rtems_filesystem_location_info_t *new_parent_loc, + const char *new_name, + size_t new_namelen +); + +void msdos_lock(rtems_filesystem_mount_table_entry_t *mt_entry); + +void msdos_unlock(rtems_filesystem_mount_table_entry_t *mt_entry); int msdos_initialize_support( rtems_filesystem_mount_table_entry_t *temp_mt_entry, @@ -273,8 +268,8 @@ int msdos_initialize_support( int msdos_file_open( rtems_libio_t *iop, /* IN */ const char *pathname, /* IN */ - uint32_t flag, /* IN */ - uint32_t mode /* IN */ + int oflag, /* IN */ + mode_t mode /* IN */ ); int msdos_file_close(rtems_libio_t *iop /* IN */); @@ -298,8 +293,8 @@ off_t msdos_file_lseek( ); int msdos_file_stat( - rtems_filesystem_location_info_t *loc, /* IN */ - struct stat *buf /* OUT */ + const rtems_filesystem_location_info_t *loc, + struct stat *buf ); int @@ -312,26 +307,11 @@ int msdos_file_sync(rtems_libio_t *iop); int msdos_file_datasync(rtems_libio_t *iop); -int msdos_file_ioctl( - rtems_libio_t *iop, /* IN */ - uint32_t command, /* IN */ - void *buffer /* IN */ -); - -int -msdos_dir_chmod( - rtems_filesystem_location_info_t *pathloc, /* IN */ - mode_t mode /* IN */ -); - -int msdos_file_rmnod(rtems_filesystem_location_info_t *parent_pathloc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */); - int msdos_dir_open( rtems_libio_t *iop, /* IN */ const char *pathname, /* IN */ - uint32_t flag, /* IN */ - uint32_t mode /* IN */ + int oflag, /* IN */ + mode_t mode /* IN */ ); int msdos_dir_close(rtems_libio_t *iop /* IN */); @@ -348,34 +328,21 @@ off_t msdos_dir_lseek( int whence /* IN */ ); -int -msdos_file_chmod( - rtems_filesystem_location_info_t *pathloc, /* IN */ - mode_t mode /* IN */ -); - -int msdos_dir_rmnod(rtems_filesystem_location_info_t *parent_pathloc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */); - int msdos_dir_sync(rtems_libio_t *iop); int msdos_dir_stat( - rtems_filesystem_location_info_t *loc, /* IN */ - struct stat *buf /* OUT */ + const rtems_filesystem_location_info_t *loc, + struct stat *buf ); -int msdos_creat_node(rtems_filesystem_location_info_t *parent_loc, - msdos_node_type_t type, - const char *name, - int name_len, - mode_t mode, - const fat_file_fd_t *link_fd); +int msdos_creat_node(const rtems_filesystem_location_info_t *parent_loc, + msdos_node_type_t type, + const char *name, + int name_len, + mode_t mode, + const fat_file_fd_t *link_fd); /* Misc prototypes */ -msdos_token_types_t msdos_get_token(const char *path, - int pathlen, - const char **token, - int *token_len); int msdos_find_name( rtems_filesystem_location_info_t *parent_loc, @@ -384,13 +351,13 @@ int msdos_find_name( ); int msdos_get_name_node( - rtems_filesystem_location_info_t *parent_loc, - bool create_node, - const char *name, - int name_len, - msdos_name_type_t name_type, - fat_dir_pos_t *dir_pos, - char *name_dir_entry + const rtems_filesystem_location_info_t *parent_loc, + bool create_node, + const char *name, + int name_len, + msdos_name_type_t name_type, + fat_dir_pos_t *dir_pos, + char *name_dir_entry ); int msdos_dir_info_remove(rtems_filesystem_location_info_t *pathloc); diff --git a/cpukit/libfs/src/dosfs/msdos_create.c b/cpukit/libfs/src/dosfs/msdos_create.c index ec5862a178..263df36353 100644 --- a/cpukit/libfs/src/dosfs/msdos_create.c +++ b/cpukit/libfs/src/dosfs/msdos_create.c @@ -55,12 +55,12 @@ * */ int -msdos_creat_node(rtems_filesystem_location_info_t *parent_loc, - msdos_node_type_t type, - const char *name, - int name_len, - mode_t mode, - const fat_file_fd_t *link_fd) +msdos_creat_node(const rtems_filesystem_location_info_t *parent_loc, + msdos_node_type_t type, + const char *name, + int name_len, + mode_t mode, + const fat_file_fd_t *link_fd) { int rc = RC_OK; ssize_t ret = 0; @@ -83,9 +83,16 @@ msdos_creat_node(rtems_filesystem_location_info_t *parent_loc, memset(short_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); memset(dot_dotdot, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2); + if (name_len > MSDOS_NAME_MAX_LFN_WITH_DOT) { + rtems_set_errno_and_return_minus_one(ENAMETOOLONG); + } + name_type = msdos_long_to_short (name, name_len, MSDOS_DIR_NAME(short_node), MSDOS_NAME_MAX); + if (name_type == MSDOS_NAME_INVALID) { + rtems_set_errno_and_return_minus_one(EINVAL); + } /* fill reserved field */ *MSDOS_DIR_NT_RES(short_node) = MSDOS_RES_NT_VALUE; diff --git a/cpukit/libfs/src/dosfs/msdos_dir.c b/cpukit/libfs/src/dosfs/msdos_dir.c index 494b9fbae6..725fd254d0 100644 --- a/cpukit/libfs/src/dosfs/msdos_dir.c +++ b/cpukit/libfs/src/dosfs/msdos_dir.c @@ -33,20 +33,10 @@ /* msdos_dir_open -- * Open fat-file which correspondes to the directory being opened and * set offset field of file control block to zero. - * - * PARAMETERS: - * iop - file control block - * pathname - name - * flag - flags - * mode - mode - * - * RETURNS: - * RC_OK, if directory opened successfully, or -1 if error occured (errno - * set apropriately) */ int -msdos_dir_open(rtems_libio_t *iop, const char *pathname, uint32_t flag, - uint32_t mode) +msdos_dir_open(rtems_libio_t *iop, const char *pathname, int oflag, + mode_t mode) { int rc = RC_OK; rtems_status_code sc = RTEMS_SUCCESSFUL; @@ -529,9 +519,9 @@ msdos_dir_lseek(rtems_libio_t *iop, off_t offset, int whence) */ int msdos_dir_stat( - rtems_filesystem_location_info_t *loc, - struct stat *buf - ) + const rtems_filesystem_location_info_t *loc, + struct stat *buf +) { rtems_status_code sc = RTEMS_SUCCESSFUL; msdos_fs_info_t *fs_info = loc->mt_entry->fs_info; @@ -594,103 +584,3 @@ msdos_dir_sync(rtems_libio_t *iop) rtems_semaphore_release(fs_info->vol_sema); return rc; } - -/* msdos_dir_chmod -- - * Change the attributes of the directory. This currently does - * nothing and returns no error. - * - * PARAMETERS: - * pathloc - node description - * mode - the new mode - * - * RETURNS: - * RC_OK always - */ -int -msdos_dir_chmod(rtems_filesystem_location_info_t *pathloc, - mode_t mode) -{ - return RC_OK; -} - -/* msdos_dir_rmnod -- - * Remove directory node. - * - * Check that this directory node is not opened as fat-file, is empty and - * not filesystem root node. If all this conditions met then delete. - * - * PARAMETERS: - * pathloc - node description - * - * RETURNS: - * RC_OK on success, or -1 if error occured (errno set apropriately). - */ -int -msdos_dir_rmnod(rtems_filesystem_location_info_t *parent_pathloc, - rtems_filesystem_location_info_t *pathloc) -{ - int rc = RC_OK; - rtems_status_code sc = RTEMS_SUCCESSFUL; - msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info; - fat_file_fd_t *fat_fd = pathloc->node_access; - bool is_empty = false; - - sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT, - MSDOS_VOLUME_SEMAPHORE_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - rtems_set_errno_and_return_minus_one(EIO); - - /* - * You cannot remove a node that still has children - */ - rc = msdos_dir_is_empty(pathloc->mt_entry, fat_fd, &is_empty); - if (rc != RC_OK) - { - rtems_semaphore_release(fs_info->vol_sema); - return rc; - } - - if (!is_empty) - { - rtems_semaphore_release(fs_info->vol_sema); - rtems_set_errno_and_return_minus_one(ENOTEMPTY); - } - - /* - * We deny attempts to delete open directory (if directory is current - * directory we assume it is open one) - */ - if (fat_fd->links_num > 1) - { - rtems_semaphore_release(fs_info->vol_sema); - rtems_set_errno_and_return_minus_one(EBUSY); - } - - /* - * You cannot remove the file system root node. - */ - if (rtems_filesystem_is_root_location(pathloc)) - { - rtems_semaphore_release(fs_info->vol_sema); - rtems_set_errno_and_return_minus_one(EBUSY); - } - - /* - * You cannot remove a mountpoint. - * not used - mount() not implemenetd yet. - */ - - /* mark file removed */ - rc = msdos_set_first_char4file_name(pathloc->mt_entry, &fat_fd->dir_pos, - MSDOS_THIS_DIR_ENTRY_EMPTY); - if (rc != RC_OK) - { - rtems_semaphore_release(fs_info->vol_sema); - return rc; - } - - fat_file_mark_removed(pathloc->mt_entry, fat_fd); - - rtems_semaphore_release(fs_info->vol_sema); - return rc; -} diff --git a/cpukit/libfs/src/dosfs/msdos_eval.c b/cpukit/libfs/src/dosfs/msdos_eval.c index 9b5e0c835d..0ab5971e62 100644 --- a/cpukit/libfs/src/dosfs/msdos_eval.c +++ b/cpukit/libfs/src/dosfs/msdos_eval.c @@ -52,384 +52,58 @@ msdos_set_handlers(rtems_filesystem_location_info_t *loc) loc->handlers = fs_info->file_handlers; } -/* msdos_eval_path -- - * - * The following routine evaluate path for a node that wishes to be - * accessed. Structure 'pathloc' is returned with a pointer to the - * node to be accessed. - * - * PARAMETERS: - * pathname - path for evaluation - * flags - flags - * pathloc - node description (IN/OUT) - * - * RETURNS: - * RC_OK and filled pathloc on success, or -1 if error occured - * (errno set appropriately) - * - */ -int -msdos_eval_path( - const char *pathname, - size_t pathnamelen, - int flags, - rtems_filesystem_location_info_t *pathloc - ) +static bool msdos_is_directory( + rtems_filesystem_eval_path_context_t *ctx, + void *arg +) { - int rc = RC_OK; - rtems_status_code sc = RTEMS_SUCCESSFUL; - msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info; - fat_file_fd_t *fat_fd = NULL; - rtems_filesystem_location_info_t newloc; - int i = 0; - int token_len = 0; - msdos_token_types_t type = MSDOS_CURRENT_DIR; - const char *token; - - sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT, - MSDOS_VOLUME_SEMAPHORE_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - rtems_set_errno_and_return_minus_one(EIO); - - if (!pathloc->node_access) - { - errno = ENOENT; - rc = -1; - goto err; - } - - fat_fd = pathloc->node_access; - - rc = fat_file_reopen(fat_fd); - if (rc != RC_OK) - goto err; - - while ((type != MSDOS_NO_MORE_PATH) && (type != MSDOS_INVALID_TOKEN)) - { - type = msdos_get_token(&pathname[i], pathnamelen, &token, &token_len); - pathnamelen -= token_len; - i += token_len; - - fat_fd = pathloc->node_access; - - switch (type) - { - case MSDOS_UP_DIR: - /* - * Only a directory can be decended into. - */ - if (fat_fd->fat_file_type != FAT_DIRECTORY) - { - errno = ENOTSUP; - rc = -1; - goto error; - } + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc( ctx ); + fat_file_fd_t *fat_fd = currentloc->node_access; - /* - * Am I at the root of this mounted filesystem? - */ - if (rtems_filesystem_is_root_location(pathloc)) - { - /* - * Am I at the root of all filesystems? - * XXX: MSDOS is not supposed to be base fs. - */ - if (pathloc->node_access == - rtems_filesystem_root.node_access) - { - break; /* Throw out the .. in this case */ - } - else - { - newloc = pathloc->mt_entry->mt_point_node; - *pathloc = newloc; - - rc = fat_file_close(pathloc->mt_entry, fat_fd); - if (rc != RC_OK) - goto err; - - rtems_semaphore_release(fs_info->vol_sema); - return (*pathloc->ops->evalpath_h)(&(pathname[i-token_len]), - pathnamelen + token_len, - flags, pathloc); - } - } - else - { - rc = msdos_find_name(pathloc, token, token_len); - if (rc != RC_OK) - { - if (rc == MSDOS_NAME_NOT_FOUND_ERR) - { - errno = ENOENT; - rc = -1; - } - goto error; - } - } - break; - - case MSDOS_NAME: - /* - * Only a directory can be decended into. - */ - if (fat_fd->fat_file_type != FAT_DIRECTORY) - { - errno = ENOTSUP; - rc = -1; - goto error; - } - - /* - * Otherwise find the token name in the present location and - * set the node access to the point we have found. - */ - rc = msdos_find_name(pathloc, token, token_len); - if (rc != RC_OK) - { - if (rc == MSDOS_NAME_NOT_FOUND_ERR) - { - errno = ENOENT; - rc = -1; - } - goto error; - } - break; - - case MSDOS_NO_MORE_PATH: - case MSDOS_CURRENT_DIR: - break; - - case MSDOS_INVALID_TOKEN: - errno = ENAMETOOLONG; - rc = -1; - goto error; - 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. - * NOTE: MSDOS filesystem currently doesn't support mount functionality -> - * action not implemented - */ - fat_fd = pathloc->node_access; - - msdos_set_handlers(pathloc); - - rtems_semaphore_release(fs_info->vol_sema); - return RC_OK; - -error: - fat_file_close(pathloc->mt_entry, fat_fd); - -err: - rtems_semaphore_release(fs_info->vol_sema); - return rc; + return fat_fd->fat_file_type == MSDOS_DIRECTORY; } -/* msdos_eval4make -- - * 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. - * - * PARAMETERS: - * path - path for evaluation - * pathloc - IN/OUT (start point for evaluation/parent directory for - * creation) - * name - new node name - * - * RETURNS: - * RC_OK, filled pathloc for parent directory and name of new node on - * success, or -1 if error occured (errno set appropriately) - */ -int -msdos_eval4make( - const char *path, - rtems_filesystem_location_info_t *pathloc, - const char **name - ) +static rtems_filesystem_eval_path_generic_status msdos_eval_token( + rtems_filesystem_eval_path_context_t *ctx, + void *arg, + const char *token, + size_t tokenlen +) { - int rc = RC_OK; - rtems_status_code sc = RTEMS_SUCCESSFUL; - msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info; - fat_file_fd_t *fat_fd = NULL; - rtems_filesystem_location_info_t newloc; - msdos_token_types_t type; - int i = 0; - int token_len; - const char *token; - bool done = false; - - sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT, - MSDOS_VOLUME_SEMAPHORE_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - rtems_set_errno_and_return_minus_one(EIO); - - if (!pathloc->node_access) - { - errno = ENOENT; - rc = -1; - goto err; + rtems_filesystem_eval_path_generic_status status = + RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE; + + if (rtems_filesystem_is_current_directory(token, tokenlen)) { + rtems_filesystem_eval_path_clear_token(ctx); + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; + } else { + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc(ctx); + int rc = msdos_find_name(currentloc, token, tokenlen); + + if (rc == RC_OK) { + rtems_filesystem_eval_path_clear_token(ctx); + msdos_set_handlers(currentloc); + if (rtems_filesystem_eval_path_has_path(ctx)) { + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; + } + } else if (rc == MSDOS_NAME_NOT_FOUND_ERR) { + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY; + } else { + rtems_filesystem_eval_path_error(ctx, 0); } + } - fat_fd = pathloc->node_access; - - rc = fat_file_reopen(fat_fd); - if (rc != RC_OK) - goto err; - - while (!done) - { - type = msdos_get_token(&path[i], strlen(&path[i]), &token, &token_len); - i += token_len; - fat_fd = pathloc->node_access; - - switch (type) - { - case MSDOS_UP_DIR: - /* - * Only a directory can be decended into. - */ - if (fat_fd->fat_file_type != FAT_DIRECTORY) - { - errno = ENOTDIR; - rc = -1; - goto error; - } - - /* - * Am I at the root of this mounted filesystem? - */ - if (rtems_filesystem_is_root_location(pathloc)) - { - /* - * Am I at the root of all filesystems? - * XXX: MSDOS is not supposed to be base fs. - */ - if (pathloc->node_access == - rtems_filesystem_root.node_access) - { - break; /* Throw out the .. in this case */ - } - else - { - newloc = pathloc->mt_entry->mt_point_node; - *pathloc = newloc; - - rc = fat_file_close(pathloc->mt_entry, fat_fd); - if (rc != RC_OK) - goto err; - - rtems_semaphore_release(fs_info->vol_sema); - return (*pathloc->ops->evalformake_h)(&path[i-token_len], - pathloc, name); - } - } - else - { - rc = msdos_find_name(pathloc, token, token_len); - if (rc != RC_OK) - { - if (rc == MSDOS_NAME_NOT_FOUND_ERR) - { - errno = ENOENT; - rc = -1; - } - goto error; - } - } - break; - - case MSDOS_NAME: - /* - * Only a directory can be decended into. - */ - if (fat_fd->fat_file_type != FAT_DIRECTORY) - { - errno = ENOTDIR; - rc = -1; - goto error; - } - - /* - * Otherwise find the token name in the present location and - * set the node access to the point we have found. - */ - rc = msdos_find_name(pathloc, token, token_len); - if (rc) - { - if (rc != MSDOS_NAME_NOT_FOUND_ERR) - { - errno = ENOENT; - rc = -1; - goto error; - } - else - done = true; - } - break; - - case MSDOS_NO_MORE_PATH: - errno = EEXIST; - rc = -1; - goto error; - break; - - case MSDOS_CURRENT_DIR: - break; - - case MSDOS_INVALID_TOKEN: - errno = ENAMETOOLONG; - rc = -1; - goto error; - break; - - } - } - - *name = &path[i - token_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 (!msdos_is_separator(path[i])) - { - errno = ENOENT; - rc = -1; - goto error; - } - } - - fat_fd = pathloc->node_access; - - if (fat_fd->fat_file_type != FAT_DIRECTORY) - { - errno = ENOTDIR; - rc = -1; - goto error; - } - - msdos_set_handlers(pathloc); - - rtems_semaphore_release(fs_info->vol_sema); - return RC_OK; + return status; +} -error: - fat_file_close(pathloc->mt_entry, fat_fd); +static const rtems_filesystem_eval_path_generic_config msdos_eval_config = { + .is_directory = msdos_is_directory, + .eval_token = msdos_eval_token +}; -err: - rtems_semaphore_release(fs_info->vol_sema); - return rc; +void msdos_eval_path(rtems_filesystem_eval_path_context_t *ctx) +{ + rtems_filesystem_eval_path_generic(ctx, NULL, &msdos_eval_config); } diff --git a/cpukit/libfs/src/dosfs/msdos_file.c b/cpukit/libfs/src/dosfs/msdos_file.c index 5378a25914..b2f98b890d 100644 --- a/cpukit/libfs/src/dosfs/msdos_file.c +++ b/cpukit/libfs/src/dosfs/msdos_file.c @@ -41,8 +41,8 @@ * and errno set appropriately */ int -msdos_file_open(rtems_libio_t *iop, const char *pathname, uint32_t flag, - uint32_t mode) +msdos_file_open(rtems_libio_t *iop, const char *pathname, int oflag, + mode_t mode) { int rc = RC_OK; rtems_status_code sc = RTEMS_SUCCESSFUL; @@ -268,9 +268,9 @@ msdos_file_lseek(rtems_libio_t *iop, off_t offset, int whence) */ int msdos_file_stat( - rtems_filesystem_location_info_t *loc, - struct stat *buf - ) + const rtems_filesystem_location_info_t *loc, + struct stat *buf +) { rtems_status_code sc = RTEMS_SUCCESSFUL; msdos_fs_info_t *fs_info = loc->mt_entry->fs_info; @@ -426,81 +426,3 @@ msdos_file_datasync(rtems_libio_t *iop) rtems_semaphore_release(fs_info->vol_sema); return RC_OK; } - - -/* msdos_file_ioctl -- - * - * - * PARAMETERS: - * iop - file control block - * ... - * - * RETURNS: - * - */ -int -msdos_file_ioctl(rtems_libio_t *iop,uint32_t command, void *buffer) -{ - int rc = RC_OK; - - return rc; -} - -/* msdos_file_chmod -- - * Change the attributes of the file. This currently does - * nothing and returns no error. - * - * PARAMETERS: - * pathloc - node description - * mode - the new mode - * - * RETURNS: - * RC_OK always - */ -int -msdos_file_chmod(rtems_filesystem_location_info_t *pathloc, - mode_t mode) -{ - return RC_OK; -} - -/* msdos_file_rmnod -- - * Remove node associated with a file - set up first name character to - * predefined value(and write it to the disk), and mark fat-file which - * correspondes to the file as "removed" - * - * PARAMETERS: - * pathloc - node description - * - * RETURNS: - * RC_OK on success, or -1 if error occured (errno set appropriately) - */ -int -msdos_file_rmnod(rtems_filesystem_location_info_t *parent_pathloc, - rtems_filesystem_location_info_t *pathloc) -{ - int rc = RC_OK; - rtems_status_code sc = RTEMS_SUCCESSFUL; - msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info; - fat_file_fd_t *fat_fd = pathloc->node_access; - - sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT, - MSDOS_VOLUME_SEMAPHORE_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - rtems_set_errno_and_return_minus_one(EIO); - - /* mark file removed */ - rc = msdos_set_first_char4file_name(pathloc->mt_entry, - &fat_fd->dir_pos, - MSDOS_THIS_DIR_ENTRY_EMPTY); - if (rc != RC_OK) - { - rtems_semaphore_release(fs_info->vol_sema); - return rc; - } - - fat_file_mark_removed(pathloc->mt_entry, fat_fd); - - rtems_semaphore_release(fs_info->vol_sema); - return RC_OK; -} diff --git a/cpukit/libfs/src/dosfs/msdos_free.c b/cpukit/libfs/src/dosfs/msdos_free.c index 90fc586a10..da99dc5d36 100644 --- a/cpukit/libfs/src/dosfs/msdos_free.c +++ b/cpukit/libfs/src/dosfs/msdos_free.c @@ -29,28 +29,9 @@ /* msdos_free_node_info -- * Call fat-file close routine. - * - * PARAMETERS: - * pathloc - node description - * - * RETURNS: - * RC_OK on success, or -1 code if error occured - * */ -int -msdos_free_node_info(rtems_filesystem_location_info_t *pathloc) +void +msdos_free_node_info(const rtems_filesystem_location_info_t *pathloc) { - int rc = RC_OK; - rtems_status_code sc = RTEMS_SUCCESSFUL; - msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info; - - sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT, - MSDOS_VOLUME_SEMAPHORE_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - rtems_set_errno_and_return_minus_one(EIO); - - rc = fat_file_close(pathloc->mt_entry, pathloc->node_access); - - rtems_semaphore_release(fs_info->vol_sema); - return rc; + fat_file_close(pathloc->mt_entry, pathloc->node_access); } diff --git a/cpukit/libfs/src/dosfs/msdos_fsunmount.c b/cpukit/libfs/src/dosfs/msdos_fsunmount.c index 310da9c8ff..37b7730525 100644 --- a/cpukit/libfs/src/dosfs/msdos_fsunmount.c +++ b/cpukit/libfs/src/dosfs/msdos_fsunmount.c @@ -38,33 +38,19 @@ * PARAMETERS: * temp_mt_entry - mount table entry * - * RETURNS: - * RC_OK on success, or -1 if error occured (errno set apropriately). - * */ -int +void msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry) { - int rc = RC_OK; msdos_fs_info_t *fs_info = temp_mt_entry->fs_info; - fat_file_fd_t *fat_fd = temp_mt_entry->mt_fs_root.node_access; + fat_file_fd_t *fat_fd = temp_mt_entry->mt_fs_root->location.node_access; /* close fat-file which correspondes to root directory */ - if (fat_file_close(temp_mt_entry, fat_fd) != RC_OK) - { - /* no return - try to free as much as possible */ - rc = -1; - } + fat_file_close(temp_mt_entry, fat_fd); - if (fat_shutdown_drive(temp_mt_entry) != RC_OK) - { - /* no return - try to free as much as possible */ - rc = -1; - } + fat_shutdown_drive(temp_mt_entry); rtems_semaphore_delete(fs_info->vol_sema); free(fs_info->cl_buf); free(temp_mt_entry->fs_info); - - return rc; } diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_dir.c b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c index 933960a3e2..193d796dd9 100644 --- a/cpukit/libfs/src/dosfs/msdos_handlers_dir.c +++ b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c @@ -26,10 +26,8 @@ const rtems_filesystem_file_handlers_r msdos_dir_handlers = { rtems_filesystem_default_ioctl, msdos_dir_lseek, msdos_dir_stat, - msdos_dir_chmod, - rtems_filesystem_default_ftruncate, + rtems_filesystem_default_ftruncate_directory, msdos_dir_sync, msdos_dir_sync, - rtems_filesystem_default_fcntl, - msdos_dir_rmnod + rtems_filesystem_default_fcntl }; diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_file.c b/cpukit/libfs/src/dosfs/msdos_handlers_file.c index 8990236303..fefb6795d9 100644 --- a/cpukit/libfs/src/dosfs/msdos_handlers_file.c +++ b/cpukit/libfs/src/dosfs/msdos_handlers_file.c @@ -23,13 +23,11 @@ const rtems_filesystem_file_handlers_r msdos_file_handlers = { msdos_file_close, msdos_file_read, msdos_file_write, - msdos_file_ioctl, + rtems_filesystem_default_ioctl, msdos_file_lseek, msdos_file_stat, - msdos_file_chmod, msdos_file_ftruncate, msdos_file_sync, msdos_file_datasync, - rtems_filesystem_default_fcntl, - msdos_file_rmnod + rtems_filesystem_default_fcntl }; diff --git a/cpukit/libfs/src/dosfs/msdos_init.c b/cpukit/libfs/src/dosfs/msdos_init.c index 217e0c1f3a..8941ec45dc 100644 --- a/cpukit/libfs/src/dosfs/msdos_init.c +++ b/cpukit/libfs/src/dosfs/msdos_init.c @@ -4,6 +4,9 @@ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru> * + * 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. @@ -19,27 +22,59 @@ #include "dosfs.h" #include "msdos.h" +static int msdos_clone_node_info(rtems_filesystem_location_info_t *loc) +{ + fat_file_fd_t *fat_fd = loc->node_access; + + return fat_file_reopen(fat_fd); +} + const rtems_filesystem_operations_table msdos_ops = { - .evalpath_h = msdos_eval_path, - .evalformake_h = msdos_eval4make, + .lock_h = msdos_lock, + .unlock_h = msdos_unlock, + .eval_path_h = msdos_eval_path, .link_h = rtems_filesystem_default_link, - .unlink_h = msdos_file_rmnod, + .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal, .node_type_h = msdos_node_type, .mknod_h = msdos_mknod, + .rmnod_h = msdos_rmnod, + .fchmod_h = rtems_filesystem_default_fchmod, .chown_h = rtems_filesystem_default_chown, + .clonenod_h = msdos_clone_node_info, .freenod_h = msdos_free_node_info, .mount_h = rtems_filesystem_default_mount, .fsmount_me_h = rtems_dosfs_initialize, .unmount_h = rtems_filesystem_default_unmount, .fsunmount_me_h = msdos_shut_down, .utime_h = rtems_filesystem_default_utime, - .eval_link_h = rtems_filesystem_default_evaluate_link, .symlink_h = rtems_filesystem_default_symlink, .readlink_h = rtems_filesystem_default_readlink, .rename_h = msdos_rename, .statvfs_h = rtems_filesystem_default_statvfs }; +void msdos_lock(rtems_filesystem_mount_table_entry_t *mt_entry) +{ + msdos_fs_info_t *fs_info = mt_entry->fs_info; + rtems_status_code sc = rtems_semaphore_obtain( + fs_info->vol_sema, + RTEMS_WAIT, + RTEMS_NO_TIMEOUT + ); + if (sc != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(0xdeadbeef); + } +} + +void msdos_unlock(rtems_filesystem_mount_table_entry_t *mt_entry) +{ + msdos_fs_info_t *fs_info = mt_entry->fs_info; + rtems_status_code sc = rtems_semaphore_release(fs_info->vol_sema); + if (sc != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(0xdeadbeef); + } +} + /* msdos_initialize -- * MSDOS filesystem initialization. Called when mounting an * MSDOS filesystem. diff --git a/cpukit/libfs/src/dosfs/msdos_initsupp.c b/cpukit/libfs/src/dosfs/msdos_initsupp.c index fc10fda71a..27905d08ca 100644 --- a/cpukit/libfs/src/dosfs/msdos_initsupp.c +++ b/cpukit/libfs/src/dosfs/msdos_initsupp.c @@ -141,9 +141,9 @@ msdos_initialize_support( rtems_set_errno_and_return_minus_one( EIO ); } - temp_mt_entry->mt_fs_root.node_access = fat_fd; - temp_mt_entry->mt_fs_root.handlers = directory_handlers; - temp_mt_entry->mt_fs_root.ops = op_table; + temp_mt_entry->mt_fs_root->location.node_access = fat_fd; + temp_mt_entry->mt_fs_root->location.handlers = directory_handlers; + temp_mt_entry->mt_fs_root->location.ops = op_table; return rc; } diff --git a/cpukit/libfs/src/dosfs/msdos_misc.c b/cpukit/libfs/src/dosfs/msdos_misc.c index f272d842a2..f27b4aea9c 100644 --- a/cpukit/libfs/src/dosfs/msdos_misc.c +++ b/cpukit/libfs/src/dosfs/msdos_misc.c @@ -257,89 +257,6 @@ msdos_long_to_short(const char *lfn, int lfn_len, char* sfn, int sfn_len) return type; } -/* msdos_get_token -- - * Routine to get a token (name or separator) from the path. - * - * PARAMETERS: - * path - path to get token from - * ret_token - returned token - * token_len - length of returned token - * - * RETURNS: - * token type, token and token length - * - */ -msdos_token_types_t -msdos_get_token(const char *path, - int pathlen, - const char **ret_token, - int *ret_token_len) -{ - msdos_token_types_t type = MSDOS_NAME; - int i = 0; - - *ret_token = NULL; - *ret_token_len = 0; - - if (pathlen == 0) - return MSDOS_NO_MORE_PATH; - - /* - * Check for a separator. - */ - while (!msdos_is_separator(path[i]) && (i < pathlen)) - { - if ( !msdos_is_valid_name_char(path[i]) ) - return MSDOS_INVALID_TOKEN; - ++i; - if ( i == MSDOS_NAME_MAX_LFN_WITH_DOT ) - return MSDOS_INVALID_TOKEN; - } - - *ret_token = path; - - /* - * If it is just a separator then it is the current dir. - */ - if ( i == 0 ) - { - if ( (*path != '\0') && pathlen ) - { - i++; - type = MSDOS_CURRENT_DIR; - } - else - type = MSDOS_NO_MORE_PATH; - } - - /* - * Set the token and token_len to the token start and length. - */ - *ret_token_len = i; - - /* - * If we copied something that was not a seperator see if - * it was a special name. - */ - if ( type == MSDOS_NAME ) - { - if ((i == 2) && ((*ret_token)[0] == '.') && ((*ret_token)[1] == '.')) - { - type = MSDOS_UP_DIR; - return type; - } - - if ((i == 1) && ((*ret_token)[0] == '.')) - { - type = MSDOS_CURRENT_DIR; - return type; - } - } - - return type; -} - - /* msdos_find_name -- * Find the node which correspondes to the name, open fat-file which * correspondes to the found node and close fat-file which correspondes @@ -491,13 +408,13 @@ msdos_find_name( */ int msdos_get_name_node( - rtems_filesystem_location_info_t *parent_loc, - bool create_node, - const char *name, - int name_len, - msdos_name_type_t name_type, - fat_dir_pos_t *dir_pos, - char *name_dir_entry + const rtems_filesystem_location_info_t *parent_loc, + bool create_node, + const char *name, + int name_len, + msdos_name_type_t name_type, + fat_dir_pos_t *dir_pos, + char *name_dir_entry ) { int rc = RC_OK; diff --git a/cpukit/libfs/src/dosfs/msdos_mknod.c b/cpukit/libfs/src/dosfs/msdos_mknod.c index ad4ad50d00..195addaf9f 100644 --- a/cpukit/libfs/src/dosfs/msdos_mknod.c +++ b/cpukit/libfs/src/dosfs/msdos_mknod.c @@ -31,31 +31,16 @@ #include "msdos.h" -/* msdos_mknod -- - * The following function checks spelling and formats name for a new node, - * determines type of the node to be created and creates it. - * - * PARAMETERS: - * name - file name to create - * mode - node type - * dev - dev - * pathloc - parent directory description - * - * RETURNS: - * RC_OK on succes, or -1 if error occured and set errno - * - */ int msdos_mknod( - const char *name, - mode_t mode, - dev_t dev, - rtems_filesystem_location_info_t *pathloc + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev ) { int rc = RC_OK; - rtems_status_code sc = RTEMS_SUCCESSFUL; - msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info; - msdos_token_types_t type = 0; + msdos_node_type_t type = 0; /* * Figure out what type of msdos node this is. @@ -71,14 +56,8 @@ int msdos_mknod( else rtems_set_errno_and_return_minus_one(EINVAL); - sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT, - MSDOS_VOLUME_SEMAPHORE_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - rtems_set_errno_and_return_minus_one(EIO); - /* Create an MSDOS node */ - rc = msdos_creat_node(pathloc, type, name, strlen(name), mode, NULL); + rc = msdos_creat_node(parentloc, type, name, namelen, mode, NULL); - rtems_semaphore_release(fs_info->vol_sema); return rc; } diff --git a/cpukit/libfs/src/dosfs/msdos_node_type.c b/cpukit/libfs/src/dosfs/msdos_node_type.c index 877cf60492..be6fb9f57e 100644 --- a/cpukit/libfs/src/dosfs/msdos_node_type.c +++ b/cpukit/libfs/src/dosfs/msdos_node_type.c @@ -32,17 +32,17 @@ #include "msdos.h" /* msdos_node_type -- - * Determine type of the node that the pathloc refers to. + * Determine type of the node that the loc refers to. * * PARAMETERS: - * pathloc - node description + * loc - node description * * RETURNS: * node type * */ rtems_filesystem_node_types_t -msdos_node_type(rtems_filesystem_location_info_t *pathloc) +msdos_node_type(const rtems_filesystem_location_info_t *loc) { fat_file_fd_t *fat_fd; @@ -52,7 +52,7 @@ msdos_node_type(rtems_filesystem_location_info_t *pathloc) * hence node_access memory can't be freed during processing node_type_h * call */ - fat_fd = pathloc->node_access; + fat_fd = loc->node_access; return fat_fd->fat_file_type; } diff --git a/cpukit/libfs/src/dosfs/msdos_rename.c b/cpukit/libfs/src/dosfs/msdos_rename.c index 1d285bd01d..8490d58370 100644 --- a/cpukit/libfs/src/dosfs/msdos_rename.c +++ b/cpukit/libfs/src/dosfs/msdos_rename.c @@ -30,53 +30,28 @@ /* msdos_rename -- * Rename the node by removing the exitsing directory entry and creating a * new one. - * - * PARAMETERS: - * old_parent_loc - node description for the "old parent" node - * old_loc - node description for the "old" node - * new_parent_loc - node description for the "parent" node - * name - name of new node - * - * RETURNS: - * RC_OK on success, or -1 if error occured (errno set appropriately) */ int -msdos_rename(rtems_filesystem_location_info_t *old_parent_loc, - rtems_filesystem_location_info_t *old_loc, - rtems_filesystem_location_info_t *new_parent_loc, - const char *new_name) +msdos_rename( + const rtems_filesystem_location_info_t *old_parent_loc, + const rtems_filesystem_location_info_t *old_loc, + const rtems_filesystem_location_info_t *new_parent_loc, + const char *new_name, + size_t new_namelen +) { int rc = RC_OK; - rtems_status_code sc = RTEMS_SUCCESSFUL; - msdos_fs_info_t *fs_info = new_parent_loc->mt_entry->fs_info; fat_file_fd_t *old_fat_fd = old_loc->node_access; - const char *token; - int len; - - /* - * check spelling and format new node name - */ - if (MSDOS_NAME != msdos_get_token(new_name, strlen(new_name), &token, &len)) { - rtems_set_errno_and_return_minus_one(ENAMETOOLONG); - } - /* - * lock volume - */ - sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT, - MSDOS_VOLUME_SEMAPHORE_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - rtems_set_errno_and_return_minus_one(EIO); /* * create new directory entry as "hard link", copying relevant info from * existing file */ rc = msdos_creat_node(new_parent_loc, - MSDOS_HARD_LINK,new_name,len,S_IFREG, + MSDOS_HARD_LINK,new_name,new_namelen,S_IFREG, old_fat_fd); if (rc != RC_OK) { - rtems_semaphore_release(fs_info->vol_sema); return rc; } @@ -87,6 +62,5 @@ msdos_rename(rtems_filesystem_location_info_t *old_parent_loc, &old_fat_fd->dir_pos, MSDOS_THIS_DIR_ENTRY_EMPTY); - rtems_semaphore_release(fs_info->vol_sema); return rc; } diff --git a/cpukit/libfs/src/dosfs/msdos_rmnod.c b/cpukit/libfs/src/dosfs/msdos_rmnod.c new file mode 100644 index 0000000000..56431b2133 --- /dev/null +++ b/cpukit/libfs/src/dosfs/msdos_rmnod.c @@ -0,0 +1,79 @@ +/* + * MSDOS directory handlers implementation + * + * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia + * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru> + * + * 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" +#endif + +#include "msdos.h" + +int +msdos_rmnod(const rtems_filesystem_location_info_t *parent_pathloc, + const rtems_filesystem_location_info_t *pathloc) +{ + int rc = RC_OK; + fat_file_fd_t *fat_fd = pathloc->node_access; + + if (fat_fd->fat_file_type == MSDOS_DIRECTORY) + { + bool is_empty = false; + + /* + * You cannot remove a node that still has children + */ + rc = msdos_dir_is_empty(pathloc->mt_entry, fat_fd, &is_empty); + if (rc != RC_OK) + { + return rc; + } + + if (!is_empty) + { + rtems_set_errno_and_return_minus_one(ENOTEMPTY); + } + + /* + * We deny attempts to delete open directory (if directory is current + * directory we assume it is open one) + */ + if (fat_fd->links_num > 1) + { + rtems_set_errno_and_return_minus_one(EBUSY); + } + + /* + * You cannot remove the file system root node. + */ + if (rtems_filesystem_location_is_root(pathloc)) + { + rtems_set_errno_and_return_minus_one(EBUSY); + } + + /* + * You cannot remove a mountpoint. + * not used - mount() not implemenetd yet. + */ + } + + /* mark file removed */ + rc = msdos_set_first_char4file_name(pathloc->mt_entry, &fat_fd->dir_pos, + MSDOS_THIS_DIR_ENTRY_EMPTY); + if (rc != RC_OK) + { + return rc; + } + + fat_file_mark_removed(pathloc->mt_entry, fat_fd); + + return rc; +} diff --git a/cpukit/libfs/src/imfs/deviceio.c b/cpukit/libfs/src/imfs/deviceio.c index bb66703be9..69f409e472 100644 --- a/cpukit/libfs/src/imfs/deviceio.c +++ b/cpukit/libfs/src/imfs/deviceio.c @@ -15,15 +15,13 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <rtems.h> -#include <rtems/libio.h> -#include <rtems/devfs.h> - #include "imfs.h" +#include <rtems/devfs.h> + /* * device_open * @@ -33,8 +31,8 @@ int device_open( rtems_libio_t *iop, const char *pathname, - uint32_t flag, - uint32_t mode + int oflag, + mode_t mode ) { rtems_libio_open_close_args_t args; diff --git a/cpukit/libfs/src/imfs/fifoimfs_init.c b/cpukit/libfs/src/imfs/fifoimfs_init.c index 13dc373eec..d2af7af8e5 100644 --- a/cpukit/libfs/src/imfs/fifoimfs_init.c +++ b/cpukit/libfs/src/imfs/fifoimfs_init.c @@ -20,26 +20,29 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif #include "imfs.h" const rtems_filesystem_operations_table fifoIMFS_ops = { - .evalpath_h = IMFS_eval_path, - .evalformake_h = IMFS_evaluate_for_make, + .lock_h = rtems_filesystem_default_lock, + .unlock_h = rtems_filesystem_default_unlock, + .eval_path_h = IMFS_eval_path, .link_h = IMFS_link, - .unlink_h = IMFS_unlink, + .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal, .node_type_h = IMFS_node_type, .mknod_h = IMFS_mknod, + .rmnod_h = IMFS_rmnod, + .fchmod_h = IMFS_fchmod, .chown_h = IMFS_chown, + .clonenod_h = rtems_filesystem_default_clonenode, .freenod_h = rtems_filesystem_default_freenode, .mount_h = IMFS_mount, .fsmount_me_h = fifoIMFS_initialize, .unmount_h = IMFS_unmount, .fsunmount_me_h = IMFS_fsunmount, .utime_h = IMFS_utime, - .eval_link_h = IMFS_evaluate_link, .symlink_h = IMFS_symlink, .readlink_h = IMFS_readlink, .rename_h = IMFS_rename, @@ -54,8 +57,7 @@ int fifoIMFS_initialize( return IMFS_initialize_support( mt_entry, &fifoIMFS_ops, - &IMFS_memfile_handlers, - &IMFS_directory_handlers, + &IMFS_link_handlers, &IMFS_fifo_handlers ); } diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h index b412c2a1fe..2a851acae4 100644 --- a/cpukit/libfs/src/imfs/imfs.h +++ b/cpukit/libfs/src/imfs/imfs.h @@ -18,13 +18,9 @@ #ifndef _RTEMS_IMFS_H #define _RTEMS_IMFS_H -#include <rtems.h> -#include <rtems/chain.h> - -#include <sys/types.h> #include <limits.h> -#include <rtems/libio.h> +#include <rtems/libio_.h> #include <rtems/pipe.h> #ifdef __cplusplus @@ -32,15 +28,6 @@ extern "C" { #endif /* - * File name macros - */ - -#define IMFS_is_valid_name_char( _ch ) ( 1 ) - -#define IMFS_is_separator( _ch ) \ - rtems_filesystem_is_separator( _ch ) - -/* * Data types */ @@ -226,22 +213,11 @@ typedef struct { ino_t ino_count; const rtems_filesystem_file_handlers_r *memfile_handlers; const rtems_filesystem_file_handlers_r *directory_handlers; + const rtems_filesystem_file_handlers_r *link_handlers; const rtems_filesystem_file_handlers_r *fifo_handlers; } IMFS_fs_info_t; /* - * Type defination for tokens returned from IMFS_get_token - */ - -typedef enum { - IMFS_NO_MORE_PATH, - IMFS_CURRENT_DIR, - IMFS_UP_DIR, - IMFS_NAME, - IMFS_INVALID_TOKEN -} IMFS_token_types; - -/* * Shared Data */ @@ -276,29 +252,18 @@ extern int miniIMFS_initialize( extern int IMFS_initialize_support( rtems_filesystem_mount_table_entry_t *mt_entry, const rtems_filesystem_operations_table *op_table, - const rtems_filesystem_file_handlers_r *memfile_handlers, - const rtems_filesystem_file_handlers_r *directory_handlers, + const rtems_filesystem_file_handlers_r *link_handlers, const rtems_filesystem_file_handlers_r *fifo_handlers ); -extern int IMFS_fsunmount( +extern void IMFS_fsunmount( rtems_filesystem_mount_table_entry_t *mt_entry ); extern int rtems_tarfs_load( - char *mountpoint, - uint8_t *tar_image, - size_t tar_size -); - -/* - * Returns the number of characters copied from path to token. - */ -extern IMFS_token_types IMFS_get_token( - const char *path, - int pathlen, - char *token, - int *token_len + const char *mountpoint, + uint8_t *tar_image, + size_t tar_size ); extern void IMFS_dump( void ); @@ -309,88 +274,59 @@ extern void IMFS_dump( void ); */ extern int IMFS_memfile_maximum_size( void ); -extern void IMFS_initialize_jnode( - IMFS_jnode_t *the_jnode, - IMFS_jnode_types_t type, - IMFS_jnode_t *the_parent, - char *name, - mode_t mode -); - -extern IMFS_jnode_t *IMFS_find_match_in_dir( - IMFS_jnode_t *directory, /* IN */ - char *name /* IN */ -); extern rtems_filesystem_node_types_t IMFS_node_type( - rtems_filesystem_location_info_t *pathloc /* IN */ + const rtems_filesystem_location_info_t *loc ); extern int IMFS_stat( - rtems_filesystem_location_info_t *loc, /* IN */ - struct stat *buf /* OUT */ -); - -extern int IMFS_Set_handlers( - rtems_filesystem_location_info_t *loc + const rtems_filesystem_location_info_t *loc, + struct stat *buf ); -extern int IMFS_evaluate_link( - rtems_filesystem_location_info_t *node, /* IN/OUT */ - int flags /* IN */ -); +extern void IMFS_Set_handlers( rtems_filesystem_location_info_t *loc ); -extern int IMFS_eval_path( - const char *pathname, /* IN */ - size_t pathnamelen, /* IN */ - int flags, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN/OUT */ +extern void IMFS_eval_path( + rtems_filesystem_eval_path_context_t *ctx ); extern int IMFS_link( - rtems_filesystem_location_info_t *to_loc, /* IN */ - rtems_filesystem_location_info_t *parent_loc, /* IN */ - const char *token /* IN */ -); - -extern int IMFS_unlink( - rtems_filesystem_location_info_t *parent_pathloc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */ + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *targetloc, + const char *name, + size_t namelen ); extern int IMFS_chown( - rtems_filesystem_location_info_t *pathloc, /* IN */ - uid_t owner, /* IN */ - gid_t group /* IN */ + const rtems_filesystem_location_info_t *loc, + uid_t owner, + gid_t group ); extern int IMFS_mknod( - const char *path, /* IN */ - mode_t mode, /* IN */ - dev_t dev, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN/OUT */ + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev ); extern IMFS_jnode_t *IMFS_allocate_node( IMFS_jnode_types_t type, /* IN */ const char *name, /* IN */ + size_t namelen, /* IN */ mode_t mode /* IN */ ); extern IMFS_jnode_t *IMFS_create_root_node(void); extern IMFS_jnode_t *IMFS_create_node( - rtems_filesystem_location_info_t *parent_loc, /* IN */ - IMFS_jnode_types_t type, /* IN */ - const char *name, /* IN */ - mode_t mode, /* IN */ - const IMFS_types_union *info /* IN */ -); - -extern int IMFS_evaluate_for_make( - const char *path, /* IN */ - rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ - const char **name /* OUT */ + const rtems_filesystem_location_info_t *pathloc, /* IN */ + IMFS_jnode_types_t type, /* IN */ + const char *name, /* IN */ + size_t namelen, /* IN */ + mode_t mode, /* IN */ + const IMFS_types_union *info /* IN */ ); extern int IMFS_mount( @@ -413,8 +349,8 @@ extern int memfile_ftruncate( extern int imfs_dir_open( rtems_libio_t *iop, /* IN */ const char *pathname, /* IN */ - uint32_t flag, /* IN */ - uint32_t mode /* IN */ + int oflag, /* IN */ + mode_t mode /* IN */ ); extern int imfs_dir_close( @@ -433,21 +369,11 @@ extern off_t imfs_dir_lseek( int whence /* IN */ ); -extern int imfs_dir_fstat( - rtems_filesystem_location_info_t *loc, /* IN */ - struct stat *buf /* OUT */ -); - -extern int imfs_dir_rmnod( - rtems_filesystem_location_info_t *parent_pathloc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */ -); - extern int memfile_open( rtems_libio_t *iop, /* IN */ const char *pathname, /* IN */ - uint32_t flag, /* IN */ - uint32_t mode /* IN */ + int oflag, /* IN */ + mode_t mode /* IN */ ); extern int memfile_close( @@ -481,8 +407,8 @@ extern off_t memfile_lseek( extern int device_open( rtems_libio_t *iop, /* IN */ const char *pathname, /* IN */ - uint32_t flag, /* IN */ - uint32_t mode /* IN */ + int oflag, /* IN */ + mode_t mode /* IN */ ); extern int device_close( @@ -519,33 +445,35 @@ extern int device_ftruncate( ); extern int IMFS_utime( - rtems_filesystem_location_info_t *pathloc, /* IN */ - time_t actime, /* IN */ - time_t modtime /* IN */ + const rtems_filesystem_location_info_t *loc, + time_t actime, + time_t modtime ); extern int IMFS_fchmod( - rtems_filesystem_location_info_t *loc, - mode_t mode + const rtems_filesystem_location_info_t *loc, + mode_t mode ); extern int IMFS_symlink( - rtems_filesystem_location_info_t *parent_loc, /* IN */ - const char *link_name, - const char *node_name + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + const char *target ); extern ssize_t IMFS_readlink( - rtems_filesystem_location_info_t *loc, /* IN */ - char *buf, /* OUT */ - size_t bufsize + const rtems_filesystem_location_info_t *loc, + char *buf, + size_t bufsize ); extern int IMFS_rename( - rtems_filesystem_location_info_t *old_loc, /* IN */ - rtems_filesystem_location_info_t *old_parent_loc, /* IN */ - rtems_filesystem_location_info_t *new_parent_loc, /* IN */ - const char *new_name /* IN */ + const rtems_filesystem_location_info_t *oldparentloc, + const rtems_filesystem_location_info_t *oldloc, + const rtems_filesystem_location_info_t *newparentloc, + const char *name, + size_t namelen ); extern int IMFS_fdatasync( @@ -561,8 +489,8 @@ extern void IMFS_check_node_remove( ); extern int IMFS_rmnod( - rtems_filesystem_location_info_t *parent_pathloc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */ + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *loc ); /* diff --git a/cpukit/libfs/src/imfs/imfs_chown.c b/cpukit/libfs/src/imfs/imfs_chown.c index 7f0c7b5688..e31b89e0b0 100644 --- a/cpukit/libfs/src/imfs/imfs_chown.c +++ b/cpukit/libfs/src/imfs/imfs_chown.c @@ -15,18 +15,19 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> -#include <rtems/libio_.h> -#include <rtems/seterr.h> #include "imfs.h" +#include <unistd.h> + +#include <rtems/libio_.h> + int IMFS_chown( - rtems_filesystem_location_info_t *pathloc, /* IN */ - uid_t owner, /* IN */ - gid_t group /* IN */ + const rtems_filesystem_location_info_t *loc, + uid_t owner, + gid_t group ) { IMFS_jnode_t *jnode; @@ -34,7 +35,7 @@ int IMFS_chown( uid_t st_uid; #endif - jnode = (IMFS_jnode_t *) pathloc->node_access; + jnode = (IMFS_jnode_t *) loc->node_access; /* * Verify I am the owner of the node or the super user. diff --git a/cpukit/libfs/src/imfs/imfs_creat.c b/cpukit/libfs/src/imfs/imfs_creat.c index 3b602d0c14..37e3ac0578 100644 --- a/cpukit/libfs/src/imfs/imfs_creat.c +++ b/cpukit/libfs/src/imfs/imfs_creat.c @@ -14,35 +14,32 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif +#include "imfs.h" + #include <stdlib.h> #include <string.h> -#include "imfs.h" -#include <rtems/libio_.h> /* * Create an IMFS filesystem node of an arbitrary type that is NOT * the root directory node. */ IMFS_jnode_t *IMFS_create_node( - rtems_filesystem_location_info_t *parent_loc, - IMFS_jnode_types_t type, - const char *name, - mode_t mode, - const IMFS_types_union *info + const rtems_filesystem_location_info_t *parent_loc, + IMFS_jnode_types_t type, + const char *name, + size_t namelen, + mode_t mode, + const IMFS_types_union *info ) { IMFS_jnode_t *node; IMFS_jnode_t *parent; IMFS_fs_info_t *fs_info; - /* - * MUST have a parent node to call this routine. - */ - if ( parent_loc == NULL ) - return NULL; + IMFS_assert( parent_loc != NULL ); parent = parent_loc->node_access; fs_info = parent_loc->mt_entry->fs_info; @@ -51,13 +48,16 @@ IMFS_jnode_t *IMFS_create_node( * Reject creation of FIFOs if support is disabled. */ if ( type == IMFS_FIFO && - fs_info->fifo_handlers == &rtems_filesystem_handlers_default ) + fs_info->fifo_handlers == &rtems_filesystem_handlers_default ) { + errno = ENOTSUP; + return NULL; + } /* * Allocate filesystem node and fill in basic information */ - node = IMFS_allocate_node( type, name, mode & ~rtems_filesystem_umask ); + node = IMFS_allocate_node( type, name, namelen, mode ); if ( !node ) return NULL; @@ -104,25 +104,36 @@ IMFS_jnode_t *IMFS_create_node( IMFS_jnode_t *IMFS_allocate_node( IMFS_jnode_types_t type, const char *name, + size_t namelen, mode_t mode ) { IMFS_jnode_t *node; struct timeval tv; + if ( namelen > IMFS_NAME_MAX ) { + errno = ENAMETOOLONG; + + return NULL; + } + /* * Allocate an IMFS jnode */ node = calloc( 1, sizeof( IMFS_jnode_t ) ); - if ( !node ) + if ( !node ) { + errno = ENOMEM; + return NULL; + } /* * Fill in the basic information */ node->st_nlink = 1; node->type = type; - strncpy( node->name, name, IMFS_NAME_MAX ); + memcpy( node->name, name, namelen ); + node->name [namelen] = '\0'; /* * Fill in the mode and permission information for the jnode structure. @@ -155,7 +166,7 @@ IMFS_jnode_t *IMFS_create_root_node(void) /* * Allocate filesystem node and fill in basic information */ - node = IMFS_allocate_node( IMFS_DIRECTORY, "", (S_IFDIR | 0755) ); + node = IMFS_allocate_node( IMFS_DIRECTORY, "", 0, (S_IFDIR | 0755) ); if ( !node ) return NULL; diff --git a/cpukit/libfs/src/imfs/imfs_debug.c b/cpukit/libfs/src/imfs/imfs_debug.c index f8bdf1ce41..091237275d 100644 --- a/cpukit/libfs/src/imfs/imfs_debug.c +++ b/cpukit/libfs/src/imfs/imfs_debug.c @@ -12,21 +12,14 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <stdlib.h> -#include <unistd.h> /* for close */ -#include <inttypes.h> +#include "imfs.h" +#include <inttypes.h> +#include <unistd.h> #include <stdio.h> -#include <sys/stat.h> - -#include "imfs.h" -#include <rtems/libio_.h> /* * IMFS_print_jnode @@ -142,7 +135,7 @@ void IMFS_dump( void ) { fprintf(stdout, "*************** Dump of Entire IMFS ***************\n" ); fprintf(stdout, "/\n" ); - IMFS_dump_directory( rtems_filesystem_root.node_access, 0 ); + IMFS_dump_directory( rtems_filesystem_root->location.node_access, 0 ); fprintf(stdout, "*************** End of Dump ***************\n" ); } diff --git a/cpukit/libfs/src/imfs/imfs_directory.c b/cpukit/libfs/src/imfs/imfs_directory.c index 7e0c125104..8ef05b4d1d 100644 --- a/cpukit/libfs/src/imfs/imfs_directory.c +++ b/cpukit/libfs/src/imfs/imfs_directory.c @@ -12,23 +12,14 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <sys/types.h> -#include <sys/stat.h> -#include <rtems/chain.h> -#include <fcntl.h> -#include <errno.h> -#include <stdlib.h> -#include <stdio.h> +#include "imfs.h" + #include <string.h> #include <dirent.h> -#include "imfs.h" -#include <rtems/libio_.h> -#include <rtems/seterr.h> - /* * imfs_dir_open * @@ -40,8 +31,8 @@ int imfs_dir_open( rtems_libio_t *iop, const char *pathname, - uint32_t flag, - uint32_t mode + int oflag, + mode_t mode ) { IMFS_jnode_t *the_jnode; @@ -203,115 +194,3 @@ off_t imfs_dir_lseek( return 0; } - - - -/* - * imfs_dir_fstat - * - * This routine will obtain the following information concerning the current - * directory: - * st_dev 0ll - * st_ino 1 - * st_mode mode extracted from the jnode - * st_nlink number of links to this node - * st_uid uid extracted from the jnode - * st_gid gid extracted from the jnode - * st_rdev 0ll - * st_size the number of bytes in the directory - * This is calculated by taking the number of entries - * in the directory and multiplying by the size of a - * dirent structure - * st_blksize 0 - * st_blocks 0 - * stat_atime time of last access - * stat_mtime time of last modification - * stat_ctime time of the last change - * - * This information will be returned to the calling function in a -stat- struct - * - */ - -int imfs_dir_fstat( - rtems_filesystem_location_info_t *loc, - struct stat *buf -) -{ - rtems_chain_node *the_node; - rtems_chain_control *the_chain; - IMFS_jnode_t *the_jnode; - - - the_jnode = (IMFS_jnode_t *) loc->node_access; - - buf->st_dev = 0ll; - buf->st_ino = the_jnode->st_ino; - buf->st_mode = the_jnode->st_mode; - buf->st_nlink = the_jnode->st_nlink; - buf->st_uid = the_jnode->st_uid; - buf->st_gid = the_jnode->st_gid; - buf->st_rdev = 0ll; - buf->st_blksize = 0; - buf->st_blocks = 0; - buf->st_atime = the_jnode->stat_atime; - buf->st_mtime = the_jnode->stat_mtime; - buf->st_ctime = the_jnode->stat_ctime; - - buf->st_size = 0; - - the_chain = &the_jnode->info.directory.Entries; - - /* Run through the chain and count the number of directory entries */ - /* that are subordinate to this directory node */ - for ( the_node = rtems_chain_first( the_chain ); - !rtems_chain_is_tail( the_chain, the_node ) ; - the_node = the_node->next ) { - - buf->st_size = buf->st_size + sizeof( struct dirent ); - } - - return 0; -} - -/* - * IMFS_dir_rmnod - * - * This routine is available from the optable to remove a node - * from the IMFS file system. - */ - -int imfs_dir_rmnod( - rtems_filesystem_location_info_t *parent_pathloc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */ -) -{ - IMFS_jnode_t *the_jnode; - - the_jnode = (IMFS_jnode_t *) pathloc->node_access; - - /* - * You cannot remove a node that still has children - */ - - if ( ! rtems_chain_is_empty( &the_jnode->info.directory.Entries ) ) - rtems_set_errno_and_return_minus_one( ENOTEMPTY ); - - /* - * You cannot remove the file system root node. - */ - - if ( rtems_filesystem_is_root_location(pathloc) ) - rtems_set_errno_and_return_minus_one( EBUSY ); - - /* - * You cannot remove a mountpoint. - */ - - if ( the_jnode->info.directory.mt_fs != NULL ) - rtems_set_errno_and_return_minus_one( EBUSY ); - - IMFS_create_orphan( the_jnode ); - IMFS_check_node_remove( the_jnode ); - - return 0; -} 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 ); } diff --git a/cpukit/libfs/src/imfs/imfs_fchmod.c b/cpukit/libfs/src/imfs/imfs_fchmod.c index 54a093de2f..4236a2901b 100644 --- a/cpukit/libfs/src/imfs/imfs_fchmod.c +++ b/cpukit/libfs/src/imfs/imfs_fchmod.c @@ -12,18 +12,14 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> - -#include <rtems/libio_.h> -#include <rtems/seterr.h> #include "imfs.h" int IMFS_fchmod( - rtems_filesystem_location_info_t *loc, - mode_t mode + const rtems_filesystem_location_info_t *loc, + mode_t mode ) { IMFS_jnode_t *jnode; diff --git a/cpukit/libfs/src/imfs/imfs_fifo.c b/cpukit/libfs/src/imfs/imfs_fifo.c index e447b26a70..790471e472 100644 --- a/cpukit/libfs/src/imfs/imfs_fifo.c +++ b/cpukit/libfs/src/imfs/imfs_fifo.c @@ -11,13 +11,9 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <stdlib.h> -#include <rtems/libio_.h> -#include <rtems/seterr.h> - #include "imfs.h" #define JNODE2PIPE(_jnode) ( (_jnode)->info.fifo.pipe ) @@ -35,8 +31,8 @@ do { \ static int IMFS_fifo_open( rtems_libio_t *iop, const char *pathname, - uint32_t flag, - uint32_t mode + int oflag, + mode_t mode ) { IMFS_jnode_t *jnode = iop->pathinfo.node_access; @@ -138,10 +134,8 @@ const rtems_filesystem_file_handlers_r IMFS_fifo_handlers = { IMFS_fifo_ioctl, IMFS_fifo_lseek, IMFS_stat, - IMFS_fchmod, rtems_filesystem_default_ftruncate, rtems_filesystem_default_fsync, rtems_filesystem_default_fdatasync, - rtems_filesystem_default_fcntl, - IMFS_rmnod, + rtems_filesystem_default_fcntl }; diff --git a/cpukit/libfs/src/imfs/imfs_fsunmount.c b/cpukit/libfs/src/imfs/imfs_fsunmount.c index b65c20e60d..49ade1bab9 100644 --- a/cpukit/libfs/src/imfs/imfs_fsunmount.c +++ b/cpukit/libfs/src/imfs/imfs_fsunmount.c @@ -12,20 +12,10 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <sys/types.h> /* for mkdir */ -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> - #include "imfs.h" -#include <rtems/libio_.h> - -#if defined(IMFS_DEBUG) -#include <stdio.h> -#endif /* * IMFS_fsunmount @@ -43,7 +33,7 @@ #define jnode_get_first_child( jnode ) \ ((IMFS_jnode_t *)( rtems_chain_head( jnode_get_control( jnode ) )->next)) -int IMFS_fsunmount( +void IMFS_fsunmount( rtems_filesystem_mount_table_entry_t *temp_mt_entry ) { @@ -57,29 +47,24 @@ int IMFS_fsunmount( * associated memory space */ - jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access; - loc = temp_mt_entry->mt_fs_root; + 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.node_access = NULL; + temp_mt_entry->mt_fs_root->location.node_access = NULL; do { next = jnode->Parent; loc.node_access = (void *)jnode; IMFS_Set_handlers( &loc ); - if ( jnode->type != IMFS_DIRECTORY ) { - result = IMFS_unlink( NULL, &loc ); + if ( jnode->type != IMFS_DIRECTORY || jnode_has_no_children( jnode ) ) { + result = IMFS_rmnod( NULL, &loc ); if (result != 0) - return -1; - jnode = next; - } else if ( jnode_has_no_children( jnode ) ) { - result = IMFS_unlink( NULL, &loc ); - if (result != 0) - return -1; + rtems_fatal_error_occurred(0xdeadbeef); jnode = next; } if ( jnode != NULL ) { @@ -89,6 +74,4 @@ int IMFS_fsunmount( } } } while (jnode != NULL); - - return 0; } diff --git a/cpukit/libfs/src/imfs/imfs_getchild.c b/cpukit/libfs/src/imfs/imfs_getchild.c deleted file mode 100644 index 1cfeb2a537..0000000000 --- a/cpukit/libfs/src/imfs/imfs_getchild.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * IMFS_find_match_in_dir() - * - * This routine returns the child name in the given directory. - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * 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" -#endif - -#include <errno.h> -#include <string.h> -#include "imfs.h" - -static const char dotname[2] = "."; -static const char dotdotname[3] = ".."; - -IMFS_jnode_t *IMFS_find_match_in_dir( - IMFS_jnode_t *directory, - char *name -) -{ - rtems_chain_node *the_node; - rtems_chain_control *the_chain; - IMFS_jnode_t *the_jnode; - - /* - * Check for fatal errors. A NULL directory show a problem in the - * the IMFS code. - */ - IMFS_assert( directory ); - IMFS_assert( name ); - - /* - * Check for "." and ".." - */ - - if ( !strcmp( name, dotname ) ) - return directory; - - if ( !strcmp( name, dotdotname ) ) - return directory->Parent; - - the_chain = &directory->info.directory.Entries; - - for ( the_node = rtems_chain_first( the_chain ); - !rtems_chain_is_tail( the_chain, the_node ); - the_node = the_node->next ) { - - the_jnode = (IMFS_jnode_t *) the_node; - - if ( !strcmp( name, the_jnode->name ) ) - return the_jnode; - } - - return 0; -} diff --git a/cpukit/libfs/src/imfs/imfs_gtkn.c b/cpukit/libfs/src/imfs/imfs_gtkn.c deleted file mode 100644 index b15b2f1136..0000000000 --- a/cpukit/libfs/src/imfs/imfs_gtkn.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * IMFS_get_token - * - * Routine to get a token (name or separator) from the path - * the length of the token is returned in token_len. - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * 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" -#endif - -#include <stdlib.h> -#include <string.h> - -#include "imfs.h" -#include <rtems/libio_.h> - -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; -} diff --git a/cpukit/libfs/src/imfs/imfs_handlers_device.c b/cpukit/libfs/src/imfs/imfs_handlers_device.c index 8e249bda33..a6edfb1f77 100644 --- a/cpukit/libfs/src/imfs/imfs_handlers_device.c +++ b/cpukit/libfs/src/imfs/imfs_handlers_device.c @@ -12,11 +12,9 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> - #include "imfs.h" /* @@ -31,10 +29,8 @@ const rtems_filesystem_file_handlers_r IMFS_device_handlers = { device_ioctl, device_lseek, IMFS_stat, - IMFS_fchmod, device_ftruncate, rtems_filesystem_default_fsync, rtems_filesystem_default_fdatasync, - rtems_filesystem_default_fcntl, - IMFS_rmnod + rtems_filesystem_default_fcntl }; diff --git a/cpukit/libfs/src/imfs/imfs_handlers_directory.c b/cpukit/libfs/src/imfs/imfs_handlers_directory.c index 5ca715825e..4778f45599 100644 --- a/cpukit/libfs/src/imfs/imfs_handlers_directory.c +++ b/cpukit/libfs/src/imfs/imfs_handlers_directory.c @@ -12,11 +12,9 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> - #include "imfs.h" /* @@ -30,11 +28,9 @@ const rtems_filesystem_file_handlers_r IMFS_directory_handlers = { rtems_filesystem_default_write, rtems_filesystem_default_ioctl, imfs_dir_lseek, - imfs_dir_fstat, - IMFS_fchmod, - rtems_filesystem_default_ftruncate, + IMFS_stat, + rtems_filesystem_default_ftruncate_directory, rtems_filesystem_default_fsync, IMFS_fdatasync, - rtems_filesystem_default_fcntl, - imfs_dir_rmnod + rtems_filesystem_default_fcntl }; diff --git a/cpukit/libfs/src/imfs/imfs_handlers_link.c b/cpukit/libfs/src/imfs/imfs_handlers_link.c index d8bbec82d4..967aa1410f 100644 --- a/cpukit/libfs/src/imfs/imfs_handlers_link.c +++ b/cpukit/libfs/src/imfs/imfs_handlers_link.c @@ -12,11 +12,9 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> - #include "imfs.h" /* @@ -31,10 +29,8 @@ const rtems_filesystem_file_handlers_r IMFS_link_handlers = { rtems_filesystem_default_ioctl, rtems_filesystem_default_lseek, IMFS_stat, /* stat */ - rtems_filesystem_default_fchmod, rtems_filesystem_default_ftruncate, rtems_filesystem_default_fsync, rtems_filesystem_default_fdatasync, - rtems_filesystem_default_fcntl, - IMFS_rmnod + rtems_filesystem_default_fcntl }; diff --git a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c index ee859ee98d..10e47fd0f8 100644 --- a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c +++ b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c @@ -12,11 +12,9 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> - #include "imfs.h" /* @@ -31,10 +29,8 @@ const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = { memfile_ioctl, memfile_lseek, IMFS_stat, - IMFS_fchmod, memfile_ftruncate, IMFS_fdatasync, /* fsync */ IMFS_fdatasync, - rtems_filesystem_default_fcntl, - IMFS_rmnod + rtems_filesystem_default_fcntl }; diff --git a/cpukit/libfs/src/imfs/imfs_init.c b/cpukit/libfs/src/imfs/imfs_init.c index c74d493b40..2a7d890a09 100644 --- a/cpukit/libfs/src/imfs/imfs_init.c +++ b/cpukit/libfs/src/imfs/imfs_init.c @@ -18,28 +18,29 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <rtems/libio_.h> - #include "imfs.h" const rtems_filesystem_operations_table IMFS_ops = { - .evalpath_h = IMFS_eval_path, - .evalformake_h = IMFS_evaluate_for_make, + .lock_h = rtems_filesystem_default_lock, + .unlock_h = rtems_filesystem_default_unlock, + .eval_path_h = IMFS_eval_path, .link_h = IMFS_link, - .unlink_h = IMFS_unlink, + .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal, .node_type_h = IMFS_node_type, .mknod_h = IMFS_mknod, + .rmnod_h = IMFS_rmnod, + .fchmod_h = IMFS_fchmod, .chown_h = IMFS_chown, + .clonenod_h = rtems_filesystem_default_clonenode, .freenod_h = rtems_filesystem_default_freenode, .mount_h = IMFS_mount, .fsmount_me_h = IMFS_initialize, .unmount_h = IMFS_unmount, .fsunmount_me_h = IMFS_fsunmount, .utime_h = IMFS_utime, - .eval_link_h = IMFS_evaluate_link, .symlink_h = IMFS_symlink, .readlink_h = IMFS_readlink, .rename_h = IMFS_rename, @@ -54,8 +55,7 @@ int IMFS_initialize( return IMFS_initialize_support( mt_entry, &IMFS_ops, - &IMFS_memfile_handlers, - &IMFS_directory_handlers, - &rtems_filesystem_handlers_default /* for fifos */ + &IMFS_link_handlers, + &rtems_filesystem_handlers_default /* for fifos */ ); } diff --git a/cpukit/libfs/src/imfs/imfs_initsupp.c b/cpukit/libfs/src/imfs/imfs_initsupp.c index 47e1d392e8..61ad6a70f2 100644 --- a/cpukit/libfs/src/imfs/imfs_initsupp.c +++ b/cpukit/libfs/src/imfs/imfs_initsupp.c @@ -12,21 +12,12 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <sys/types.h> /* for mkdir */ -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> - #include "imfs.h" -#include <rtems/libio_.h> -#include <rtems/seterr.h> -#if defined(IMFS_DEBUG) -#include <stdio.h> -#endif +#include <stdlib.h> /* * IMFS_determine_bytes_per_block @@ -66,8 +57,7 @@ static int IMFS_determine_bytes_per_block( int IMFS_initialize_support( rtems_filesystem_mount_table_entry_t *temp_mt_entry, const rtems_filesystem_operations_table *op_table, - const rtems_filesystem_file_handlers_r *memfile_handlers, - const rtems_filesystem_file_handlers_r *directory_handlers, + const rtems_filesystem_file_handlers_r *link_handlers, const rtems_filesystem_file_handlers_r *fifo_handlers ) { @@ -87,9 +77,9 @@ int IMFS_initialize_support( * * NOTE: UNIX root is 755 and owned by root/root (0/0). */ - temp_mt_entry->mt_fs_root.node_access = IMFS_create_root_node(); - temp_mt_entry->mt_fs_root.handlers = directory_handlers; - temp_mt_entry->mt_fs_root.ops = op_table; + temp_mt_entry->mt_fs_root->location.node_access = IMFS_create_root_node(); + temp_mt_entry->mt_fs_root->location.handlers = &IMFS_directory_handlers; + temp_mt_entry->mt_fs_root->location.ops = op_table; temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS; /* @@ -97,7 +87,7 @@ int IMFS_initialize_support( */ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) ); if ( !fs_info ) { - free(temp_mt_entry->mt_fs_root.node_access); + free(temp_mt_entry->mt_fs_root->location.node_access); rtems_set_errno_and_return_minus_one(ENOMEM); } temp_mt_entry->fs_info = fs_info; @@ -108,11 +98,10 @@ int IMFS_initialize_support( fs_info->instance = imfs_instance++; fs_info->ino_count = 1; - fs_info->memfile_handlers = memfile_handlers; - fs_info->directory_handlers = directory_handlers; + fs_info->link_handlers = link_handlers; fs_info->fifo_handlers = fifo_handlers; - jnode = temp_mt_entry->mt_fs_root.node_access; + jnode = temp_mt_entry->mt_fs_root->location.node_access; jnode->st_ino = fs_info->ino_count; return 0; diff --git a/cpukit/libfs/src/imfs/imfs_link.c b/cpukit/libfs/src/imfs/imfs_link.c index c7dc6475f9..130c529d75 100644 --- a/cpukit/libfs/src/imfs/imfs_link.c +++ b/cpukit/libfs/src/imfs/imfs_link.c @@ -16,51 +16,36 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> #include "imfs.h" -#include <rtems/libio_.h> -#include <rtems/seterr.h> int IMFS_link( - rtems_filesystem_location_info_t *to_loc, /* IN */ - rtems_filesystem_location_info_t *parent_loc, /* IN */ - const char *token /* IN */ + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *targetloc, + const char *name, + size_t namelen ) { IMFS_types_union info; IMFS_jnode_t *new_node; - char new_name[ IMFS_NAME_MAX + 1 ]; - int i; /* * Verify this node can be linked to. */ - info.hard_link.link_node = to_loc->node_access; + info.hard_link.link_node = targetloc->node_access; if ( info.hard_link.link_node->st_nlink >= LINK_MAX ) rtems_set_errno_and_return_minus_one( EMLINK ); /* - * Remove any separators at the end of the string. - */ - IMFS_get_token( token, strlen( token ), new_name, &i ); - - /* * Create a new link node. - * - * NOTE: Coverity Id 19 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( - parent_loc, + parentloc, IMFS_HARD_LINK, - new_name, + name, + namelen, ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )), &info ); diff --git a/cpukit/libfs/src/imfs/imfs_load_tar.c b/cpukit/libfs/src/imfs/imfs_load_tar.c index 69c69c3e6d..0ae0f7cf88 100644 --- a/cpukit/libfs/src/imfs/imfs_load_tar.c +++ b/cpukit/libfs/src/imfs/imfs_load_tar.c @@ -21,16 +21,12 @@ * pointing to addresses in the TAR image. */ -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <tar.h> +#include "imfs.h" +#include <sys/stat.h> #include <string.h> +#include <tar.h> -#include <rtems.h> -#include <rtems/libio_.h> -#include <rtems/imfs.h> #include <rtems/untar.h> /* @@ -80,13 +76,11 @@ * create_node. */ int rtems_tarfs_load( - char *mountpoint, + const char *mountpoint, uint8_t *tar_image, - size_t tar_size + size_t tar_size ) { - rtems_filesystem_location_info_t root_loc; - rtems_filesystem_location_info_t loc; const char *hdr_ptr; char filename[100]; char full_filename[256]; @@ -97,26 +91,27 @@ int rtems_tarfs_load( int offset; unsigned long nblocks; IMFS_jnode_t *node; - int status; - - status = rtems_filesystem_evaluate_path( - mountpoint, - strlen(mountpoint), - 0, - &root_loc, - 0 + int rv = 0; + int eval_flags = RTEMS_LIBIO_FOLLOW_LINK; + rtems_filesystem_eval_path_context_t ctx; + rtems_filesystem_location_info_t rootloc; + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start( &ctx, mountpoint, eval_flags ); + + rtems_filesystem_eval_path_extract_currentloc( &ctx, &rootloc ); + rtems_filesystem_eval_path_set_flags( + &ctx, + RTEMS_LIBIO_MAKE | RTEMS_LIBIO_EXCLUSIVE ); - if (status != 0) - return -1; - - if (root_loc.ops != &IMFS_ops && root_loc.ops != &fifoIMFS_ops) - return -1; + if (rootloc.ops != &IMFS_ops && rootloc.ops != &fifoIMFS_ops) { + rv = -1; + } /* * Create an IMFS node structure pointing to tar image memory. */ offset = 0; - while (1) { + while ( rv == 0 ) { if (offset + 512 > tar_size) break; @@ -154,22 +149,23 @@ int rtems_tarfs_load( } /* * Create a LINEAR_FILE node - * - * NOTE: Coverity Id 20 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. */ else if (linkflag == REGTYPE) { - const char *name; - - loc = root_loc; - if (IMFS_evaluate_for_make(filename, &loc, &name) == 0) { + rtems_filesystem_location_free( currentloc ); + rtems_filesystem_location_clone( currentloc, &rootloc ); + rtems_filesystem_eval_path_set_path( + &ctx, + filename, + strlen( filename ) + ); + rtems_filesystem_eval_path_continue( &ctx ); + + if ( !rtems_filesystem_location_is_null( currentloc ) ) { node = IMFS_create_node( - &loc, - IMFS_LINEAR_FILE, (char *)name, + currentloc, + IMFS_LINEAR_FILE, + rtems_filesystem_eval_path_get_token( &ctx ), + rtems_filesystem_eval_path_get_tokenlen( &ctx ), (file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG, NULL ); @@ -181,6 +177,10 @@ int rtems_tarfs_load( offset += 512 * nblocks; } } - return status; + + rtems_filesystem_location_free( &rootloc ); + rtems_filesystem_eval_path_cleanup( &ctx ); + + return rv; } diff --git a/cpukit/libfs/src/imfs/imfs_mknod.c b/cpukit/libfs/src/imfs/imfs_mknod.c index 747391e9fd..47f7dca0e8 100644 --- a/cpukit/libfs/src/imfs/imfs_mknod.c +++ b/cpukit/libfs/src/imfs/imfs_mknod.c @@ -6,6 +6,9 @@ * COPYRIGHT (c) 1989-2010. * 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. @@ -14,65 +17,60 @@ */ #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> + +static void get_type_and_info_by_mode_and_dev( + mode_t mode, + dev_t dev, + IMFS_jnode_types_t *type, + IMFS_types_union *info +) +{ + 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 ); + } +} int IMFS_mknod( - const char *token, /* IN */ - mode_t mode, /* IN */ - dev_t dev, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN/OUT */ + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev ) { - IMFS_token_types type = 0; - IMFS_jnode_t *new_node; - int result; - char new_name[ IMFS_NAME_MAX + 1 ]; - IMFS_types_union info; + int rv = 0; + IMFS_jnode_types_t type; + IMFS_types_union info; + IMFS_jnode_t *new_node; - IMFS_get_token( token, strlen( token ), new_name, &result ); + get_type_and_info_by_mode_and_dev( mode, dev, &type, &info ); - /* - * 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 ); + new_node = IMFS_create_node( parentloc, type, name, namelen, mode, &info ); + if ( new_node != NULL ) { + IMFS_jnode_t *parent = parentloc->node_access; - /* - * 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( parent ); + IMFS_update_mtime( parent ); + } else { + rv = -1; + } - IMFS_update_ctime(new_node->Parent); - IMFS_update_mtime(new_node->Parent); - return 0; + return rv; } diff --git a/cpukit/libfs/src/imfs/imfs_mount.c b/cpukit/libfs/src/imfs/imfs_mount.c index 3ec16da3f7..243e5a0e30 100644 --- a/cpukit/libfs/src/imfs/imfs_mount.c +++ b/cpukit/libfs/src/imfs/imfs_mount.c @@ -1,16 +1,12 @@ /* * IMFS_mount * - * This routine will look at a mount table entry that we are going to - * add to the mount table. If the mount point rtems_filesystem - * location_info_t struct refers to a node that is a directory, - * the node will be marked as a mount point by setting its directory.mt_fs - * pointer to point to the mount table entry that we are about to add - * to the mount table chain. - * * 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. @@ -19,35 +15,27 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> - #include "imfs.h" -#include <rtems/libio_.h> -#include <rtems/seterr.h> -int IMFS_mount( - rtems_filesystem_mount_table_entry_t *mt_entry -) +int IMFS_mount( rtems_filesystem_mount_table_entry_t *mt_entry ) { - IMFS_jnode_t *node; - - node = mt_entry->mt_point_node.node_access; - - /* - * Is the node that we are mounting onto a directory node ? - */ - - if ( node->type != IMFS_DIRECTORY ) - rtems_set_errno_and_return_minus_one( ENOTDIR ); - - /* - * Set mt_fs pointer to point to the mount table entry for - * the mounted file system. - */ - - node->info.directory.mt_fs = mt_entry; - return 0; + int rv = 0; + IMFS_jnode_t *node = mt_entry->mt_point_node->location.node_access; + + if ( node->type == IMFS_DIRECTORY ) { + if ( node->info.directory.mt_fs == NULL ) { + node->info.directory.mt_fs = mt_entry; + } else { + errno = EBUSY; + rv = -1; + } + } else { + errno = ENOTDIR; + rv = -1; + } + + return rv; } diff --git a/cpukit/libfs/src/imfs/imfs_ntype.c b/cpukit/libfs/src/imfs/imfs_ntype.c index f80182b144..f399707c0c 100644 --- a/cpukit/libfs/src/imfs/imfs_ntype.c +++ b/cpukit/libfs/src/imfs/imfs_ntype.c @@ -7,6 +7,9 @@ * 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. @@ -15,18 +18,30 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> #include "imfs.h" rtems_filesystem_node_types_t IMFS_node_type( - rtems_filesystem_location_info_t *pathloc /* IN */ + const rtems_filesystem_location_info_t *loc ) { - IMFS_jnode_t *node; + const IMFS_jnode_t *node = loc->node_access; + IMFS_jnode_types_t imfs_type = node->type; + rtems_filesystem_node_types_t type; + + switch ( imfs_type ) { + case IMFS_HARD_LINK: + type = node->info.hard_link.link_node->type; + break; + case IMFS_LINEAR_FILE: + type = RTEMS_FILESYSTEM_MEMORY_FILE; + break; + default: + type = imfs_type; + break; + } - node = pathloc->node_access; - return node->type; + return type; } diff --git a/cpukit/libfs/src/imfs/imfs_readlink.c b/cpukit/libfs/src/imfs/imfs_readlink.c index b598fcf2c1..6786806abd 100644 --- a/cpukit/libfs/src/imfs/imfs_readlink.c +++ b/cpukit/libfs/src/imfs/imfs_readlink.c @@ -15,18 +15,15 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> #include "imfs.h" -#include <rtems/libio_.h> -#include <rtems/seterr.h> ssize_t IMFS_readlink( - rtems_filesystem_location_info_t *loc, - char *buf, /* OUT */ - size_t bufsize + const rtems_filesystem_location_info_t *loc, + char *buf, + size_t bufsize ) { IMFS_jnode_t *node; diff --git a/cpukit/libfs/src/imfs/imfs_rename.c b/cpukit/libfs/src/imfs/imfs_rename.c index 95c27fa9fd..855d026c36 100644 --- a/cpukit/libfs/src/imfs/imfs_rename.c +++ b/cpukit/libfs/src/imfs/imfs_rename.c @@ -15,40 +15,50 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> #include "imfs.h" -#include <rtems/libio_.h> -#include <rtems/seterr.h> int IMFS_rename( - rtems_filesystem_location_info_t *old_parent_loc, /* IN */ - rtems_filesystem_location_info_t *old_loc, /* IN */ - rtems_filesystem_location_info_t *new_parent_loc, /* IN */ - const char *new_name /* IN */ + const rtems_filesystem_location_info_t *oldparentloc, + const rtems_filesystem_location_info_t *oldloc, + const rtems_filesystem_location_info_t *newparentloc, + const char *name, + size_t namelen ) { - IMFS_jnode_t *the_jnode; - IMFS_jnode_t *new_parent; + int rv = 0; + IMFS_jnode_t *node = oldloc->node_access; + IMFS_jnode_t *new_parent = newparentloc->node_access; - the_jnode = old_loc->node_access; - - strncpy( the_jnode->name, new_name, IMFS_NAME_MAX ); + /* + * FIXME: Due to insufficient checks we can create inaccessible nodes with + * this operation. + */ - if ( the_jnode->Parent != NULL ) - rtems_chain_extract( (rtems_chain_node *) the_jnode ); + if ( node->Parent != NULL ) { + if ( namelen < IMFS_NAME_MAX ) { + memcpy( node->name, name, namelen ); + node->name [namelen] = '\0'; - new_parent = new_parent_loc->node_access; - the_jnode->Parent = new_parent; + rtems_chain_extract( &node->Node ); - rtems_chain_append( &new_parent->info.directory.Entries, &the_jnode->Node ); + node->Parent = new_parent; + rtems_chain_append( + &new_parent->info.directory.Entries, + &node->Node + ); - /* - * Update the time. - */ - IMFS_update_ctime( the_jnode ); + IMFS_update_ctime( node ); + } else { + errno = ENAMETOOLONG; + rv = -1; + } + } else { + errno = EINVAL; + rv = -1; + } - return 0; + return rv; } diff --git a/cpukit/libfs/src/imfs/imfs_rmnod.c b/cpukit/libfs/src/imfs/imfs_rmnod.c index 25c7cde084..c50041942f 100644 --- a/cpukit/libfs/src/imfs/imfs_rmnod.c +++ b/cpukit/libfs/src/imfs/imfs_rmnod.c @@ -7,6 +7,9 @@ * 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. @@ -15,17 +18,13 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <stdlib.h> - -#include <rtems.h> -#include <rtems/libio.h> -#include <rtems/libio_.h> - #include "imfs.h" +#include <stdlib.h> + void IMFS_create_orphan( IMFS_jnode_t *jnode ) { if ( jnode->Parent != NULL ) { @@ -40,10 +39,7 @@ void IMFS_create_orphan( IMFS_jnode_t *jnode ) void IMFS_check_node_remove( IMFS_jnode_t *jnode ) { - if ( !rtems_libio_is_file_open( jnode ) && jnode->st_nlink < 1 ) { - if ( rtems_filesystem_current.node_access == jnode ) - rtems_filesystem_current.node_access = NULL; - + if ( jnode->st_nlink < 1 ) { switch ( jnode->type ) { case IMFS_MEMORY_FILE: IMFS_memfile_remove( jnode ); @@ -59,19 +55,75 @@ void IMFS_check_node_remove( IMFS_jnode_t *jnode ) } } -/* - * IMFS_rmnod - */ +static int IMFS_rmnod_directory( + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *loc +) +{ + IMFS_jnode_t *node = loc->node_access; + int rv = 0; + + if ( !rtems_chain_is_empty( &node->info.directory.Entries ) ) { + errno = ENOTEMPTY; + rv = -1; + } else if ( + rtems_filesystem_location_is_root( loc ) + || node->info.directory.mt_fs != NULL + ) { + errno = EBUSY; + rv = -1; + } + + return rv; +} + +static int IMFS_rmnod_hard_link( + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *loc +) +{ + int rv = 0; + IMFS_jnode_t *node = loc->node_access; + IMFS_jnode_t *target = node->info.hard_link.link_node; + + if ( target->st_nlink == 1) { + rtems_filesystem_location_info_t target_loc = *loc; + + target_loc.node_access = target; + IMFS_Set_handlers( &target_loc ); + + rv = (*target_loc.ops->rmnod_h)( parentloc, &target_loc ); + } else { + --target->st_nlink; + IMFS_update_ctime( target ); + } + + return rv; +} int IMFS_rmnod( - rtems_filesystem_location_info_t *parent_pathloc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */ + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *loc ) { - IMFS_jnode_t *jnode = (IMFS_jnode_t *) pathloc->node_access; + int rv = 0; + IMFS_jnode_t *node = loc->node_access; - IMFS_create_orphan( jnode ); - IMFS_check_node_remove( jnode ); + switch ( node->type ) { + case IMFS_DIRECTORY: + rv = IMFS_rmnod_directory( parentloc, loc ); + break; + case IMFS_HARD_LINK: + rv = IMFS_rmnod_hard_link( parentloc, loc ); + break; + default: + break; + } + + if ( rv == 0 ) { + IMFS_create_orphan( node ); + IMFS_check_node_remove( node ); + } - return 0; + return rv; } diff --git a/cpukit/libfs/src/imfs/imfs_stat.c b/cpukit/libfs/src/imfs/imfs_stat.c index 5bc1eae579..66d1ca2ba9 100644 --- a/cpukit/libfs/src/imfs/imfs_stat.c +++ b/cpukit/libfs/src/imfs/imfs_stat.c @@ -6,6 +6,9 @@ * 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. @@ -14,31 +17,45 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> -#include <string.h> #include "imfs.h" -#include <rtems/libio_.h> -#include <rtems/seterr.h> + +#include <dirent.h> +#include <string.h> + +static size_t IMFS_directory_size( const IMFS_jnode_t *the_jnode ) +{ + size_t size = 0; + const rtems_chain_control *chain = &the_jnode->info.directory.Entries; + const rtems_chain_node *current = rtems_chain_immutable_first( chain ); + const rtems_chain_node *tail = rtems_chain_immutable_tail( chain ); + + while ( current != tail ) { + size += sizeof(struct dirent); + current = rtems_chain_immutable_next( current ); + } + + return size; +} int IMFS_stat( - rtems_filesystem_location_info_t *loc, - struct stat *buf + const rtems_filesystem_location_info_t *loc, + struct stat *buf ) { - IMFS_fs_info_t *fs_info; - IMFS_jnode_t *the_jnode; - IMFS_device_t *io; - - the_jnode = loc->node_access; + IMFS_fs_info_t *fs_info = loc->mt_entry->fs_info; + IMFS_jnode_t *the_jnode = loc->node_access; + IMFS_device_t *io = &the_jnode->info.device; + if ( the_jnode->type == IMFS_HARD_LINK ) { + the_jnode = the_jnode->info.hard_link.link_node; + } switch ( the_jnode->type ) { case IMFS_DEVICE: - io = &the_jnode->info.device; buf->st_rdev = rtems_filesystem_make_dev_t( io->major, io->minor ); break; @@ -47,12 +64,15 @@ int IMFS_stat( buf->st_size = the_jnode->info.file.size; break; + case IMFS_DIRECTORY: + buf->st_size = IMFS_directory_size( the_jnode ); + break; + case IMFS_SYM_LINK: buf->st_size = strlen( the_jnode->info.sym_link.name ); break; case IMFS_FIFO: - buf->st_size = 0; break; default: @@ -64,7 +84,6 @@ int IMFS_stat( * The device number of the IMFS is the major number and the minor is the * instance. */ - fs_info = loc->mt_entry->fs_info; buf->st_dev = rtems_filesystem_make_dev_t( IMFS_DEVICE_MAJOR_NUMBER, fs_info->instance ); @@ -78,7 +97,9 @@ int IMFS_stat( buf->st_mtime = the_jnode->stat_mtime; buf->st_ctime = the_jnode->stat_ctime; - buf->st_blksize = imfs_rq_memfile_bytes_per_block; + if ( the_jnode->type != IMFS_DIRECTORY ) { + buf->st_blksize = imfs_rq_memfile_bytes_per_block; + } return 0; } diff --git a/cpukit/libfs/src/imfs/imfs_symlink.c b/cpukit/libfs/src/imfs/imfs_symlink.c index 863ad23510..5a1d06ad19 100644 --- a/cpukit/libfs/src/imfs/imfs_symlink.c +++ b/cpukit/libfs/src/imfs/imfs_symlink.c @@ -16,54 +16,39 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> -#include <string.h> -#include <stdlib.h> #include "imfs.h" -#include <rtems/libio_.h> -#include <rtems/seterr.h> + +#include <stdlib.h> int IMFS_symlink( - rtems_filesystem_location_info_t *parent_loc, - const char *link_name, - const char *node_name + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + const char *target ) { 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); + info.sym_link.name = strdup(target); 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, + parentloc, IMFS_SYM_LINK, - new_name, + name, + namelen, ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )), &info ); diff --git a/cpukit/libfs/src/imfs/imfs_unlink.c b/cpukit/libfs/src/imfs/imfs_unlink.c deleted file mode 100644 index 0ec176ed03..0000000000 --- a/cpukit/libfs/src/imfs/imfs_unlink.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * IMFS_unlink - * - * Routine to remove a link node from the tree. - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * 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" -#endif - -#include <errno.h> -#include <stdlib.h> - -#include "imfs.h" -#include <rtems/libio_.h> -#include <rtems/seterr.h> - -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; -} diff --git a/cpukit/libfs/src/imfs/imfs_unmount.c b/cpukit/libfs/src/imfs/imfs_unmount.c index ee1482bfa5..47acec9320 100644 --- a/cpukit/libfs/src/imfs/imfs_unmount.c +++ b/cpukit/libfs/src/imfs/imfs_unmount.c @@ -1,17 +1,12 @@ /* * IMFS_unmount * - * This routine will look at a mount table entry that we are going to - * add to the mount table. If the mount point - * rtems_filesystem_location_info_t struct refers to a node that is a - * directory that has a file system mounted on it, the node will be - * marked as a mount point by * setting its directory.mt_fs pointer - * to NULL. This indicates that a directory is no longer mounted on - * this node. - * * 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. @@ -20,43 +15,27 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> - #include "imfs.h" -#include <rtems/libio_.h> -#include <rtems/seterr.h> -int IMFS_unmount( - rtems_filesystem_mount_table_entry_t *mt_entry -) +int IMFS_unmount( rtems_filesystem_mount_table_entry_t *mt_entry ) { - IMFS_jnode_t *node; - - node = mt_entry->mt_point_node.node_access; - - /* - * Is the node that we are mounting onto a directory node ? - */ - - if ( node->type != IMFS_DIRECTORY ) - rtems_set_errno_and_return_minus_one( ENOTDIR ); - - /* - * Did the node indicate that there was a directory mounted here? - */ - - if ( node->info.directory.mt_fs == NULL ) - rtems_set_errno_and_return_minus_one( EINVAL ); /* XXX */ - - /* - * Set the mt_fs pointer to indicate that there is no longer - * a file system mounted to this point. - */ - - node->info.directory.mt_fs = NULL; - - return 0; + int rv = 0; + IMFS_jnode_t *node = mt_entry->mt_point_node->location.node_access; + + if ( node->type == IMFS_DIRECTORY ) { + if ( node->info.directory.mt_fs == mt_entry ) { + node->info.directory.mt_fs = NULL; + } else { + errno = EINVAL; + rv = -1; + } + } else { + errno = ENOTDIR; + rv = -1; + } + + return rv; } diff --git a/cpukit/libfs/src/imfs/imfs_utime.c b/cpukit/libfs/src/imfs/imfs_utime.c index 2867e13ed6..b16af11b30 100644 --- a/cpukit/libfs/src/imfs/imfs_utime.c +++ b/cpukit/libfs/src/imfs/imfs_utime.c @@ -15,24 +15,22 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <errno.h> -#include <sys/time.h> - -#include <rtems/libio_.h> #include "imfs.h" +#include <sys/time.h> + int IMFS_utime( - rtems_filesystem_location_info_t *pathloc, /* IN */ - time_t actime, /* IN */ - time_t modtime /* IN */ + const rtems_filesystem_location_info_t *loc, + time_t actime, + time_t modtime ) { IMFS_jnode_t *the_jnode; - the_jnode = (IMFS_jnode_t *) pathloc->node_access; + the_jnode = (IMFS_jnode_t *) loc->node_access; the_jnode->stat_atime = actime; the_jnode->stat_mtime = modtime; diff --git a/cpukit/libfs/src/imfs/ioman.c b/cpukit/libfs/src/imfs/ioman.c index 0dce7e7239..c0dbee5d05 100644 --- a/cpukit/libfs/src/imfs/ioman.c +++ b/cpukit/libfs/src/imfs/ioman.c @@ -5,6 +5,9 @@ * 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. @@ -13,19 +16,13 @@ */ #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 <string.h> -#include <rtems.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -#include "imfs.h" /* * rtems_io_register_name @@ -52,42 +49,23 @@ rtems_status_code rtems_io_register_name( return RTEMS_SUCCESSFUL; } -/* - * rtems_io_lookup_name - * - * This version is reentrant. - * - * XXX - This is dependent upon IMFS and should not be. - * Suggest adding a filesystem routine to fill in the device_info. - */ - rtems_status_code rtems_io_lookup_name( const char *name, rtems_driver_name_t *device_info ) { - IMFS_jnode_t *the_jnode; - rtems_filesystem_location_info_t loc; - int result; - rtems_filesystem_node_types_t node_type; - - result = rtems_filesystem_evaluate_path( - name, strlen( name ), 0x00, &loc, true ); - the_jnode = loc.node_access; - - node_type = (*loc.ops->node_type_h)( &loc ); - - if ( (result != 0) || node_type != RTEMS_FILESYSTEM_DEVICE ) { - rtems_filesystem_freenode( &loc ); - return RTEMS_UNSATISFIED; + rtems_status_code sc = RTEMS_SUCCESSFUL; + struct stat st; + int rv = stat( name, &st ); + + if ( rv == 0 && S_ISCHR( st.st_mode ) ) { + device_info->device_name = name; + device_info->device_name_length = strlen( name ); + device_info->major = rtems_filesystem_dev_major_t( st.st_rdev ); + device_info->minor = rtems_filesystem_dev_minor_t( st.st_rdev ); + } else { + sc = RTEMS_UNSATISFIED; } - device_info->device_name = name; - device_info->device_name_length = strlen( name ); - device_info->major = the_jnode->info.device.major; - device_info->minor = the_jnode->info.device.minor; - - rtems_filesystem_freenode( &loc ); - - return RTEMS_SUCCESSFUL; + return sc; } diff --git a/cpukit/libfs/src/imfs/memfile.c b/cpukit/libfs/src/imfs/memfile.c index 35c1eee0ec..65810c0bca 100644 --- a/cpukit/libfs/src/imfs/memfile.c +++ b/cpukit/libfs/src/imfs/memfile.c @@ -18,18 +18,13 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif +#include "imfs.h" + #include <stdlib.h> #include <string.h> -#include <errno.h> - -#include <rtems.h> -#include <rtems/libio.h> -#include "imfs.h" -#include <rtems/libio_.h> -#include <rtems/seterr.h> #define MEMFILE_STATIC @@ -86,8 +81,8 @@ void memfile_free_block( int memfile_open( rtems_libio_t *iop, const char *pathname, - uint32_t flag, - uint32_t mode + int oflag, + mode_t mode ) { IMFS_jnode_t *the_jnode; diff --git a/cpukit/libfs/src/imfs/miniimfs_init.c b/cpukit/libfs/src/imfs/miniimfs_init.c index b43a5318e8..a4db968e3c 100644 --- a/cpukit/libfs/src/imfs/miniimfs_init.c +++ b/cpukit/libfs/src/imfs/miniimfs_init.c @@ -18,28 +18,29 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <rtems/libio_.h> - #include "imfs.h" static const rtems_filesystem_operations_table miniIMFS_ops = { - .evalpath_h = IMFS_eval_path, - .evalformake_h = IMFS_evaluate_for_make, + .lock_h = rtems_filesystem_default_lock, + .unlock_h = rtems_filesystem_default_unlock, + .eval_path_h = IMFS_eval_path, .link_h = rtems_filesystem_default_link, - .unlink_h = rtems_filesystem_default_unlink, + .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal, .node_type_h = IMFS_node_type, .mknod_h = IMFS_mknod, + .rmnod_h = IMFS_rmnod, + .fchmod_h = rtems_filesystem_default_fchmod, .chown_h = rtems_filesystem_default_chown, + .clonenod_h = rtems_filesystem_default_clonenode, .freenod_h = rtems_filesystem_default_freenode, .mount_h = IMFS_mount, .fsmount_me_h = miniIMFS_initialize, .unmount_h = rtems_filesystem_default_unmount, - .fsunmount_me_h = rtems_filesystem_default_unmount, + .fsunmount_me_h = rtems_filesystem_default_fsunmount, .utime_h = rtems_filesystem_default_utime, - .eval_link_h = rtems_filesystem_default_evaluate_link, .symlink_h = rtems_filesystem_default_symlink, .readlink_h = rtems_filesystem_default_readlink, .rename_h = rtems_filesystem_default_rename, @@ -54,8 +55,7 @@ int miniIMFS_initialize( return IMFS_initialize_support( mt_entry, &miniIMFS_ops, - &rtems_filesystem_handlers_default, /* for memfiles */ - &rtems_filesystem_handlers_default, /* for directories */ + &rtems_filesystem_handlers_default, /* for links */ &rtems_filesystem_handlers_default /* for fifos */ ); } diff --git a/cpukit/libfs/src/nfsclient/src/librtemsNfs.h b/cpukit/libfs/src/nfsclient/src/librtemsNfs.h index fc17d1de7f..4e8247ced0 100644 --- a/cpukit/libfs/src/nfsclient/src/librtemsNfs.h +++ b/cpukit/libfs/src/nfsclient/src/librtemsNfs.h @@ -123,7 +123,7 @@ rpcUdpCleanup(void); * Supply zero values to have the * driver chose reasonable defaults. */ -int +void nfsInit(int smallPoolDepth, int bigPoolDepth); /* Driver cleanup code diff --git a/cpukit/libfs/src/nfsclient/src/nfs.c b/cpukit/libfs/src/nfsclient/src/nfs.c index 80e757cbdf..ee1185367f 100644 --- a/cpukit/libfs/src/nfsclient/src/nfs.c +++ b/cpukit/libfs/src/nfsclient/src/nfs.c @@ -4,7 +4,12 @@ /* Author: Till Straumann <strauman@slac.stanford.edu> 2002 */ -/* Hacked on by others. */ +/* + * Hacked on by others. + * + * Modifications to support reference counting in the file system are + * Copyright (c) 2012 embedded brains GmbH. + */ /* * Authorship @@ -74,6 +79,7 @@ #include <mount_prot.h> #include "rpcio.h" +#include "librtemsNfs.h" /* Configurable parameters */ @@ -201,6 +207,21 @@ static struct timeval _nfscalltimeout = { 10, 0 }; /* {secs, us } */ #define UNLOCK(s) do { rtems_semaphore_release((s)); \ } while (0) +static inline char * +nfs_dupname(const char *name, size_t namelen) +{ + char *dupname = malloc(namelen + 1); + + if (dupname != NULL) { + memcpy(dupname, name, namelen); + dupname [namelen] = '\0'; + } else { + errno = ENOMEM; + } + + return dupname; +} + /***************************************** Types with Associated XDR Routines *****************************************/ @@ -214,12 +235,6 @@ typedef struct strbuf { u_int max; } strbuf; -static bool_t -xdr_strbuf(XDR *xdrs, strbuf *obj) -{ - return xdr_string(xdrs, &obj->buf, obj->max); -} - /* Read 'readlink' results into a 'strbuf'. * This is convenient as it avoids * one extra step of copying / lenght @@ -562,9 +577,9 @@ typedef struct NfsNodeRec_ { *****************************************/ static ssize_t nfs_readlink( - rtems_filesystem_location_info_t *loc, /* IN */ - char *buf, /* OUT */ - size_t len + const rtems_filesystem_location_info_t *loc, + char *buf, + size_t len ); static int updateAttr(NfsNode node, int force); @@ -591,10 +606,10 @@ static int updateAttr(NfsNode node, int force); static int nfs_sattr(NfsNode node, sattr *arg, u_long mask); -extern struct _rtems_filesystem_operations_table nfs_fs_ops; -static struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers; -static struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers; -static struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers; +extern const struct _rtems_filesystem_operations_table nfs_fs_ops; +static const struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers; +static const struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers; +static const struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers; static rtems_driver_address_table drvNfs; int @@ -603,64 +618,6 @@ nfsMountsShow(FILE*); rtems_status_code rtems_filesystem_resolve_location(char *buf, int len, rtems_filesystem_location_info_t *loc); - -/***************************************** - Inline Routines - *****************************************/ - - -/* * * * * * * * * * * * * * * * * * - Trivial Operations on a NfsNode - * * * * * * * * * * * * * * * * * */ - -/* determine if a location 'l' is an NFS root node */ -static inline int -locIsRoot(rtems_filesystem_location_info_t *l) -{ -NfsNode me = (NfsNode) l->node_access; -NfsNode r; - r = (NfsNode)l->mt_entry->mt_fs_root.node_access; - return SERP_ATTR(r).fileid == SERP_ATTR(me).fileid && - SERP_ATTR(r).fsid == SERP_ATTR(me).fsid; -} - -/* determine if a location 'l' is an NFS node */ -static inline int -locIsNfs(rtems_filesystem_location_info_t *l) -{ - return l->ops == &nfs_fs_ops; -} - -/* determine if two locations refer to the - * same entity. We know that 'nfsloc' is a - * location inside nfs. However, we needn't - * know anything about 'anyloc'. - */ -static inline int -locAreEqual( - rtems_filesystem_location_info_t *nfsloc, - rtems_filesystem_location_info_t *anyloc -) -{ -NfsNode na = (NfsNode) nfsloc->node_access; -NfsNode nb; - - if (!locIsNfs(anyloc)) - return 0; - - nb = (NfsNode) anyloc->node_access; - - if (na->nfs != nb->nfs) - return 0; - - updateAttr(nb, 0); - - return SERP_ATTR(na).fileid == SERP_ATTR(nb).fileid && - SERP_ATTR(na).fsid == SERP_ATTR(nb).fsid; -} - - - /***************************************** Global Variables *****************************************/ @@ -1326,409 +1283,229 @@ enum clnt_stat stat = RPC_FAILED; RTEMS File System Operations for NFS *****************************************/ -#if 0 /* for reference */ - -struct rtems_filesystem_location_info_tt -{ - void *node_access; - rtems_filesystem_file_handlers_r *handlers; - rtems_filesystem_operations_table *ops; - rtems_filesystem_mount_table_entry_t *mt_entry; -}; - -#endif - -/* - * Evaluate a path letting 'pathloc' travel along. - * - * The important semantics of this operation are: - * - * If this routine returns -1, the caller assumes - * pathloc to be _invalid_ and hence it will not - * invoke rtems_filesystem_freenode() on it. - * - * OTOH, if evalpath returns 0, - * rtems_filesystem_freenode() will eventually be - * called which results in our freeing the associated - * NfsNode attached to node_access. - * - * Therefore, this routine will _always_ allocate - * a NfsNode and pass it out to *pathloc (provided - * that the evaluation succeeds). - * - * However, if the evaluation finds that it has to - * step across FS boundaries (mount point or a symlink - * pointing outside), the NfsNode is destroyed - * before passing control to the new FS' evalpath_h() - * - */ - -union nfs_evalpath_arg { - int i; - const char **c; - }; - -STATIC int nfs_do_evalpath( - const char *pathname, /* IN */ - int pathnamelen, /* IN */ - union nfs_evalpath_arg *arg, - rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ - int forMake +static bool nfs_is_directory( + rtems_filesystem_eval_path_context_t *ctx, + void *arg ) { -char *del = 0, *part; -int e = 0; -NfsNode node = pathloc->node_access; -char *p = malloc(MAXPATHLEN+1); -Nfs nfs = (Nfs)pathloc->mt_entry->fs_info; -RpcUdpServer server = nfs->server; -unsigned long flags; -#if DEBUG & DEBUG_COUNT_NODES -unsigned long niu,siu; -#endif + bool is_dir = false; + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc(ctx); + NfsNode node = currentloc->node_access; + int force_update = 0; - if ( !p ) { - e = ENOMEM; - goto cleanup; + if (updateAttr(node, force_update) == 0) { + is_dir = SERP_ATTR(node).type == NFDIR; } - memset(p, 0, MAXPATHLEN+1); - memcpy(p, pathname, pathnamelen); - LOCK(nfsGlob.lock); - node = nfsNodeClone(node); - UNLOCK(nfsGlob.lock); - - /* from here on, the NFS is protected from being unmounted - * since the node refcount is > 1 - */ - - /* clone the node */ - if ( !node ) { - /* nodeClone sets errno */ - pathloc->node_access = 0; - if ( ! (e = errno) ) { - /* if we have no node, e must not be zero! */ - e = ENOMEM; - } - goto cleanup; - } - - pathloc->node_access = node; - - /* Special case: the RTEMS filesystem code - * may emit '..' on a regular file node to - * find the parent directory :-(. - * (eval.c: rtems_filesystem_evaluate_parent()) - * Try to catch this case here: - */ - if ( NFDIR != SERP_ATTR(node).type && '.'==*p && '.'==*(p+1) ) { - for ( part = p+2; '/'==*part; part++ ) - /* skip trailing '/' */; - if ( !*part ) { - /* this is it; back out dir and let them look up the dir itself... */ - memcpy( &SERP_FILE(node), - &node->args.dir, - sizeof(node->args.dir)); - *(p+1)=0; - } - } - - for (part=p; part && *part; part=del) { - - if ( NFLNK == SERP_ATTR(node).type ) { - /* follow midpath link */ - char *b = malloc(NFS_MAXPATHLEN+1); - int l; - - if (!b) { - e = ENOMEM; - goto cleanup; - } - if (nfs_readlink(pathloc, b, NFS_MAXPATHLEN+1)) { - free(b); - e = errno; - goto cleanup; - } - - /* prepend the link value to the rest of the path */ - if ( (l=strlen(b)) + strlen(part) + 1 > NFS_MAXPATHLEN ) { - free(b); - e = EINVAL; - goto cleanup; - } - /* swap string buffers and reset delimiter */ - b[l++] = DELIM; - strcpy(b+l,part); - part = b; - b = p; - p = del = part; - - free(b); - - /* back up the directory filehandle (only necessary - * if we don't back out to the root - */ - if (! (DELIM == *part) ) { - memcpy( &SERP_FILE(node), - &node->args.dir, - sizeof(node->args.dir)); - - if (updateAttr(node, 1 /* force */)) { - e = errno; - goto cleanup; - } - } - } + return is_dir; +} - /* find delimiter and eat /// sequences - * (only if we don't restart at the root) - */ - if ( DELIM != *part && (del = strchr(part, DELIM))) { - do { - *del++=0; - } while (DELIM==*del); - } +static NfsNode nfs_search_in_directory( + Nfs nfs, + NfsNode node, + char *part +) +{ + int rv; - /* refuse to backup over the root */ - if ( 0==strcmp(part,UPDIR) - && locAreEqual(pathloc, &rtems_filesystem_root) ) { - part++; - } + /* lookup one element */ + SERP_ARGS(node).diroparg.name = part; - /* cross mountpoint upwards */ - if ( (0==strcmp(part,UPDIR) && locIsRoot(pathloc)) /* cross mountpoint up */ - || DELIM == *part /* link starts at root */ - ) { - int rval; + /* remember args / directory fh */ + memcpy( &node->args, &SERP_FILE(node), sizeof(node->args)); #if DEBUG & DEBUG_EVALPATH - fprintf(stderr, - "Crossing mountpoint upwards\n"); + fprintf(stderr,"Looking up '%s'\n",part); #endif - if (DELIM == *part) { - *pathloc = rtems_filesystem_root; - } else { - *pathloc = pathloc->mt_entry->mt_point_node; - /* re-append the rest of the path */ - if (del) - while ( 0 == *--del ) - *del = DELIM; - } - - nfsNodeDestroy(node); - -#if DEBUG & DEBUG_EVALPATH - fprintf(stderr, - "Re-evaluating '%s'\n", - part); -#endif + rv = nfscall( + nfs->server, + NFSPROC_LOOKUP, + (xdrproc_t) xdr_diropargs, &SERP_FILE(node), + (xdrproc_t) xdr_serporid, &node->serporid + ); - if (forMake) - rval = pathloc->ops->evalformake_h(part, pathloc, arg->c); - else - rval = pathloc->ops->evalpath_h(part, strlen(part), arg->i, pathloc); + if (rv == 0 && node->serporid.status == NFS_OK) { + int force_update = 1; - free(p); - return rval; + rv = updateAttr(node, force_update); + if (rv != 0) { + node = NULL; } + } else { + node = NULL; + } - /* lookup one element */ - SERP_ARGS(node).diroparg.name = part; - - /* remember args / directory fh */ - memcpy( &node->args, &SERP_FILE(node), sizeof(node->args)); - - /* don't lookup the item we want to create */ - if ( forMake && (!del || !*del) ) - break; + return node; +} -#if DEBUG & DEBUG_EVALPATH - fprintf(stderr,"Looking up '%s'\n",part); -#endif +static void nfs_follow_link(rtems_filesystem_eval_path_context_t *ctx) +{ + const size_t len = NFS_MAXPATHLEN + 1; + char *link = malloc(len); - if ( nfscall(server, - NFSPROC_LOOKUP, - (xdrproc_t)xdr_diropargs, &SERP_FILE(node), - (xdrproc_t)xdr_serporid, &node->serporid) || - NFS_OK != (errno=node->serporid.status) ) { - e = errno; - goto cleanup; - } - node->age = nowSeconds(); + if (link != NULL) { + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc(ctx); + ssize_t rv = nfs_readlink(currentloc, link, len); -#if DEBUG & DEBUG_EVALPATH - if (NFLNK == SERP_ATTR(node).type && del) { - fprintf(stderr, - "Following midpath link '%s'\n", - part); + if (rv >= 0) { + rtems_filesystem_eval_path_recursive(ctx, link, (size_t) rv); + } else { + rtems_filesystem_eval_path_error(ctx, 0); } -#endif + free(link); + } else { + rtems_filesystem_eval_path_error(ctx, ENOMEM); } +} - if (forMake) { - /* remember the name - do this _before_ copying - * the name to local storage; the caller expects a - * pointer into pathloc - */ - assert( node->args.name ); - - *(arg->c) = pathname + (node->args.name - p);
- -#if 0 - /* restore the directory node */ +static bool nfs_update_currentloc( + rtems_filesystem_eval_path_context_t *ctx, + Nfs nfs, + NfsNode node +) +{ + bool ok = true; + rtems_filesystem_location_info_t *pathloc = + rtems_filesystem_eval_path_get_currentloc(ctx); - memcpy( &SERP_FILE(node), - &node->args.dir, - sizeof(node->args.dir)); + pathloc->node_access = node; - if ( (nfscall(nfs->server, - NFSPROC_GETATTR, - (xdrproc_t)xdr_nfs_fh, &SERP_FILE(node), - (xdrproc_t)xdr_attrstat, &node->serporid) && !errno && (errno = EIO)) || - (NFS_OK != (errno=node->serporid.status) ) ) { - goto cleanup; - } -#endif + switch (SERP_ATTR(node).type) { + case NFDIR: pathloc->handlers = &nfs_dir_file_handlers; break; + case NFREG: pathloc->handlers = &nfs_file_file_handlers; break; + case NFLNK: pathloc->handlers = &nfs_link_file_handlers; break; + default: pathloc->handlers = &rtems_filesystem_handlers_default; break; } - if (locIsRoot(pathloc)) { - - /* stupid filesystem code has no 'op' for comparing nodes - * but just compares the 'node_access' pointers. - * Luckily, this is only done for comparing the root nodes. - * Hence, we never give them a copy of the root but always - * the root itself. - */ - pathloc->node_access = pathloc->mt_entry->mt_fs_root.node_access; - /* increment the 'in use' counter since we return one more - * reference to the root node - */ - rtems_interrupt_disable(flags); - nfs->nodesInUse++; - rtems_interrupt_enable(flags); - nfsNodeDestroy(node); - - - } else { - switch (SERP_ATTR(node).type) { - case NFDIR: pathloc->handlers = &nfs_dir_file_handlers; break; - case NFREG: pathloc->handlers = &nfs_file_file_handlers; break; - case NFLNK: pathloc->handlers = &nfs_link_file_handlers; break; - default: pathloc->handlers = &rtems_filesystem_handlers_default; break; - } - pathloc->node_access = node; - - /* remember the name of this directory entry */ + /* remember the name of this directory entry */ - if (node->args.name) { - if (node->str) { + if (node->args.name) { + if (node->str) { #if DEBUG & DEBUG_COUNT_NODES - rtems_interrupt_disable(flags); - nfs->stringsInUse--; - rtems_interrupt_enable(flags); + rtems_interrupt_level flags; + rtems_interrupt_disable(flags); + nfs->stringsInUse--; + rtems_interrupt_enable(flags); #endif - free(node->str); - } - node->args.name = node->str = strdup(node->args.name); - if (!node->str) { - e = ENOMEM; - goto cleanup; - } - + free(node->str); + } + node->args.name = node->str = strdup(node->args.name); + if (node->str != NULL) { #if DEBUG & DEBUG_COUNT_NODES + rtems_interrupt_level flags; rtems_interrupt_disable(flags); nfs->stringsInUse++; rtems_interrupt_enable(flags); #endif + } else { + rtems_filesystem_eval_path_error(ctx, ENOMEM); + ok = false; } - } - node = 0; - e = 0; + return ok; +} -cleanup: - free(p); -#if DEBUG & DEBUG_COUNT_NODES - /* cache counters; nfs may be unmounted by other thread after the last - * node is destroyed - */ - niu = nfs->nodesInUse; - siu = nfs->stringsInUse; -#endif - if (node) { - nfsNodeDestroy(node); - pathloc->node_access = 0; - } -#if DEBUG & DEBUG_COUNT_NODES - fprintf(stderr, - "leaving evalpath, in use count is %i nodes, %i strings\n", - niu,siu); -#endif - if (e) { -#if DEBUG & DEBUG_EVALPATH - perror("Evalpath"); -#endif - rtems_set_errno_and_return_minus_one(e); +static rtems_filesystem_eval_path_generic_status nfs_eval_part( + rtems_filesystem_eval_path_context_t *ctx, + char *part +) +{ + 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); + Nfs nfs = currentloc->mt_entry->fs_info; + NfsNode dir = currentloc->node_access; + NfsNode entry = nfs_search_in_directory(nfs, dir, part); + + if (entry != NULL) { + rtems_filesystem_eval_path_clear_token(ctx); + + if (nfs_update_currentloc(ctx, nfs, entry)) { + int eval_flags = rtems_filesystem_eval_path_get_flags(ctx); + bool follow_sym_link = (eval_flags & RTEMS_LIBIO_FOLLOW_SYM_LINK) != 0; + bool terminal = !rtems_filesystem_eval_path_has_path( ctx ); + + if (SERP_ATTR(entry).type == NFLNK && (follow_sym_link || !terminal)) { + nfs_follow_link(ctx); + } else if (!terminal) { + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; + } + } } else { - return 0; + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY; } + + return status; } -/* MANDATORY; may set errno=ENOSYS and return -1 */ -static int nfs_evalformake( - const char *path, /* IN */ - rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ - const char **pname /* OUT */ +static rtems_filesystem_eval_path_generic_status nfs_eval_token( + rtems_filesystem_eval_path_context_t *ctx, + void *arg, + const char *token, + size_t tokenlen ) { - union nfs_evalpath_arg args; - args.c = pname; - - return nfs_do_evalpath(path, strlen(path), &args, pathloc, 1 /*forMake*/); + rtems_filesystem_eval_path_generic_status status = + RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE; + + if (rtems_filesystem_is_current_directory(token, tokenlen)) { + rtems_filesystem_eval_path_clear_token(ctx); + if (rtems_filesystem_eval_path_has_path(ctx)) { + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; + } + } else { + char *part = nfs_dupname(token, tokenlen); + + if (part != NULL) { + status = nfs_eval_part(ctx, part); + free(part); + } else { + rtems_filesystem_eval_path_error(ctx, ENOMEM); + } + } + + return status; } -static int nfs_evalpath( - const char *path, /* IN */ - size_t pathlen, /* IN */ - int flags, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN/OUT */ -) +static const rtems_filesystem_eval_path_generic_config nfs_eval_config = { + .is_directory = nfs_is_directory, + .eval_token = nfs_eval_token +}; + +static void nfs_eval_path(rtems_filesystem_eval_path_context_t *ctx) { - union nfs_evalpath_arg args; - args.i = flags; - return nfs_do_evalpath(path, pathlen, &args, pathloc, 0 /*not forMake*/); + rtems_filesystem_eval_path_generic(ctx, NULL, &nfs_eval_config); } - /* create a hard link */ static int nfs_link( - rtems_filesystem_location_info_t *to_loc, /* IN */ - rtems_filesystem_location_info_t *parent_loc, /* IN */ - const char *name /* IN */ + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *targetloc, + const char *name, + size_t namelen ) { +int rv = 0; NfsNode pNode; nfsstat status; -NfsNode tNode = to_loc->node_access; +NfsNode tNode = targetloc->node_access; +char *dupname; + + dupname = nfs_dupname(name, namelen); + if (dupname == NULL) + return -1; #if DEBUG & DEBUG_SYSCALLS - fprintf(stderr,"Creating link '%s'\n",name); + fprintf(stderr,"Creating link '%s'\n",dupname); #endif - if ( !locIsNfs(parent_loc) ) { - errno = EXDEV; - return -1; - } - - pNode = parent_loc->node_access; - if ( tNode->nfs != pNode->nfs ) { - errno = EXDEV; - return -1; - } memcpy(&SERP_ARGS(tNode).linkarg.to.dir, &SERP_FILE(pNode), sizeof(SERP_FILE(pNode))); @@ -1744,16 +1521,18 @@ NfsNode tNode = to_loc->node_access; #if DEBUG & DEBUG_SYSCALLS perror("nfs_link"); #endif - return -1; + rv = -1; } - return 0; + free(dupname); + + return rv; } static int nfs_do_unlink( - rtems_filesystem_location_info_t *parent_loc,/* IN */ - rtems_filesystem_location_info_t *loc, /* IN */ + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *loc, int proc ) { @@ -1791,18 +1570,10 @@ char *name = NFSPROC_REMOVE == proc ? return 0; } -static int nfs_unlink( - rtems_filesystem_location_info_t *parent_loc, /* IN */ - rtems_filesystem_location_info_t *loc /* IN */ -) -{ - return nfs_do_unlink(parent_loc, loc, NFSPROC_REMOVE); -} - static int nfs_chown( - rtems_filesystem_location_info_t *pathloc, /* IN */ - uid_t owner, /* IN */ - gid_t group /* IN */ + const rtems_filesystem_location_info_t *pathloc, /* IN */ + uid_t owner, /* IN */ + gid_t group /* IN */ ) { sattr arg; @@ -1814,14 +1585,27 @@ sattr arg; } +static int nfs_clonenode(rtems_filesystem_location_info_t *loc) +{ + NfsNode node = loc->node_access; + + LOCK(nfsGlob.lock); + node = nfsNodeClone(node); + UNLOCK(nfsGlob.lock); + + loc->node_access = node; + + return node != NULL ? 0 : -1; +} + /* Cleanup the FS private info attached to pathloc->node_access */ -static int nfs_freenode( - rtems_filesystem_location_info_t *pathloc /* IN */ +static void nfs_freenode( + const rtems_filesystem_location_info_t *pathloc /* IN */ ) { +#if DEBUG & DEBUG_COUNT_NODES Nfs nfs = ((NfsNode)pathloc->node_access)->nfs; -#if DEBUG & DEBUG_COUNT_NODES /* print counts at entry where they are > 0 so 'nfs' is safe from being destroyed * and there's no race condition */ @@ -1831,22 +1615,7 @@ Nfs nfs = ((NfsNode)pathloc->node_access)->nfs; nfs->stringsInUse); #endif - /* never destroy the root node; it is released by the unmount - * code - */ - if (locIsRoot(pathloc)) { - unsigned long flags; - /* just adjust the references to the root node but - * don't really release it - */ - rtems_interrupt_disable(flags); - nfs->nodesInUse--; - rtems_interrupt_enable(flags); - } else { - nfsNodeDestroy(pathloc->node_access); - pathloc->node_access = 0; - } - return 0; + nfsNodeDestroy(pathloc->node_access); } /* NOTE/TODO: mounting on top of NFS is not currently supported @@ -1982,12 +1751,12 @@ char *path = mt_entry->dev; /* looks good so far */ - mt_entry->mt_fs_root.node_access = rootNode; + mt_entry->mt_fs_root->location.node_access = rootNode; rootNode = 0; - mt_entry->mt_fs_root.ops = &nfs_fs_ops; - mt_entry->mt_fs_root.handlers = &nfs_dir_file_handlers; + mt_entry->mt_fs_root->location.ops = &nfs_fs_ops; + mt_entry->mt_fs_root->location.handlers = &nfs_dir_file_handlers; mt_entry->pathconf_limits_and_options = nfs_limits_and_options; LOCK(nfsGlob.llock); @@ -2016,7 +1785,7 @@ cleanup: } /* This op is called when they try to unmount THIS fs */ -STATIC int nfs_fsunmount_me( +STATIC void nfs_fsunmount_me( rtems_filesystem_mount_table_entry_t *mt_entry /* in */ ) { @@ -2035,7 +1804,8 @@ LOCK(nfsGlob.llock); fprintf(stderr, "Refuse to unmount; there are still %i nodes in use (1 used by us)\n", nodesInUse); - rtems_set_errno_and_return_minus_one(EBUSY); + rtems_fatal_error_occurred(0xdeadbeef); + return; } status = buildIpAddr(&uid, &gid, 0, &saddr, &path); @@ -2052,20 +1822,17 @@ LOCK(nfsGlob.llock); if (stat) { UNLOCK(nfsGlob.llock); fprintf(stderr,"NFS UMOUNT -- %s\n", clnt_sperrno(stat)); - errno = EIO; - return -1; + return; } - nfsNodeDestroy(mt_entry->mt_fs_root.node_access); - mt_entry->mt_fs_root.node_access = 0; + nfsNodeDestroy(mt_entry->mt_fs_root->location.node_access); + mt_entry->mt_fs_root->location.node_access = 0; nfsDestroy(mt_entry->fs_info); mt_entry->fs_info = 0; nfsGlob.num_mounted_fs--; UNLOCK(nfsGlob.llock); - - return 0; } /* OPTIONAL; may be NULL - BUT: CAUTION; mount() doesn't check @@ -2073,10 +1840,10 @@ UNLOCK(nfsGlob.llock); * //NOTE: (10/25/2002) patch submitted and probably applied */ static rtems_filesystem_node_types_t nfs_node_type( - rtems_filesystem_location_info_t *pathloc /* in */ + const rtems_filesystem_location_info_t *loc ) { -NfsNode node = pathloc->node_access; +NfsNode node = loc->node_access; if (updateAttr(node, 0 /* only if old */)) return -1; @@ -2104,28 +1871,35 @@ NfsNode node = pathloc->node_access; } static int nfs_mknod( - const char *path, /* IN */ - mode_t mode, /* IN */ - dev_t dev, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN/OUT */ + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev ) { +int rv = 0; struct timeval now; diropres res; -NfsNode node = pathloc->node_access; +NfsNode node = parentloc->node_access; mode_t type = S_IFMT & mode; +char *dupname; if (type != S_IFDIR && type != S_IFREG) rtems_set_errno_and_return_minus_one(ENOTSUP); + dupname = nfs_dupname(name, namelen); + if (dupname == NULL) + return -1; + #if DEBUG & DEBUG_SYSCALLS - fprintf(stderr,"nfs_mknod: creating %s\n", path); + fprintf(stderr,"nfs_mknod: creating %s\n", dupname); #endif rtems_clock_get_tod_timeval(&now); - SERP_ARGS(node).createarg.name = (filename)path; + SERP_ARGS(node).createarg.name = dupname; SERP_ARGS(node).createarg.attributes.mode = mode; /* TODO: either use our uid or use the Nfs credentials */ SERP_ARGS(node).createarg.attributes.uid = 0; @@ -2144,16 +1918,40 @@ mode_t type = S_IFMT & mode; #if DEBUG & DEBUG_SYSCALLS perror("nfs_mknod"); #endif - return -1; + rv = -1; } - return 0; + free(dupname); + + return rv; +} + +static int nfs_rmnod( + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *loc +) +{ + int rv = 0; + NfsNode node = loc->node_access; + int force_update = 0; + + if (updateAttr(node, force_update) == 0) { + int proc = SERP_ATTR(node).type == NFDIR + ? NFSPROC_RMDIR + : NFSPROC_REMOVE; + + rv = nfs_do_unlink(parentloc, loc, proc); + } else { + rv = -1; + } + + return rv; } static int nfs_utime( - rtems_filesystem_location_info_t *pathloc, /* IN */ - time_t actime, /* IN */ - time_t modtime /* IN */ + const rtems_filesystem_location_info_t *pathloc, /* IN */ + time_t actime, /* IN */ + time_t modtime /* IN */ ) { sattr arg; @@ -2168,24 +1966,30 @@ sattr arg; } static int nfs_symlink( - rtems_filesystem_location_info_t *loc, /* IN */ - const char *link_name, /* IN */ - const char *node_name + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + const char *target ) { +int rv = 0; struct timeval now; nfsstat status; -NfsNode node = loc->node_access; +NfsNode node = parentloc->node_access; +char *dupname; + dupname = nfs_dupname(name, namelen); + if (dupname == NULL) + return -1; #if DEBUG & DEBUG_SYSCALLS - fprintf(stderr,"nfs_symlink: creating %s -> %s\n", link_name, node_name); + fprintf(stderr,"nfs_symlink: creating %s -> %s\n", dupname, target); #endif rtems_clock_get_tod_timeval(&now); - SERP_ARGS(node).symlinkarg.name = (filename)link_name; - SERP_ARGS(node).symlinkarg.to = (nfspath) node_name; + SERP_ARGS(node).symlinkarg.name = dupname; + SERP_ARGS(node).symlinkarg.to = (nfspath) target; SERP_ARGS(node).symlinkarg.attributes.mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; /* TODO */ @@ -2205,243 +2009,103 @@ NfsNode node = loc->node_access; #if DEBUG & DEBUG_SYSCALLS perror("nfs_symlink"); #endif - return -1; + rv = -1; } - return 0; + free(dupname); + + return rv; } -static int nfs_do_readlink( - rtems_filesystem_location_info_t *loc, /* IN */ - strbuf *psbuf /* IN/OUT */ +static ssize_t nfs_readlink( + const rtems_filesystem_location_info_t *loc, + char *buf, + size_t len ) { -NfsNode node = loc->node_access; -Nfs nfs = node->nfs; -readlinkres_strbuf rr; -int wasAlloced; -int rval; - - rr.strbuf = *psbuf; + NfsNode node = loc->node_access; + Nfs nfs = node->nfs; + readlinkres_strbuf rr; - wasAlloced = (0 == psbuf->buf); + rr.strbuf.buf = buf; + rr.strbuf.max = len - 1; - if ( (rval = nfscall(nfs->server, + if ( nfscall(nfs->server, NFSPROC_READLINK, (xdrproc_t)xdr_nfs_fh, &SERP_FILE(node), - (xdrproc_t)xdr_readlinkres_strbuf, &rr)) ) { - if (wasAlloced) - xdr_free( (xdrproc_t)xdr_strbuf, (caddr_t)&rr.strbuf ); - } - - - if (NFS_OK != rr.status) { - if (wasAlloced) - xdr_free( (xdrproc_t)xdr_strbuf, (caddr_t)&rr.strbuf ); - rtems_set_errno_and_return_minus_one(rr.status); + (xdrproc_t)xdr_readlinkres_strbuf, &rr) + || (NFS_OK != (errno = rr.status)) ) { +#if DEBUG & DEBUG_SYSCALLS + perror("nfs_readlink"); +#endif + return -1; } - *psbuf = rr.strbuf; - - return 0; + return (ssize_t) strlen(rr.strbuf.buf); } -static ssize_t nfs_readlink( - rtems_filesystem_location_info_t *loc, /* IN */ - char *buf, /* OUT */ - size_t len -) +static void nfs_lock(rtems_filesystem_mount_table_entry_t *mt_entry) { -strbuf sbuf; - sbuf.buf = buf; - sbuf.max = len; - - return nfs_do_readlink(loc, &sbuf); } -/* The semantics of this routine are: - * - * The caller submits a valid pathloc, i.e. it has - * an NfsNode attached to node_access. - * On return, pathloc points to the target node which - * may or may not be an NFS node. - * Hence, the original NFS node is released in either - * case: - * - link evaluation fails; pathloc points to no valid node - * - link evaluation success; pathloc points to a new valid - * node. If it's an NFS node, a new NfsNode will be attached - * to node_access... - */ - -#define LINKVAL_BUFLEN (MAXPATHLEN+1) -#define RVAL_ERR_BUT_DONT_FREENODE (-1) -#define RVAL_ERR_AND_DO_FREENODE ( 1) -#define RVAL_OK ( 0) +static void nfs_unlock(rtems_filesystem_mount_table_entry_t *mt_entry) +{ +} -static int nfs_eval_link( - rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ - int flags /* IN */ +static bool nfs_are_nodes_equal( + const rtems_filesystem_location_info_t *a, + const rtems_filesystem_location_info_t *b ) { -rtems_filesystem_node_types_t type; -char *buf = malloc(LINKVAL_BUFLEN); -int rval = RVAL_ERR_AND_DO_FREENODE; + bool equal = false; + NfsNode na = a->node_access; - if (!buf) { - errno = ENOMEM; - goto cleanup; - } - - /* in this loop, we must not use NFS specific ops as we might - * step out of our FS during the process... - * This algorithm should actually be performed by the - * generic's evaluate_path routine :-( - * - * Unfortunately, there is no way of finding the - * directory node who contains 'pathloc', however :-( - */ - do { - /* assume the generics have verified 'pathloc' to be - * a link... - */ - if ( !pathloc->ops->readlink_h ) { - errno = ENOTSUP; - goto cleanup; - } - - if ( pathloc->ops->readlink_h(pathloc, buf, LINKVAL_BUFLEN) ) { - goto cleanup; - } - -#if DEBUG & DEBUG_EVALPATH - fprintf(stderr, "link value is '%s'\n", buf); -#endif - - /* is the link value an absolute path ? */ - if ( DELIM != *buf ) { - /* NO; a relative path */ - - /* we must backup to the link's directory - we - * know only how to do that for NFS, however. - * In this special case, we can avoid recursion. - * Otherwise (i.e. if the link is on another FS), - * we must step into its eval_link_h(). - */ - if (locIsNfs(pathloc)) { - NfsNode node = pathloc->node_access; - int err; - - memcpy( &SERP_FILE(node), - &node->args.dir, - sizeof(node->args.dir) ); - - if (updateAttr(node, 1 /* force */)) - goto cleanup; - - if (SERP_ATTR(node).type != NFDIR) { - errno = ENOTDIR; - goto cleanup; - } - - pathloc->handlers = &nfs_dir_file_handlers; - - err = nfs_evalpath(buf, strlen(buf), flags, pathloc); - - /* according to its semantics, - * nfs_evalpath cloned the node attached - * to pathloc. Hence we have to - * release the old one (referring to - * the link; the new clone has been - * updated and refers to the link _value_). - */ - nfsNodeDestroy(node); - - if (err) { - /* nfs_evalpath has set errno; - * pathloc->node_access has no - * valid node attached in this case - */ - rval = RVAL_ERR_BUT_DONT_FREENODE; - goto cleanup; - } - - } else { - if ( ! pathloc->ops->eval_link_h ) { - errno = ENOTSUP; - goto cleanup; - } - if (!pathloc->ops->eval_link_h(pathloc, flags)) { - /* FS is responsible for freeing its pathloc->node_access - * if necessary - */ - rval = RVAL_ERR_BUT_DONT_FREENODE; - goto cleanup; - } - } - } else { - /* link points to an absolute path '/xxx' */ - - /* release this node; filesystem_evaluate_path() will - * lookup a new one. - */ - rtems_filesystem_freenode(pathloc); - - if (rtems_filesystem_evaluate_path(buf, strlen(buf), flags, pathloc, 1)) { - /* If evalpath fails then there is no valid node - * attached to pathloc; hence we must not attempt - * to free the node - */ - rval = RVAL_ERR_BUT_DONT_FREENODE; - goto cleanup; - } - } + if (updateAttr(na, 0) == 0) { + NfsNode nb = b->node_access; - if ( !pathloc->ops->node_type_h ) { - errno = ENOTSUP; - goto cleanup; + if (updateAttr(nb, 0) == 0) { + equal = SERP_ATTR(na).fileid == SERP_ATTR(nb).fileid + && SERP_ATTR(na).fsid == SERP_ATTR(nb).fsid; } - - type = pathloc->ops->node_type_h(pathloc); - - - /* I dont know what to do about hard links */ - } while ( RTEMS_FILESYSTEM_SYM_LINK == type ); - - rval = RVAL_OK; - -cleanup: - - free(buf); - - if (RVAL_ERR_AND_DO_FREENODE == rval) { - rtems_filesystem_freenode(pathloc); - return -1; } - return rval; + return equal; } +static int nfs_fchmod( + const rtems_filesystem_location_info_t *loc, + mode_t mode +) +{ +sattr arg; + + arg.mode = mode; + return nfs_sattr(loc->node_access, &arg, SATTR_MODE); -struct _rtems_filesystem_operations_table nfs_fs_ops = { - nfs_evalpath, /* MANDATORY */ - nfs_evalformake, /* MANDATORY; may set errno=ENOSYS and return -1 */ - nfs_link, /* OPTIONAL; may be defaulted */ - nfs_unlink, /* OPTIONAL; may be defaulted */ - nfs_node_type, /* OPTIONAL; may be defaulted; BUG in mount - no test!! */ - nfs_mknod, /* OPTIONAL; may be defaulted */ - nfs_chown, /* OPTIONAL; may be defaulted */ - nfs_freenode, /* OPTIONAL; may be defaulted; (release node_access) */ - rtems_filesystem_default_mount, - rtems_nfs_initialize, /* OPTIONAL; may be defaulted -- not used anymore */ - rtems_filesystem_default_unmount, - nfs_fsunmount_me, /* OPTIONAL; may be defaulted */ - nfs_utime, /* OPTIONAL; may be defaulted */ - nfs_eval_link, /* OPTIONAL; may be defaulted */ - nfs_symlink, /* OPTIONAL; may be defaulted */ - nfs_readlink, /* OPTIONAL; may be defaulted */ - rtems_filesystem_default_rename, /* OPTIONAL; may be defaulted */ - rtems_filesystem_default_statvfs /* OPTIONAL; may be defaulted */ +} +const struct _rtems_filesystem_operations_table nfs_fs_ops = { + .lock_h = nfs_lock, + .unlock_h = nfs_unlock, + .eval_path_h = nfs_eval_path, + .link_h = nfs_link, + .are_nodes_equal_h = nfs_are_nodes_equal, + .node_type_h = nfs_node_type, + .mknod_h = nfs_mknod, + .rmnod_h = nfs_rmnod, + .fchmod_h = nfs_fchmod, + .chown_h = nfs_chown, + .clonenod_h = nfs_clonenode, + .freenod_h = nfs_freenode, + .mount_h = rtems_filesystem_default_mount, + .fsmount_me_h = rtems_nfs_initialize, + .unmount_h = rtems_filesystem_default_unmount, + .fsunmount_me_h = nfs_fsunmount_me, + .utime_h = nfs_utime, + .symlink_h = nfs_symlink, + .readlink_h = nfs_readlink, + .rename_h = rtems_filesystem_default_rename, + .statvfs_h = rtems_filesystem_default_statvfs }; /***************************************** @@ -2472,8 +2136,8 @@ struct _rtems_filesystem_operations_table nfs_fs_ops = { static int nfs_file_open( rtems_libio_t *iop, const char *pathname, - uint32_t flag, - uint32_t mode + int oflag, + mode_t mode ) { return 0; @@ -2487,8 +2151,8 @@ static int nfs_file_open( static int nfs_dir_open( rtems_libio_t *iop, const char *pathname, - uint32_t flag, - uint32_t mode + int oflag, + mode_t mode ) { NfsNode node = iop->pathinfo.node_access; @@ -2796,8 +2460,8 @@ struct stat /* common for file/dir/link */ static int nfs_fstat( - rtems_filesystem_location_info_t *loc, - struct stat *buf + const rtems_filesystem_location_info_t *loc, + struct stat *buf ) { NfsNode node = loc->node_access; @@ -2939,20 +2603,6 @@ u_int mode; return 0; } - -/* common for file/dir/link */ -static int nfs_fchmod( - rtems_filesystem_location_info_t *loc, - mode_t mode -) -{ -sattr arg; - - arg.mode = mode; - return nfs_sattr(loc->node_access, &arg, SATTR_MODE); - -} - /* just set the size attribute to 'length' * the server will take care of the rest :-) */ @@ -2973,71 +2623,52 @@ sattr arg; SATTR_SIZE); } -/* files and symlinks are removed - * by the common nfs_unlink() routine. - * NFS has a different NFSPROC_RMDIR - * call, though... - */ -static int nfs_dir_rmnod( - rtems_filesystem_location_info_t *parentpathloc, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN */ -) -{ - return nfs_do_unlink(parentpathloc, pathloc, NFSPROC_RMDIR); -} - /* the file handlers table */ -static +static const struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers = { - nfs_file_open, /* OPTIONAL; may be defaulted */ - nfs_file_close, /* OPTIONAL; may be defaulted */ - nfs_file_read, /* OPTIONAL; may be defaulted */ - nfs_file_write, /* OPTIONAL; may be defaulted */ - rtems_filesystem_default_ioctl, - nfs_file_lseek, /* OPTIONAL; may be defaulted */ - nfs_fstat, /* OPTIONAL; may be defaulted */ - nfs_fchmod, /* OPTIONAL; may be defaulted */ - nfs_file_ftruncate, /* OPTIONAL; may be defaulted */ - rtems_filesystem_default_fsync, - rtems_filesystem_default_fdatasync, - rtems_filesystem_default_fcntl, - nfs_unlink, /* OPTIONAL; may be defaulted */ + .open_h = nfs_file_open, + .close_h = nfs_file_close, + .read_h = nfs_file_read, + .write_h = nfs_file_write, + .ioctl_h = rtems_filesystem_default_ioctl, + .lseek_h = nfs_file_lseek, + .fstat_h = nfs_fstat, + .ftruncate_h = nfs_file_ftruncate, + .fsync_h = rtems_filesystem_default_fsync, + .fdatasync_h = rtems_filesystem_default_fdatasync, + .fcntl_h = rtems_filesystem_default_fcntl }; /* the directory handlers table */ -static +static const struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers = { - nfs_dir_open, /* OPTIONAL; may be defaulted */ - nfs_dir_close, /* OPTIONAL; may be defaulted */ - nfs_dir_read, /* OPTIONAL; may be defaulted */ - rtems_filesystem_default_write, - rtems_filesystem_default_ioctl, - nfs_dir_lseek, /* OPTIONAL; may be defaulted */ - nfs_fstat, /* OPTIONAL; may be defaulted */ - nfs_fchmod, /* OPTIONAL; may be defaulted */ - rtems_filesystem_default_ftruncate, - rtems_filesystem_default_fsync, - rtems_filesystem_default_fdatasync, - rtems_filesystem_default_fcntl, - nfs_dir_rmnod, /* OPTIONAL; may be defaulted */ + .open_h = nfs_dir_open, + .close_h = nfs_dir_close, + .read_h = nfs_dir_read, + .write_h = rtems_filesystem_default_write, + .ioctl_h = rtems_filesystem_default_ioctl, + .lseek_h = nfs_dir_lseek, + .fstat_h = nfs_fstat, + .ftruncate_h = rtems_filesystem_default_ftruncate_directory, + .fsync_h = rtems_filesystem_default_fsync, + .fdatasync_h = rtems_filesystem_default_fdatasync, + .fcntl_h = rtems_filesystem_default_fcntl }; /* the link handlers table */ -static +static const struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers = { - rtems_filesystem_default_open, - rtems_filesystem_default_close, - rtems_filesystem_default_read, - rtems_filesystem_default_write, - rtems_filesystem_default_ioctl, - rtems_filesystem_default_lseek, - nfs_fstat, /* OPTIONAL; may be defaulted */ - nfs_fchmod, /* OPTIONAL; may be defaulted */ - rtems_filesystem_default_ftruncate, - rtems_filesystem_default_fsync, - rtems_filesystem_default_fdatasync, - rtems_filesystem_default_fcntl, - nfs_unlink, /* OPTIONAL; may be defaulted */ + .open_h = rtems_filesystem_default_open, + .close_h = rtems_filesystem_default_close, + .read_h = rtems_filesystem_default_read, + .write_h = rtems_filesystem_default_write, + .ioctl_h = rtems_filesystem_default_ioctl, + .lseek_h = rtems_filesystem_default_lseek, + .fstat_h = nfs_fstat, + .ftruncate_h = rtems_filesystem_default_ftruncate, + .fsync_h = rtems_filesystem_default_fsync, + .fdatasync_h = rtems_filesystem_default_fdatasync, + .fcntl_h = rtems_filesystem_default_fcntl }; /* we need a dummy driver entry table to get a @@ -3096,7 +2727,7 @@ Nfs nfs; for (nfs = nfsGlob.mounted_fs; nfs; nfs=nfs->next) { fprintf(f,"%s on ", nfs->mt_entry->dev); - if (rtems_filesystem_resolve_location(mntpt, MAXPATHLEN, &nfs->mt_entry->mt_fs_root)) + if (rtems_filesystem_resolve_location(mntpt, MAXPATHLEN, &nfs->mt_entry->mt_fs_root->location)) fprintf(f,"<UNABLE TO LOOKUP MOUNTPOINT>\n"); else fprintf(f,"%s\n",mntpt); @@ -3236,15 +2867,15 @@ rtems_filesystem_location_info_t old; /* IMPORTANT: let the helper task have its own libio environment (i.e. cwd) */ if (RTEMS_SUCCESSFUL == (rpa->status = rtems_libio_set_private_env())) { - old = rtems_filesystem_current; + old = rtems_filesystem_current->location; - rtems_filesystem_current = *(rpa->loc); + rtems_filesystem_current->location = *(rpa->loc); if ( !getcwd(rpa->buf, rpa->len) ) rpa->status = RTEMS_UNSATISFIED; /* must restore the cwd because 'freenode' will be called on it */ - rtems_filesystem_current = old; + rtems_filesystem_current->location = old; } rtems_semaphore_release(rpa->sync); rtems_task_delete(RTEMS_SELF); diff --git a/cpukit/libfs/src/rfs/rtems-rfs-dir.h b/cpukit/libfs/src/rfs/rtems-rfs-dir.h index 6bbe6d6e18..3b8e7c4f06 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-dir.h +++ b/cpukit/libfs/src/rfs/rtems-rfs-dir.h @@ -29,47 +29,6 @@ #include <rtems/rfs/rtems-rfs-inode.h> /** - * The current directory string as held in directory lists. - */ -#define RTEMS_RFS_CURRENT_DIR_STR "." - -/** - * The size of the current directory. - */ -#define RTEMS_RFS_CURRENT_DIR_SIZE (1) - -/** - * Test if the path provided is a current directory. - * - * @param _p Pointer to the path string. - * @return bool True if the path is a current directory. - */ -#define rtems_rfs_current_dir(_p) \ - ((_p[0] == RTEMS_RFS_CURRENT_DIR_STR[0]) && \ - ((_p[1] == '\0') || rtems_filesystem_is_separator (_p[1]))) - -/** - * The parent directory string as held in directory lists. - */ -#define RTEMS_RFS_PARENT_DIR_STR ".." - -/** - * The size of the parent directory. - */ -#define RTEMS_RFS_PARENT_DIR_SIZE (2) - -/** - * Test if the path provided is a parent directory. - * - * @param _p Pointer to the path string. - * @return bool True if the path is a parent directory. - */ -#define rtems_rfs_parent_dir(_p) \ - ((_p[0] == RTEMS_RFS_PARENT_DIR_STR[0]) && \ - (_p[1] == RTEMS_RFS_PARENT_DIR_STR[1]) && \ - ((_p[2] == '\0') || rtems_filesystem_is_separator (_p[2]))) - -/** * Define the offsets of the fields of a directory entry. */ #define RTEMS_RFS_DIR_ENTRY_INO (0) /**< The ino offset in a directory diff --git a/cpukit/libfs/src/rfs/rtems-rfs-file.c b/cpukit/libfs/src/rfs/rtems-rfs-file.c index d8a7335ea4..abd123da1b 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-file.c +++ b/cpukit/libfs/src/rfs/rtems-rfs-file.c @@ -31,7 +31,7 @@ int rtems_rfs_file_open (rtems_rfs_file_system* fs, rtems_rfs_ino ino, - uint32_t flags, + int oflag, rtems_rfs_file_handle** file) { rtems_rfs_file_handle* handle; @@ -132,7 +132,7 @@ rtems_rfs_file_open (rtems_rfs_file_system* fs, printf ("rtems-rfs: file-open: ino=%" PRId32 " share created\n", ino); } - handle->flags = flags; + handle->flags = oflag; handle->shared = shared; *file = handle; diff --git a/cpukit/libfs/src/rfs/rtems-rfs-file.h b/cpukit/libfs/src/rfs/rtems-rfs-file.h index 284e6273d8..ecadb359bc 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-file.h +++ b/cpukit/libfs/src/rfs/rtems-rfs-file.h @@ -180,7 +180,7 @@ typedef struct _rtems_rfs_file_handle /** * Special flags that can be controlled by the fctrl call. */ - uint32_t flags; + int flags; /** * The buffer of data at the file's position. @@ -298,7 +298,7 @@ typedef struct _rtems_rfs_file_handle */ int rtems_rfs_file_open (rtems_rfs_file_system* fs, rtems_rfs_ino ino, - uint32_t flags, + int oflag, rtems_rfs_file_handle** handle); /** diff --git a/cpukit/libfs/src/rfs/rtems-rfs-link.c b/cpukit/libfs/src/rfs/rtems-rfs-link.c index 392a7520d6..2dcdf8a67a 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-link.c +++ b/cpukit/libfs/src/rfs/rtems-rfs-link.c @@ -385,8 +385,7 @@ rtems_rfs_symlink_read (rtems_rfs_file_system* fs, if (size < *length) { - rtems_rfs_inode_close (fs, &inode); - return EINVAL; + *length = size; } if (rtems_rfs_inode_get_block_count (&inode) == 0) @@ -450,8 +449,6 @@ rtems_rfs_symlink_read (rtems_rfs_file_system* fs, } } - path[*length] = '\0'; - rc = rtems_rfs_inode_close (fs, &inode); return rc; diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c index d5a5a3fcf7..9ca829e168 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c +++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c @@ -38,8 +38,8 @@ static int rtems_rfs_rtems_device_open ( rtems_libio_t *iop, const char *pathname, - uint32_t flag, - uint32_t mode) + int oflag, + mode_t mode) { rtems_libio_open_close_args_t args; rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo); @@ -257,10 +257,8 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_device_handlers = { .ioctl_h = rtems_rfs_rtems_device_ioctl, .lseek_h = rtems_rfs_rtems_device_lseek, .fstat_h = rtems_rfs_rtems_fstat, - .fchmod_h = rtems_rfs_rtems_fchmod, .ftruncate_h = rtems_rfs_rtems_device_ftruncate, .fsync_h = rtems_filesystem_default_fsync, .fdatasync_h = rtems_filesystem_default_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, - .rmnod_h = rtems_rfs_rtems_rmnod + .fcntl_h = rtems_filesystem_default_fcntl }; diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c index 8f9b363336..77eeeba9fa 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c +++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c @@ -36,18 +36,12 @@ * This rountine will verify that the node being opened as a directory is in * fact a directory node. If it is then the offset into the directory will be * set to 0 to position to the first directory entry. - * - * @param iop - * @param pathname - * @param flag - * @param mode - * @@return int */ static int rtems_rfs_rtems_dir_open (rtems_libio_t* iop, const char* pathname, - uint32_t flag, - uint32_t mode) + int oflag, + mode_t mode) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo); rtems_rfs_ino ino = rtems_rfs_rtems_get_iop_ino (iop); @@ -193,36 +187,6 @@ rtems_rfs_rtems_dir_lseek (rtems_libio_t* iop, return 0; } -static int -rtems_rfs_rtems_dir_rmnod (rtems_filesystem_location_info_t* parent_pathloc, - rtems_filesystem_location_info_t* pathloc) -{ - rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); - rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_pathloc); - rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); - uint32_t doff = rtems_rfs_rtems_get_pathloc_doff (pathloc); - int rc; - - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_DIR_RMNOD)) - printf ("rtems-rfs: dir-rmnod: parent:%" PRId32 " doff:%" PRIu32 ", ino:%" PRId32 "\n", - parent, doff, ino); - - if (ino == RTEMS_RFS_ROOT_INO) - return rtems_rfs_rtems_error ("dir_rmnod: root inode", EBUSY); - - rtems_rfs_rtems_lock (fs); - - rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_if_empty); - if (rc) - { - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("dir_rmnod: unlinking", rc); - } - - rtems_rfs_rtems_unlock (fs); - return 0; -} - /* * Set of operations handlers for operations on directories. */ @@ -235,10 +199,8 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_dir_handlers = { .ioctl_h = rtems_filesystem_default_ioctl, .lseek_h = rtems_rfs_rtems_dir_lseek, .fstat_h = rtems_rfs_rtems_fstat, - .fchmod_h = rtems_rfs_rtems_fchmod, - .ftruncate_h = rtems_filesystem_default_ftruncate, + .ftruncate_h = rtems_filesystem_default_ftruncate_directory, .fsync_h = rtems_filesystem_default_fsync, .fdatasync_h = rtems_rfs_rtems_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, - .rmnod_h = rtems_rfs_rtems_dir_rmnod + .fcntl_h = rtems_filesystem_default_fcntl }; diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c index 346ae54ff5..0a15652dfc 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c +++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c @@ -38,30 +38,24 @@ /** * This routine processes the open() system call. Note that there is nothing * special to be done at open() time. - * - * @param iop - * @param pathname - * @param flag - * @param mode - * @return int */ static int rtems_rfs_rtems_file_open (rtems_libio_t* iop, const char* pathname, - uint32_t flag, - uint32_t mode) + int oflag, + mode_t mode) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo); rtems_rfs_ino ino; rtems_rfs_file_handle* file; - uint32_t flags; + int flags; int rc; flags = 0; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN)) - printf("rtems-rfs: file-open: path:%s ino:%" PRId32 " flags:%04" PRIx32 " mode:%04" PRIx32 "\n", + printf("rtems-rfs: file-open: path:%s ino:%" PRId32 " flags:%04i mode:%04" PRIu32 "\n", pathname, ino, flags, mode); rtems_rfs_rtems_lock (fs); @@ -352,10 +346,8 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_file_handlers = { .ioctl_h = rtems_rfs_rtems_file_ioctl, .lseek_h = rtems_rfs_rtems_file_lseek, .fstat_h = rtems_rfs_rtems_fstat, - .fchmod_h = rtems_rfs_rtems_fchmod, .ftruncate_h = rtems_rfs_rtems_file_ftruncate, .fsync_h = rtems_rfs_rtems_fdatasync, .fdatasync_h = rtems_rfs_rtems_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, - .rmnod_h = rtems_rfs_rtems_rmnod + .fcntl_h = rtems_filesystem_default_fcntl }; diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-utils.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-utils.c index 44c8885bbe..e77ffddaf8 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-utils.c +++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-utils.c @@ -25,60 +25,6 @@ #include "rtems-rfs-rtems.h" -bool -rtems_rfs_rtems_eval_perms (rtems_rfs_inode_handle* inode, int flags) -{ - uid_t st_uid; - gid_t st_gid; - uint16_t uid; - uint16_t gid; - uint16_t mode; - int flags_to_test; - - uid = rtems_rfs_inode_get_uid (inode); - gid = rtems_rfs_inode_get_gid (inode); - mode = rtems_rfs_inode_get_mode (inode); - -#if defined (RTEMS_POSIX_API) - st_uid = geteuid (); - st_gid = getegid (); -#else - st_uid = uid; - st_gid = gid; -#endif - - /* - * Check if I am owner or a group member or someone else. - */ - flags_to_test = flags; - - if ((st_uid == 0) || (st_uid == uid)) - flags_to_test |= flags << 6; - if ((st_uid == 0) || (st_gid == gid)) - flags_to_test |= flags << 3; - else - /* must be other - already set above */; - - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PERMS)) - printf ("rtems-rfs: eval-perms: uid=%d gid=%d iuid=%d igid=%d " \ - "flags=%o flags_to_test=%o mode=%o (%o)\n", - st_uid, st_gid, uid, gid, - flags, flags_to_test, mode & 0777, - flags_to_test & (mode & 0777)); - - /* - * If all of the flags are set we have permission - * to do this. - */ - if ((flags_to_test & (mode & 0777)) != 0) - return true; - - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PERMS)) - printf("rtems-rfs: eval-perms: perms failed\n"); - - return false; -} - /* * The following sets the handlers based on the type of inode. */ diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems.c index 7c92a09a3c..e6006a8970 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-rtems.c +++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems.c @@ -1,6 +1,9 @@ /* * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> * + * 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. @@ -35,522 +38,245 @@ #include <rtems/rfs/rtems-rfs-link.h> #include "rtems-rfs-rtems.h" -/** - * The libio permissions for read/execute. - */ -#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ) -/** - * The libio permissions for write/execute. - */ -#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE) - -/** - * Evaluate the path to a node that wishes to be accessed. The pathloc is - * returned with the ino to the node to be accessed. - * - * The routine starts from the root stripping away any leading path separators - * breaking the path up into the node names and checking an inode exists for - * that node name. Permissions are checked to insure access to the node is - * allowed. A path to a node must be accessable all the way even if the end - * result is directly accessable. As a user on Linux try "ls /root/../tmp" and - * you will see if fails. - * - * The whole process is complicated by crossmount paths where we head down into - * this file system only to return to the top and out to a another mounted file - * system. For example we are mounted on '/e' and the user enters "ls - * /e/a/b/../../dev". We need to head down then back up. - * - * @param path - * @param pathlen - * @param flags - * @param pathloc - */ -static int -rtems_rfs_rtems_eval_path (const char* path, - size_t pathlen, - int flags, - rtems_filesystem_location_info_t* pathloc) +static bool +rtems_rfs_rtems_eval_perms (rtems_filesystem_eval_path_context_t *ctx, + int eval_flags, + rtems_rfs_inode_handle* inode) { - rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); - rtems_rfs_inode_handle inode; - rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); - uint32_t doff = 0; - const char* node; - size_t node_len; - int stripped; - int rc; - - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH)) - printf ("rtems-rfs-rtems: eval-path: in: path:%s pathlen:%zi ino:%" PRId32 "\n", - path, pathlen, ino); + return rtems_filesystem_eval_path_check_access( + ctx, + eval_flags, + rtems_rfs_inode_get_mode (inode), + rtems_rfs_inode_get_uid (inode), + rtems_rfs_inode_get_gid (inode) + ); +} +static rtems_filesystem_node_types_t +rtems_rfs_rtems_node_type_by_inode (rtems_rfs_inode_handle* inode) +{ /* - * Eat any separators at the start of the path. + * Do not return RTEMS_FILESYSTEM_HARD_LINK because this would result in an + * eval link which does not make sense in the case of the RFS file + * system. All directory entries are links to an inode. A link such as a HARD + * link is actually the normal path to a regular file, directory, device + * etc's inode. Links to inodes can be considered "the real" one, yet they + * are all links. */ - stripped = rtems_filesystem_prefix_separators (path, pathlen); - path += stripped; - pathlen -= stripped; - - rtems_rfs_rtems_lock (fs); - - while (true) - { - /* - * Open and load the inode. - */ - rc = rtems_rfs_inode_open (fs, ino, &inode, true); - if (rc > 0) - { - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_path: opening inode", rc); - } - - /* - * Is this the end of the pathname we were given ? - */ - if ((*path == '\0') || (pathlen == 0)) - break; - - /* - * If a directory the execute bit must be set for us to enter. - */ - if (RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)) && - !rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_SEARCH)) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_path: eval perms", EACCES); - } - - /* - * Extract the node name we will look for this time around. - */ - node = path; - node_len = 0; - while (!rtems_filesystem_is_separator (*path) && - (*path != '\0') && pathlen && - ((node_len + 1) < rtems_rfs_fs_max_name (fs))) - { - path++; - pathlen--; - node_len++; - } - - /* - * Eat any separators at the start of the path. - */ - stripped = rtems_filesystem_prefix_separators (path, pathlen); - path += stripped; - pathlen -= stripped; - node_len += stripped; - - /* - * If the node is the current directory and there is more path to come move - * on to it otherwise we are at the inode we want. - */ - if (rtems_rfs_current_dir (node)) - { - if (*path) - { - rtems_rfs_inode_close (fs, &inode); - continue; - } - break; - } - - /* - * If the node is a parent we must move up one directory. If the location - * is on another file system we have a crossmount so we call that file - * system to handle the remainder of the path. - */ - if (rtems_rfs_parent_dir (node)) - { - /* - * If we are at the root inode of the file system we have a crossmount - * path. - */ - if (ino == RTEMS_RFS_ROOT_INO) - { - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH)) - printf("rtems-rfs-rtems: eval-path: crossmount: path:%s (%zd)\n", - path - node_len, pathlen + node_len); - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - *pathloc = pathloc->mt_entry->mt_point_node; - return (*pathloc->ops->evalpath_h)(path - node_len, pathlen + node_len, - flags, pathloc); - } - - /* - * We need to find the parent of this node. - */ - rc = rtems_rfs_dir_lookup_ino (fs, &inode, - RTEMS_RFS_PARENT_DIR_STR, - RTEMS_RFS_PARENT_DIR_SIZE, &ino, &doff); - if (rc > 0) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_path: read parent inode", rc); - } - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH)) - printf("rtems-rfs-rtems: eval-path: parent: ino:%" PRId32 "\n", ino); - } - else - { - /* - * Look up the node name in this directory. If found drop through, close - * the current inode and let the loop open the inode so the mode can be - * read and handlers set. - */ - rc = rtems_rfs_dir_lookup_ino (fs, &inode, - node, node_len - stripped, &ino, &doff); - if (rc > 0) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return ((errno = rc) == 0) ? 0 : -1; - } - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH)) - printf("rtems-rfs-rtems: eval-path: down: path:%s ino:%" PRId32 "\n", node, ino); - } + uint16_t mode = rtems_rfs_inode_get_mode (inode); + if (RTEMS_RFS_S_ISDIR (mode)) + return RTEMS_FILESYSTEM_DIRECTORY; + else if (RTEMS_RFS_S_ISLNK (mode)) + return RTEMS_FILESYSTEM_SYM_LINK; + else if (RTEMS_RFS_S_ISBLK (mode) || RTEMS_RFS_S_ISCHR (mode)) + return RTEMS_FILESYSTEM_DEVICE; + else + return RTEMS_FILESYSTEM_MEMORY_FILE; +} - rc = rtems_rfs_inode_close (fs, &inode); - if (rc > 0) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_path: closing node", rc); - } - } +static void +rtems_rfs_rtems_lock_by_mt_entry (rtems_filesystem_mount_table_entry_t *mt_entry) +{ + rtems_rfs_file_system* fs = mt_entry->fs_info; - rtems_rfs_rtems_set_pathloc_ino (pathloc, ino); - rtems_rfs_rtems_set_pathloc_doff (pathloc, doff); + rtems_rfs_rtems_lock (fs); +} - rc = rtems_rfs_rtems_set_handlers (pathloc, &inode) ? 0 : EIO; +static void +rtems_rfs_rtems_unlock_by_mt_entry (rtems_filesystem_mount_table_entry_t *mt_entry) +{ + rtems_rfs_file_system* fs = mt_entry->fs_info; - rtems_rfs_inode_close (fs, &inode); rtems_rfs_rtems_unlock (fs); - - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH)) - printf("rtems-rfs-rtems: eval-path: ino:%" PRId32 "\n", ino); - - return rc; } -/** - * The following routine evaluates a path for a new node to be created. The - * pathloc is returned with a pointer to the parent of the new node. The name - * is returned with a pointer to the first character in the new node name. The - * parent node is verified to be a directory. - * - * @param path - * @param pathloc - * @param name - * @return int - */ -static int -rtems_rfs_rtems_eval_for_make (const char* path, - rtems_filesystem_location_info_t* pathloc, - const char** name) +static bool +rtems_rfs_rtems_is_directory( + rtems_filesystem_eval_path_context_t *ctx, + void *arg +) { - rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); - rtems_rfs_inode_handle inode; - rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); - rtems_rfs_ino node_ino; - uint32_t doff = 0; - const char* node; - int node_len; - int stripped; - int rc; + rtems_rfs_inode_handle* inode = arg; - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE)) - printf ("rtems-rfs-rtems: eval-for-make: path:%s ino:%" PRId32 "\n", path, ino); - - *name = path + strlen (path); - - while (*name != path) - { - (*name)--; - if (rtems_filesystem_is_separator (**name)) - { - (*name)++; - break; - } - } - - /* - * Eat any separators at start of the path. - */ - stripped = rtems_filesystem_prefix_separators (path, strlen(path)); - path += stripped; - - rtems_rfs_rtems_lock (fs); - - while (true) - { - /* - * Open and load the inode. - */ - rc = rtems_rfs_inode_open (fs, ino, &inode, true); - if (rc > 0) - { - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: read ino", rc); - } + return rtems_rfs_rtems_node_type_by_inode (inode) + == RTEMS_FILESYSTEM_DIRECTORY; +} - /* - * If a directory the execute bit must be set for us to enter. - */ - if (RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)) && - !rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_SEARCH)) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: eval perms", EACCES); - } +static void rtems_rfs_rtems_follow_link( + rtems_filesystem_eval_path_context_t* ctx, + rtems_rfs_file_system* fs, + rtems_rfs_ino ino +) +{ + size_t len = MAXPATHLEN; + char *link = malloc(len + 1); - /* - * Is this the end of the pathname we were given ? - */ - if (path == *name) - break; - - /* - * Extract the node name we will look for this time around. - */ - node = path; - node_len = 0; - while (!rtems_filesystem_is_separator(*path) && - (*path != '\0') && - (node_len < (rtems_rfs_fs_max_name (fs) - 1))) - { - node_len++; - path++; - } + if (link != NULL) { + int rc = rtems_rfs_symlink_read (fs, ino, link, len, &len); - /* - * Eat any separators at start of the new path. - */ - stripped = rtems_filesystem_prefix_separators (path, strlen (path)); - path += stripped; - node_len += stripped; - - /* - * If the node is the current directory and there is more path to come move - * on to it otherwise we are at the inode we want. - */ - if (rtems_rfs_current_dir (node)) - { - if (*path) - { - rtems_rfs_inode_close (fs, &inode); - continue; - } - break; + if (rc == 0) { + rtems_filesystem_eval_path_recursive (ctx, link, len); + } else { + rtems_filesystem_eval_path_error (ctx, 0); } - /* - * If the node is a parent we must move up one directory. If the location - * is on another file system we have a crossmount so we call that file - * system to handle the remainder of the path. - */ - if (rtems_rfs_parent_dir (path)) - { - /* - * If we are at the root inode of the file system we have a crossmount - * path. - */ - if (ino == RTEMS_RFS_ROOT_INO) - { - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE)) - printf("rtems-rfs-rtems: eval-for-make: crossmount: path:%s\n", - path - node_len); - - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - *pathloc = pathloc->mt_entry->mt_point_node; - return (*pathloc->ops->evalformake_h)(path + 2, pathloc, name); - } + free(link); + } else { + rtems_filesystem_eval_path_error (ctx, ENOMEM); + } +} - /* - * If not a directory give and up return. We cannot change dir from a - * regular file or device node. - */ - if (!RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode))) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: not dir", ENOTSUP); +static rtems_filesystem_eval_path_generic_status +rtems_rfs_rtems_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_rfs_inode_handle* inode = arg; + bool access_ok = rtems_rfs_rtems_eval_perms (ctx, RTEMS_LIBIO_PERMS_SEARCH, inode); + + if (access_ok) { + if (rtems_filesystem_is_current_directory (token, tokenlen)) { + rtems_filesystem_eval_path_clear_token (ctx); + } else { + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc( ctx ); + rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (currentloc); + rtems_rfs_ino entry_ino; + uint32_t entry_doff; + int rc = rtems_rfs_dir_lookup_ino ( + fs, + inode, + token, + tokenlen, + &entry_ino, + &entry_doff + ); + + if (rc == 0) { + rc = rtems_rfs_inode_close (fs, inode); + if (rc == 0) { + rc = rtems_rfs_inode_open (fs, entry_ino, inode, true); + } + + if (rc != 0) { + /* + * This prevents the rtems_rfs_inode_close() from doing something in + * rtems_rfs_rtems_eval_path(). + */ + memset (inode, 0, sizeof(*inode)); + } + } else { + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY; + rc = -1; } - /* - * We need to find the parent of this node. - */ - rc = rtems_rfs_dir_lookup_ino (fs, &inode, - RTEMS_RFS_PARENT_DIR_STR, - RTEMS_RFS_PARENT_DIR_SIZE, &ino, &doff); - if (rc > 0) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: read parent inode", rc); - } - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE)) - printf ("rtems-rfs-rtems: eval-for-make: parent: ino:%" PRId32 "\n", ino); - } - else - { - /* - * Read the inode so we know it exists and what type it is. - */ - rc = rtems_rfs_dir_lookup_ino (fs, &inode, - node, node_len - stripped, &ino, &doff); - if (rc > 0) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: reading inode", rc); + if (rc == 0) { + bool is_sym_link = rtems_rfs_rtems_node_type_by_inode (inode) + == RTEMS_FILESYSTEM_SYM_LINK; + int eval_flags = rtems_filesystem_eval_path_get_flags (ctx); + bool follow_sym_link = (eval_flags & RTEMS_LIBIO_FOLLOW_SYM_LINK) != 0; + bool terminal = !rtems_filesystem_eval_path_has_path (ctx); + + rtems_filesystem_eval_path_clear_token (ctx); + + if (is_sym_link && (follow_sym_link || !terminal)) { + rtems_rfs_rtems_follow_link (ctx, fs, entry_ino); + } else { + rc = rtems_rfs_rtems_set_handlers (currentloc, inode) ? 0 : EIO; + if (rc == 0) { + rtems_rfs_rtems_set_pathloc_ino (currentloc, entry_ino); + rtems_rfs_rtems_set_pathloc_doff (currentloc, entry_doff); + + if (!terminal) { + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; + } + } else { + rtems_filesystem_eval_path_error ( + ctx, + rtems_rfs_rtems_error ("eval_path: set handlers", rc) + ); + } + } } - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE)) - printf("rtems-rfs-rtems: eval-for-make: down: path:%s ino:%" PRId32 "\n", - node, ino); - } - - rc = rtems_rfs_inode_close (fs, &inode); - if (rc > 0) - { - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: closing node", rc); } } - if (!RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode))) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: not dir", ENOTDIR); - } + return status; +} - if (!rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_WX)) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: cannot write", EACCES); - } +static const rtems_filesystem_eval_path_generic_config +rtems_rfs_rtems_eval_config = { + .is_directory = rtems_rfs_rtems_is_directory, + .eval_token = rtems_rfs_rtems_eval_token +}; - /* - * Make sure the name does not already exists in the directory. - */ - rc = rtems_rfs_dir_lookup_ino (fs, &inode, *name, strlen (*name), - &node_ino, &doff); - if (rc == 0) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: found name", EEXIST); - } +static void +rtems_rfs_rtems_eval_path (rtems_filesystem_eval_path_context_t *ctx) +{ + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc (ctx); + rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (currentloc); + rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (currentloc); + rtems_rfs_inode_handle inode; + int rc; - if (rc != ENOENT) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: look up", rc); + rc = rtems_rfs_inode_open (fs, ino, &inode, true); + if (rc == 0) { + rtems_filesystem_eval_path_generic ( + ctx, + &inode, + &rtems_rfs_rtems_eval_config + ); + rc = rtems_rfs_inode_close (fs, &inode); + if (rc != 0) { + rtems_filesystem_eval_path_error ( + ctx, + rtems_rfs_rtems_error ("eval_path: closing inode", rc) + ); + } + } else { + rtems_filesystem_eval_path_error ( + ctx, + rtems_rfs_rtems_error ("eval_path: opening inode", rc) + ); } - - /* - * Set the parent ino in the path location. - */ - - rtems_rfs_rtems_set_pathloc_ino (pathloc, ino); - rtems_rfs_rtems_set_pathloc_doff (pathloc, doff); - - rc = rtems_rfs_rtems_set_handlers (pathloc, &inode) ? 0 : EIO; - - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE)) - printf("rtems-rfs-rtems: eval-for-make: parent ino:%" PRId32 " name:%s\n", - ino, *name); - - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - - return rc; } /** * The following rouine creates a new link node under parent with the name - * given in name. The link node is set to point to the node at to_loc. - * - * @param to_loc - * @param parent_loc - * @param name - * @return int + * given in name. The link node is set to point to the node at targetloc. */ static int -rtems_rfs_rtems_link (rtems_filesystem_location_info_t* to_loc, - rtems_filesystem_location_info_t* parent_loc, - const char* name) +rtems_rfs_rtems_link (const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *targetloc, + const char *name, + size_t namelen) { - rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (to_loc); - rtems_rfs_ino target = rtems_rfs_rtems_get_pathloc_ino (to_loc); - rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc); + rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (targetloc); + rtems_rfs_ino target = rtems_rfs_rtems_get_pathloc_ino (targetloc); + rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parentloc); int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_LINK)) printf ("rtems-rfs-rtems: link: in: parent:%" PRId32 " target:%" PRId32 "\n", parent, target); - rtems_rfs_rtems_lock (fs); - - rc = rtems_rfs_link (fs, name, strlen (name), parent, target, false); + rc = rtems_rfs_link (fs, name, namelen, parent, target, false); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("link: linking", rc); } - rtems_rfs_rtems_unlock (fs); return 0; } /** - * Routine to remove a link node from the file system. - * - * @param parent_loc - * @param loc - * @return int - */ - -static int -rtems_rfs_rtems_unlink (rtems_filesystem_location_info_t* parent_loc, - rtems_filesystem_location_info_t* loc) -{ - rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parent_loc); - rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc); - rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (loc); - uint32_t doff = rtems_rfs_rtems_get_pathloc_doff (loc); - int rc; - - rtems_rfs_rtems_lock (fs); - - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_UNLINK)) - printf("rtems-rfs-rtems: unlink: parent:%" PRId32 " doff:%" PRIu32 " ino:%" PRId32 "\n", - parent, doff, ino); - - rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_denied); - if (rc) - { - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("unlink: unlink inode", rc); - } - - rtems_rfs_rtems_unlock (fs); - - return 0; -} - -/** * The following verifies that and returns the type of node that the loc refers * to. * @@ -559,51 +285,28 @@ rtems_rfs_rtems_unlink (rtems_filesystem_location_info_t* parent_loc, */ static rtems_filesystem_node_types_t -rtems_rfs_rtems_node_type (rtems_filesystem_location_info_t* pathloc) +rtems_rfs_rtems_node_type (const rtems_filesystem_location_info_t* pathloc) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); rtems_filesystem_node_types_t type; rtems_rfs_inode_handle inode; - uint16_t mode; int rc; - rtems_rfs_rtems_lock (fs); - rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("node_type: opening inode", rc); } - /* - * Do not return RTEMS_FILESYSTEM_HARD_LINK because this would result in an - * eval link which does not make sense in the case of the RFS file - * system. All directory entries are links to an inode. A link such as a HARD - * link is actually the normal path to a regular file, directory, device - * etc's inode. Links to inodes can be considered "the real" one, yet they - * are all links. - */ - mode = rtems_rfs_inode_get_mode (&inode); - if (RTEMS_RFS_S_ISDIR (mode)) - type = RTEMS_FILESYSTEM_DIRECTORY; - else if (RTEMS_RFS_S_ISLNK (mode)) - type = RTEMS_FILESYSTEM_SYM_LINK; - else if (RTEMS_RFS_S_ISBLK (mode) || RTEMS_RFS_S_ISCHR (mode)) - type = RTEMS_FILESYSTEM_DEVICE; - else - type = RTEMS_FILESYSTEM_MEMORY_FILE; + type = rtems_rfs_rtems_node_type_by_inode (&inode); rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("node_type: closing inode", rc); } - rtems_rfs_rtems_unlock (fs); - return type; } @@ -618,9 +321,9 @@ rtems_rfs_rtems_node_type (rtems_filesystem_location_info_t* pathloc) */ static int -rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc, - uid_t owner, - gid_t group) +rtems_rfs_rtems_chown (const rtems_filesystem_location_info_t *pathloc, + uid_t owner, + gid_t group) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); @@ -634,12 +337,9 @@ rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc, printf ("rtems-rfs-rtems: chown: in: ino:%" PRId32 " uid:%d gid:%d\n", ino, owner, group); - rtems_rfs_rtems_lock (fs); - rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("chown: opening inode", rc); } @@ -653,7 +353,6 @@ rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc, if ((uid != rtems_rfs_inode_get_uid (&inode)) && (uid != 0)) { rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("chown: not able", EPERM); } #endif @@ -663,12 +362,9 @@ rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc, rc = rtems_rfs_inode_close (fs, &inode); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("chown: closing inode", rc); } - rtems_rfs_rtems_unlock (fs); - return 0; } @@ -683,21 +379,18 @@ rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc, */ static int -rtems_rfs_rtems_utime(rtems_filesystem_location_info_t* pathloc, - time_t atime, - time_t mtime) +rtems_rfs_rtems_utime(const rtems_filesystem_location_info_t* pathloc, + time_t atime, + time_t mtime) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); rtems_rfs_inode_handle inode; int rc; - rtems_rfs_rtems_lock (fs); - rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("utime: read inode", rc); } @@ -707,73 +400,46 @@ rtems_rfs_rtems_utime(rtems_filesystem_location_info_t* pathloc, rc = rtems_rfs_inode_close (fs, &inode); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("utime: closing inode", rc); } - rtems_rfs_rtems_unlock (fs); - return 0; } /** - * The following rouine creates a new symbolic link node under parent with the - * name given in name. The node is set to point to the node at to_loc. - * - * @param parent_loc - * @param link_name - * @param node_name - * return int + * The following routine creates a new symbolic link node under parent with the + * name given in node_name. */ static int -rtems_rfs_rtems_symlink (rtems_filesystem_location_info_t* parent_loc, - const char* link_name, - const char* node_name) +rtems_rfs_rtems_symlink (const rtems_filesystem_location_info_t* parent_loc, + const char* node_name, + size_t node_name_len, + const char* target) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parent_loc); rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc); - uid_t uid; - gid_t gid; int rc; -#if defined(RTEMS_POSIX_API) - uid = geteuid (); - gid = getegid (); -#else - uid = 0; - gid = 0; -#endif - - rtems_rfs_rtems_lock (fs); - - rc = rtems_rfs_symlink (fs, node_name, strlen (node_name), - link_name, strlen (link_name), - uid, gid, parent); + rc = rtems_rfs_symlink (fs, node_name, node_name_len, + target, strlen (target), + geteuid(), getegid(), parent); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("symlink: linking", rc); } - rtems_rfs_rtems_unlock (fs); - return 0; } /** * The following rouine puts the symblic links destination name into buf. - * - * @param loc - * @param buf - * @param bufsize - * @return int */ static ssize_t -rtems_rfs_rtems_readlink (rtems_filesystem_location_info_t* pathloc, - char* buf, - size_t bufsize) +rtems_rfs_rtems_readlink (const rtems_filesystem_location_info_t* pathloc, + char* buf, + size_t bufsize) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); @@ -783,23 +449,18 @@ rtems_rfs_rtems_readlink (rtems_filesystem_location_info_t* pathloc, if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_READLINK)) printf ("rtems-rfs-rtems: readlink: in: ino:%" PRId32 "\n", ino); - rtems_rfs_rtems_lock (fs); - rc = rtems_rfs_symlink_read (fs, ino, buf, bufsize, &length); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("readlink: reading link", rc); } - rtems_rfs_rtems_unlock (fs); - - return (int) length; + return (ssize_t) length; } -int -rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc, - mode_t mode) +static int +rtems_rfs_rtems_fchmod (const rtems_filesystem_location_info_t* pathloc, + mode_t mode) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); @@ -814,12 +475,9 @@ rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc, printf ("rtems-rfs-rtems: fchmod: in: ino:%" PRId32 " mode:%06" PRIomode_t "\n", ino, mode); - rtems_rfs_rtems_lock (fs); - rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("fchmod: opening inode", rc); } @@ -834,7 +492,6 @@ rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc, if ((uid != rtems_rfs_inode_get_uid (&inode)) && (uid != 0)) { rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("fchmod: checking uid", EPERM); } #endif @@ -847,18 +504,15 @@ rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc, rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("fchmod: closing inode", rc); } - rtems_rfs_rtems_unlock (fs); - return 0; } int -rtems_rfs_rtems_fstat (rtems_filesystem_location_info_t* pathloc, - struct stat* buf) +rtems_rfs_rtems_fstat (const rtems_filesystem_location_info_t* pathloc, + struct stat* buf) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); @@ -870,12 +524,9 @@ rtems_rfs_rtems_fstat (rtems_filesystem_location_info_t* pathloc, if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_STAT)) printf ("rtems-rfs-rtems: stat: in: ino:%" PRId32 "\n", ino); - rtems_rfs_rtems_lock (fs); - rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("stat: opening inode", rc); } @@ -931,32 +582,25 @@ rtems_rfs_rtems_fstat (rtems_filesystem_location_info_t* pathloc, rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("stat: closing inode", rc); } - rtems_rfs_rtems_unlock (fs); return 0; } /** * Routine to create a node in the RFS file system. - * - * @param name - * @param mode - * @param dev - * @param pathloc - * @return int */ static int -rtems_rfs_rtems_mknod (const char *name, - mode_t mode, - dev_t dev, - rtems_filesystem_location_info_t *pathloc) +rtems_rfs_rtems_mknod (const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev) { - rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); - rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (pathloc); + rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parentloc); + rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parentloc); rtems_rfs_ino ino; rtems_rfs_inode_handle inode; uid_t uid; @@ -971,21 +615,17 @@ rtems_rfs_rtems_mknod (const char *name, gid = 0; #endif - rtems_rfs_rtems_lock (fs); - - rc = rtems_rfs_inode_create (fs, parent, name, strlen (name), + rc = rtems_rfs_inode_create (fs, parent, name, namelen, rtems_rfs_rtems_imode (mode), 1, uid, gid, &ino); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("mknod: inode create", rc); } rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("mknod: inode open", rc); } @@ -1003,18 +643,15 @@ rtems_rfs_rtems_mknod (const char *name, else { rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("mknod: bad mode", EINVAL); } rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("mknod: closing inode", rc); } - rtems_rfs_rtems_unlock (fs); return 0; } @@ -1026,8 +663,8 @@ rtems_rfs_rtems_mknod (const char *name, * @return int */ int -rtems_rfs_rtems_rmnod (rtems_filesystem_location_info_t* parent_pathloc, - rtems_filesystem_location_info_t* pathloc) +rtems_rfs_rtems_rmnod (const rtems_filesystem_location_info_t* parent_pathloc, + const rtems_filesystem_location_info_t* pathloc) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_pathloc); @@ -1039,16 +676,15 @@ rtems_rfs_rtems_rmnod (rtems_filesystem_location_info_t* parent_pathloc, printf ("rtems-rfs: rmnod: parent:%" PRId32 " doff:%" PRIu32 ", ino:%" PRId32 "\n", parent, doff, ino); - rtems_rfs_rtems_lock (fs); + if (ino == RTEMS_RFS_ROOT_INO) + return rtems_rfs_rtems_error ("rmnod: root inode", EBUSY); - rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_denied); + rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_if_empty); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("rmnod: unlinking", rc); } - rtems_rfs_rtems_unlock (fs); return 0; } @@ -1073,18 +709,13 @@ rtems_rfs_rtems_fdatasync (rtems_libio_t* iop) /** * Rename the node. - * - * @param old_parent_loc The old name's parent location. - * @param old_loc The old name's location. - * @param new_parent_loc The new name's parent location. - * @param new_name The new name. - * @return int */ static int -rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_loc, - rtems_filesystem_location_info_t* old_loc, - rtems_filesystem_location_info_t* new_parent_loc, - const char* new_name) +rtems_rfs_rtems_rename(const rtems_filesystem_location_info_t* old_parent_loc, + const rtems_filesystem_location_info_t* old_loc, + const rtems_filesystem_location_info_t* new_parent_loc, + const char* new_name, + size_t new_name_len) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (old_loc); rtems_rfs_ino old_parent; @@ -1100,19 +731,16 @@ rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_loc, doff = rtems_rfs_rtems_get_pathloc_doff (old_loc); if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RENAME)) - printf ("rtems-rfs: rename: ino:%" PRId32 " doff:%" PRIu32 ", new parent:%" PRId32 " new name:%s\n", - ino, doff, new_parent, new_name); - - rtems_rfs_rtems_lock (fs); + printf ("rtems-rfs: rename: ino:%" PRId32 " doff:%" PRIu32 ", new parent:%" PRId32 "\n", + ino, doff, new_parent); /* * Link to the inode before unlinking so the inode is not erased when * unlinked. */ - rc = rtems_rfs_link (fs, new_name, strlen (new_name), new_parent, ino, true); + rc = rtems_rfs_link (fs, new_name, new_name_len, new_parent, ino, true); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("rename: linking", rc); } @@ -1124,12 +752,9 @@ rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_loc, rtems_rfs_unlink_dir_allowed); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("rename: unlinking", rc); } - rtems_rfs_rtems_unlock (fs); - return 0; } @@ -1141,8 +766,8 @@ rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_loc, * @return int */ static int -rtems_rfs_rtems_statvfs (rtems_filesystem_location_info_t* pathloc, - struct statvfs* sb) +rtems_rfs_rtems_statvfs (const rtems_filesystem_location_info_t* pathloc, + struct statvfs* sb) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); size_t blocks; @@ -1177,12 +802,10 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_link_handlers = .ioctl_h = rtems_filesystem_default_ioctl, .lseek_h = rtems_filesystem_default_lseek, .fstat_h = rtems_rfs_rtems_fstat, - .fchmod_h = rtems_filesystem_default_fchmod, .ftruncate_h = rtems_filesystem_default_ftruncate, .fsync_h = rtems_filesystem_default_fsync, .fdatasync_h = rtems_filesystem_default_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, - .rmnod_h = rtems_rfs_rtems_rmnod + .fcntl_h = rtems_filesystem_default_fcntl }; /** @@ -1191,27 +814,30 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_link_handlers = int rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t *mt_entry, const void *data); -int rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t *mt_entry); +void rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t *mt_entry); /** * RFS file system operations table. */ const rtems_filesystem_operations_table rtems_rfs_ops = { - .evalpath_h = rtems_rfs_rtems_eval_path, - .evalformake_h = rtems_rfs_rtems_eval_for_make, + .lock_h = rtems_rfs_rtems_lock_by_mt_entry, + .unlock_h = rtems_rfs_rtems_unlock_by_mt_entry, + .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal, + .eval_path_h = rtems_rfs_rtems_eval_path, .link_h = rtems_rfs_rtems_link, - .unlink_h = rtems_rfs_rtems_unlink, .node_type_h = rtems_rfs_rtems_node_type, + .fchmod_h = rtems_rfs_rtems_fchmod, .mknod_h = rtems_rfs_rtems_mknod, + .rmnod_h = rtems_rfs_rtems_rmnod, .chown_h = rtems_rfs_rtems_chown, + .clonenod_h = rtems_filesystem_default_clonenode, .freenod_h = rtems_filesystem_default_freenode, .mount_h = rtems_filesystem_default_mount, .fsmount_me_h = rtems_rfs_rtems_initialise, .unmount_h = rtems_filesystem_default_unmount, .fsunmount_me_h = rtems_rfs_rtems_shutdown, .utime_h = rtems_rfs_rtems_utime, - .eval_link_h = rtems_filesystem_default_evaluate_link, /* never called cause we lie in the node type */ .symlink_h = rtems_rfs_rtems_symlink, .readlink_h = rtems_rfs_rtems_readlink, .rename_h = rtems_rfs_rtems_rename, @@ -1292,9 +918,9 @@ rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t* mt_entry, mt_entry->fs_info = fs; - mt_entry->mt_fs_root.node_access = (void*) RTEMS_RFS_ROOT_INO; - mt_entry->mt_fs_root.handlers = &rtems_rfs_rtems_dir_handlers; - mt_entry->mt_fs_root.ops = &rtems_rfs_ops; + mt_entry->mt_fs_root->location.node_access = (void*) RTEMS_RFS_ROOT_INO; + mt_entry->mt_fs_root->location.handlers = &rtems_rfs_rtems_dir_handlers; + mt_entry->mt_fs_root->location.ops = &rtems_rfs_ops; rtems_rfs_rtems_unlock (fs); @@ -1304,19 +930,17 @@ rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t* mt_entry, /** * Shutdown the file system. */ -int +void rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t* mt_entry) { rtems_rfs_file_system* fs = mt_entry->fs_info; rtems_rfs_rtems_private* rtems; - int rc; rtems = rtems_rfs_fs_user (fs); - rc = rtems_rfs_fs_close(fs); + /* FIXME: Return value? */ + rtems_rfs_fs_close(fs); rtems_rfs_mutex_destroy (&rtems->access); free (rtems); - - return rtems_rfs_rtems_error ("shutdown: close", rc); } diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems.h b/cpukit/libfs/src/rfs/rtems-rfs-rtems.h index a1b0e8556e..c4f8c9a358 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-rtems.h +++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems.h @@ -225,16 +225,6 @@ typedef struct rtems_rfs_rtems_private &rtems_rfs_rtems_ ## _h ## _handlers /** - * Evaluate the permissions of the inode's mode against the flags. - * - * @param inode The inode handler to check the mode, uid and gid. - * @param flags The flags to check permissions of. - * @retval true The permissions allow access to the inode. - * @retval false Access to the inode is not permitted. - */ -bool rtems_rfs_rtems_eval_perms (rtems_rfs_inode_handle* inode, int flags); - -/** * Set the handlers in the path location based on the mode of the inode. * * @param loc Pointer to the path location to set the handlers in. @@ -292,23 +282,9 @@ extern const rtems_filesystem_file_handlers_r rtems_rfs_rtems_file_handlers; /** * The following routine does a stat on a node. - * - * @param iop - * @param buf - * @return int - */ -int rtems_rfs_rtems_fstat (rtems_filesystem_location_info_t* pathloc, - struct stat* buf); - -/** - * File change mode routine. - * - * @param iop - * @param mode - * @return int */ -int rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc, - mode_t mode); +int rtems_rfs_rtems_fstat (const rtems_filesystem_location_info_t* pathloc, + struct stat* buf); /** * Routine to remove a node from the RFS file system. @@ -316,8 +292,8 @@ int rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc, * @param parent_pathloc * @param pathloc */ -int rtems_rfs_rtems_rmnod (rtems_filesystem_location_info_t* parent_pathloc, - rtems_filesystem_location_info_t* pathloc); +int rtems_rfs_rtems_rmnod (const rtems_filesystem_location_info_t* parent_pathloc, + const rtems_filesystem_location_info_t* pathloc); /** * The following routine does a sync on an inode node. Currently it flushes diff --git a/cpukit/libfs/src/rfs/rtems-rfs-shell.c b/cpukit/libfs/src/rfs/rtems-rfs-shell.c index 6969f1c588..8ef5b76ff5 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-shell.c +++ b/cpukit/libfs/src/rfs/rtems-rfs-shell.c @@ -102,10 +102,12 @@ rtems_rfs_get_fs (const char* path, rtems_rfs_file_system** fs) * system data. */ { - rtems_filesystem_location_info_t pathloc; - rc = rtems_filesystem_evaluate_path (path, strlen (path), 0, &pathloc, true); - *fs = rtems_rfs_rtems_pathloc_dev (&pathloc); - rtems_filesystem_freenode (&pathloc); + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_LIBIO_FOLLOW_LINK; + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start (&ctx, path, eval_flags); + *fs = rtems_rfs_rtems_pathloc_dev (currentloc); + rtems_filesystem_eval_path_cleanup (&ctx); } #endif diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am index e468dd13a0..654c0505aa 100644 --- a/cpukit/libmisc/Makefile.am +++ b/cpukit/libmisc/Makefile.am @@ -103,6 +103,7 @@ libshell_a_SOURCES = shell/cat_file.c shell/cmds.c shell/internal.h \ shell/main_time.c shell/main_mknod.c \ shell/main_setenv.c shell/main_getenv.c shell/main_unsetenv.c \ shell/main_mkrfs.c shell/main_debugrfs.c \ + shell/main_lsof.c \ shell/shell-wait-for-input.c if LIBNETWORKING diff --git a/cpukit/libmisc/shell/main_lsof.c b/cpukit/libmisc/shell/main_lsof.c new file mode 100644 index 0000000000..993d107da8 --- /dev/null +++ b/cpukit/libmisc/shell/main_lsof.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/libio_.h> +#include <rtems/shell.h> +#include <rtems/shellconfig.h> + +static void lsof(void) +{ + rtems_chain_control *mt_chain = &rtems_filesystem_mount_table; + rtems_chain_node *mt_node = NULL; + + for ( + mt_node = rtems_chain_first( mt_chain ); + !rtems_chain_is_tail( mt_chain, mt_node ); + mt_node = rtems_chain_next( mt_node ) + ) { + rtems_filesystem_mount_table_entry_t *mt_entry = + (rtems_filesystem_mount_table_entry_t *) mt_node; + rtems_chain_control *mt_entry_chain = &mt_entry->location_chain; + rtems_chain_node *mt_entry_node = NULL; + + printk( + "%c %c %s %s -> %s root 0x%08x -> 0x%08x\n", + mt_entry->mounted ? 'M' : 'U', + mt_entry->writeable ? 'W' : 'R', + mt_entry->type, + mt_entry->target, + mt_entry->dev, + mt_entry->mt_fs_root, + mt_entry->mt_fs_root->location.node_access + ); + + for ( + mt_entry_node = rtems_chain_first( mt_entry_chain ); + !rtems_chain_is_tail( mt_entry_chain, mt_entry_node ); + mt_entry_node = rtems_chain_next( mt_entry_node ) + ) { + const rtems_filesystem_location_info_t *loc = + (rtems_filesystem_location_info_t *) mt_entry_node; + + printk( + "\t0x%08x -> 0x%08x\n", + loc, + loc->node_access + ); + } + } +} + +static int rtems_shell_main_lsof(int argc, char **argv) +{ + lsof(); + + return 0; +} + +rtems_shell_cmd_t rtems_shell_LSOF_Command = { + .name = "lsof", + .usage = "lsof", + .topic = "files", + .command = rtems_shell_main_lsof +}; diff --git a/cpukit/libmisc/shell/shellconfig.h b/cpukit/libmisc/shell/shellconfig.h index 971df25b22..85fb3d0a6d 100644 --- a/cpukit/libmisc/shell/shellconfig.h +++ b/cpukit/libmisc/shell/shellconfig.h @@ -61,6 +61,7 @@ extern rtems_shell_cmd_t rtems_shell_RM_Command; extern rtems_shell_cmd_t rtems_shell_LN_Command; extern rtems_shell_cmd_t rtems_shell_MKNOD_Command; extern rtems_shell_cmd_t rtems_shell_UMASK_Command; +extern rtems_shell_cmd_t rtems_shell_LSOF_Command; extern rtems_shell_cmd_t rtems_shell_MOUNT_Command; extern rtems_shell_cmd_t rtems_shell_UNMOUNT_Command; extern rtems_shell_cmd_t rtems_shell_BLKSYNC_Command; @@ -329,6 +330,11 @@ extern rtems_shell_alias_t *rtems_shell_Initial_aliases[]; &rtems_shell_UMASK_Command, #endif #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \ + !defined(CONFIGURE_SHELL_NO_COMMAND_LSOF)) || \ + defined(CONFIGURE_SHELL_COMMAND_LSOF) + &rtems_shell_LSOF_Command, + #endif + #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \ !defined(CONFIGURE_SHELL_NO_COMMAND_MOUNT)) || \ defined(CONFIGURE_SHELL_COMMAND_MOUNT) &rtems_shell_MOUNT_Command, diff --git a/cpukit/libnetworking/lib/ftpfs.c b/cpukit/libnetworking/lib/ftpfs.c index e588bc41ad..b50890e4c9 100644 --- a/cpukit/libnetworking/lib/ftpfs.c +++ b/cpukit/libnetworking/lib/ftpfs.c @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2009, 2010, 2011 + * Copyright (c) 2009-2012 * embedded brains GmbH * Obere Lagerstr. 30 * D-82178 Puchheim @@ -54,7 +54,7 @@ #include <rtems.h> #include <rtems/ftpfs.h> #include <rtems/imfs.h> -#include <rtems/libio.h> +#include <rtems/libio_.h> #include <rtems/rtems_bsdnet.h> #include <rtems/seterr.h> @@ -939,8 +939,8 @@ static int rtems_ftpfs_open_data_connection_passive( static int rtems_ftpfs_open( rtems_libio_t *iop, const char *path, - uint32_t flags, - uint32_t mode + int oflag, + mode_t mode ) { int eno = 0; @@ -962,11 +962,6 @@ static int rtems_ftpfs_open( /* Invalidate data handle */ iop->data1 = NULL; - /* Check location, it was allocated during path evaluation */ - if (location == NULL) { - rtems_set_errno_and_return_minus_one(ENOMEM); - } - /* Split location into parts */ ok = rtems_ftpfs_split_names( location, @@ -976,17 +971,7 @@ static int rtems_ftpfs_open( &filename ); if (!ok) { - if (strlen(location) == 0) { - /* - * This is an access to the root node that will be used for file system - * option settings. - */ - iop->pathinfo.handlers = &rtems_ftpfs_root_handlers; - - return 0; - } else { - rtems_set_errno_and_return_minus_one(ENOENT); - } + rtems_set_errno_and_return_minus_one(ENOENT); } DEBUG_PRINTF( "user = '%s', password = '%s', filename = '%s'\n", @@ -1154,39 +1139,40 @@ static int rtems_ftpfs_ftruncate(rtems_libio_t *iop, off_t count) return 0; } -static int rtems_ftpfs_eval_path( - const char *pathname, - size_t pathnamelen, - int flags, - rtems_filesystem_location_info_t *pathloc +static void rtems_ftpfs_eval_path( + rtems_filesystem_eval_path_context_t *self ) { - /* - * The caller of this routine has striped off the mount prefix from the path. - * We need to store this path here or otherwise we would have to do this job - * again. The path is used in rtems_ftpfs_open() via iop->pathinfo.node_access. - */ - char *pathname_dup = malloc(pathnamelen + 1); + rtems_filesystem_eval_path_eat_delimiter(self); - if (pathname_dup != NULL) { - memcpy(pathname_dup, pathname, pathnamelen); - pathname_dup [pathnamelen] = '\0'; - } + if (rtems_filesystem_eval_path_has_path(self)) { + const char *path = rtems_filesystem_eval_path_get_path(self); + size_t pathlen = rtems_filesystem_eval_path_get_pathlen(self); + char *pathdup = malloc(pathlen + 1); - pathloc->node_access = pathname_dup; + rtems_filesystem_eval_path_clear_path(self); - return 0; + if (pathdup != NULL) { + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc(self); + + memcpy(pathdup, path, pathlen); + pathdup [pathlen] = '\0'; + currentloc->node_access = pathdup; + currentloc->handlers = &rtems_ftpfs_handlers; + } else { + rtems_filesystem_eval_path_error(self, ENOMEM); + } + } } -static int rtems_ftpfs_free_node(rtems_filesystem_location_info_t *pathloc) +static void rtems_ftpfs_free_node(const rtems_filesystem_location_info_t *loc) { - free(pathloc->node_access); - - return 0; + free(loc->node_access); } static rtems_filesystem_node_types_t rtems_ftpfs_node_type( - rtems_filesystem_location_info_t *pathloc + const rtems_filesystem_location_info_t *loc ) { return RTEMS_FILESYSTEM_MEMORY_FILE; @@ -1209,11 +1195,11 @@ int rtems_ftpfs_initialize( me->timeout.tv_usec = 0; /* Set handler and oparations table */ - e->mt_fs_root.handlers = &rtems_ftpfs_handlers; - e->mt_fs_root.ops = &rtems_ftpfs_ops; + e->mt_fs_root->location.handlers = &rtems_ftpfs_root_handlers; + e->mt_fs_root->location.ops = &rtems_ftpfs_ops; /* We maintain no real file system nodes, so there is no real root */ - e->mt_fs_root.node_access = NULL; + e->mt_fs_root->location.node_access = NULL; /* Just use the limits from IMFS */ e->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS; @@ -1221,13 +1207,11 @@ int rtems_ftpfs_initialize( return 0; } -static int rtems_ftpfs_unmount_me( +static void rtems_ftpfs_unmount_me( rtems_filesystem_mount_table_entry_t *e ) { free(e->fs_info); - - return 0; } static int rtems_ftpfs_ioctl( @@ -1271,14 +1255,12 @@ static int rtems_ftpfs_ioctl( * a remote to remote copy. This is not a very sophisticated method. */ static int rtems_ftpfs_fstat( - rtems_filesystem_location_info_t *loc, + const rtems_filesystem_location_info_t *loc, struct stat *st ) { static unsigned ino = 0; - memset(st, 0, sizeof(*st)); - /* FIXME */ st->st_ino = ++ino; st->st_dev = rtems_filesystem_make_dev_t(0xcc494cd6U, 0x1d970b4dU); @@ -1289,22 +1271,27 @@ static int rtems_ftpfs_fstat( } static const rtems_filesystem_operations_table rtems_ftpfs_ops = { - .evalpath_h = rtems_ftpfs_eval_path, - .evalformake_h = rtems_filesystem_default_evalformake, + .lock_h = rtems_filesystem_default_lock, + .unlock_h = rtems_filesystem_default_unlock, + .eval_path_h = rtems_ftpfs_eval_path, .link_h = rtems_filesystem_default_link, - .unlink_h = rtems_filesystem_default_unlink, + .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal, .node_type_h = rtems_ftpfs_node_type, .mknod_h = rtems_filesystem_default_mknod, + .rmnod_h = rtems_filesystem_default_rmnod, + .fchmod_h = rtems_filesystem_default_fchmod, .chown_h = rtems_filesystem_default_chown, + .clonenod_h = rtems_filesystem_default_clonenode, .freenod_h = rtems_ftpfs_free_node, .mount_h = rtems_filesystem_default_mount, .fsmount_me_h = rtems_ftpfs_initialize, .unmount_h = rtems_filesystem_default_unmount, .fsunmount_me_h = rtems_ftpfs_unmount_me, .utime_h = rtems_filesystem_default_utime, - .eval_link_h = rtems_filesystem_default_evaluate_link, .symlink_h = rtems_filesystem_default_symlink, - .readlink_h = rtems_filesystem_default_readlink + .readlink_h = rtems_filesystem_default_readlink, + .rename_h = rtems_filesystem_default_rename, + .statvfs_h = rtems_filesystem_default_statvfs }; static const rtems_filesystem_file_handlers_r rtems_ftpfs_handlers = { @@ -1315,12 +1302,10 @@ static const rtems_filesystem_file_handlers_r rtems_ftpfs_handlers = { .ioctl_h = rtems_filesystem_default_ioctl, .lseek_h = rtems_filesystem_default_lseek, .fstat_h = rtems_ftpfs_fstat, - .fchmod_h = rtems_filesystem_default_fchmod, .ftruncate_h = rtems_ftpfs_ftruncate, .fsync_h = rtems_filesystem_default_fsync, .fdatasync_h = rtems_filesystem_default_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, - .rmnod_h = rtems_filesystem_default_rmnod + .fcntl_h = rtems_filesystem_default_fcntl }; static const rtems_filesystem_file_handlers_r rtems_ftpfs_root_handlers = { @@ -1331,10 +1316,8 @@ static const rtems_filesystem_file_handlers_r rtems_ftpfs_root_handlers = { .ioctl_h = rtems_ftpfs_ioctl, .lseek_h = rtems_filesystem_default_lseek, .fstat_h = rtems_filesystem_default_fstat, - .fchmod_h = rtems_filesystem_default_fchmod, .ftruncate_h = rtems_filesystem_default_ftruncate, .fsync_h = rtems_filesystem_default_fsync, .fdatasync_h = rtems_filesystem_default_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, - .rmnod_h = rtems_filesystem_default_rmnod + .fcntl_h = rtems_filesystem_default_fcntl }; diff --git a/cpukit/libnetworking/lib/tftpDriver.c b/cpukit/libnetworking/lib/tftpDriver.c index c5e6c6b075..0e284c1e5c 100644 --- a/cpukit/libnetworking/lib/tftpDriver.c +++ b/cpukit/libnetworking/lib/tftpDriver.c @@ -9,6 +9,9 @@ * Saskatoon, Saskatchewan, CANADA * eric@skatter.usask.ca * + * Modifications to support reference counting in the file system are + * Copyright (c) 2012 embedded brains GmbH. + * * $Id$ * */ @@ -146,13 +149,6 @@ struct tftpStream { #define TFTPFS_VERBOSE (1 << 0) /* - * Root node_access value - * By using the address of the file system - * we ensure a unique value for this identifier. - */ -#define ROOT_NODE_ACCESS(_fs) (_fs) - -/* * TFTP File system info. */ typedef struct tftpfs_info_s { @@ -170,39 +166,48 @@ typedef struct tftpfs_info_s { * Number of streams open at the same time */ -typedef const char *tftp_node; static const rtems_filesystem_operations_table rtems_tftp_ops; static const rtems_filesystem_file_handlers_r rtems_tftp_handlers; +static bool rtems_tftp_is_directory( + const char *path, + size_t pathlen +) +{ + return path [pathlen - 1] == '/'; +} + int rtems_tftpfs_initialize( rtems_filesystem_mount_table_entry_t *mt_entry, const void *data ) { - tftpfs_info_t *fs; rtems_status_code sc; + const char *device = mt_entry->dev; + size_t devicelen = strlen (device); + tftpfs_info_t *fs; + char *root_path; - mt_entry->mt_fs_root.handlers = &rtems_tftp_handlers; - mt_entry->mt_fs_root.ops = &rtems_tftp_ops; + if (devicelen == 0) + rtems_set_errno_and_return_minus_one (ENXIO); - /* - * We have no tftp filesystem specific data to maintain. This - * filesystem may only be mounted ONCE. - * - * And we maintain no real filesystem nodes, so there is no real root. - */ + fs = malloc (sizeof (*fs)); + root_path = malloc (devicelen + 2); + if (root_path == NULL || fs == NULL) + goto error; - fs = malloc (sizeof (tftpfs_info_t)); - if (!fs) - rtems_set_errno_and_return_minus_one (ENOMEM); + root_path = memcpy (root_path, device, devicelen); + root_path [devicelen] = '/'; + root_path [devicelen + 1] = '\0'; fs->flags = 0; fs->nStreams = 0; fs->tftpStreams = 0; - mt_entry->fs_info = fs; - mt_entry->mt_fs_root.node_access = ROOT_NODE_ACCESS (fs); - mt_entry->mt_fs_root.node_access_2 = NULL; + mt_entry->fs_info = fs; + mt_entry->mt_fs_root->location.node_access = root_path; + mt_entry->mt_fs_root->location.handlers = &rtems_tftp_handlers; + mt_entry->mt_fs_root->location.ops = &rtems_tftp_ops; /* * Now allocate a semaphore for mutual exclusion. @@ -223,7 +228,7 @@ int rtems_tftpfs_initialize( ); if (sc != RTEMS_SUCCESSFUL) - rtems_set_errno_and_return_minus_one (ENOMEM); + goto error; if (data) { char* config = (char*) data; @@ -238,6 +243,13 @@ int rtems_tftpfs_initialize( } return 0; + +error: + + free (fs); + free (root_path); + + rtems_set_errno_and_return_minus_one (ENOMEM); } /* @@ -254,7 +266,7 @@ releaseStream (tftpfs_info_t *fs, int s) rtems_semaphore_release (fs->tftp_mutex); } -static int +static void rtems_tftpfs_shutdown (rtems_filesystem_mount_table_entry_t* mt_entry) { tftpfs_info_t *fs = tftpfs_info_mount_table (mt_entry); @@ -263,7 +275,7 @@ rtems_tftpfs_shutdown (rtems_filesystem_mount_table_entry_t* mt_entry) releaseStream (fs, s); rtems_semaphore_delete (fs->tftp_mutex); free (fs); - return 0; + free (mt_entry->mt_fs_root->location.node_access); } /* @@ -418,17 +430,6 @@ sendAck (struct tftpStream *tp) return 0; } -static int rtems_tftp_evaluate_for_make( - const char *path __attribute__((unused)), /* IN */ - rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ - const char **name __attribute__((unused)) /* OUT */ -) -{ - pathloc->node_access = NULL; - pathloc->node_access_2 = NULL; - rtems_set_errno_and_return_minus_one (EIO); -} - /* * Convert a path to canonical form */ @@ -483,62 +484,41 @@ fixPath (char *path) return; } -static int rtems_tftp_eval_path( - const char *pathname, /* IN */ - size_t pathnamelen, /* IN */ - int flags, /* IN */ - rtems_filesystem_location_info_t *pathloc /* IN/OUT */ -) +static void rtems_tftp_eval_path(rtems_filesystem_eval_path_context_t *self) { - tftpfs_info_t *fs; - char *cp; - - /* - * Get the file system info. - */ - fs = tftpfs_info_pathloc (pathloc); - - pathloc->handlers = &rtems_tftp_handlers; - - /* - * Hack to provide the illusion of directories inside the TFTP file system. - * Paths ending in a / are assumed to be directories. - */ - if (pathname[strlen(pathname)-1] == '/') { - int nal = 0; - if (pathloc->node_access != ROOT_NODE_ACCESS (fs)) - nal = strlen(pathloc->node_access); - cp = malloc(nal + pathnamelen + 1); - if (cp == NULL) - rtems_set_errno_and_return_minus_one(ENOMEM); - if (nal) - memcpy (cp, pathloc->node_access, nal); - memcpy(cp + nal, pathname, pathnamelen); - cp[nal + pathnamelen] = '\0'; - fixPath (cp); - pathloc->node_access = cp; - } - else { - if (pathnamelen) { - /* - * Reject it if it's not read-only or write-only. - */ - flags &= RTEMS_LIBIO_PERMS_READ | RTEMS_LIBIO_PERMS_WRITE; - if ((flags != RTEMS_LIBIO_PERMS_READ) \ - && (flags != RTEMS_LIBIO_PERMS_WRITE)) - rtems_set_errno_and_return_minus_one(EINVAL); - - cp = malloc(pathnamelen + 1); - if (cp == NULL) - rtems_set_errno_and_return_minus_one(ENOMEM); - memcpy(cp, pathname, pathnamelen); - cp[pathnamelen] = '\0'; - fixPath (cp); - pathloc->node_access_2 = cp; + int eval_flags = rtems_filesystem_eval_path_get_flags (self); + + if ((eval_flags & RTEMS_LIBIO_MAKE) == 0) { + int rw = RTEMS_LIBIO_PERMS_READ | RTEMS_LIBIO_PERMS_WRITE; + + if ((eval_flags & rw) != rw) { + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc (self); + char *current = currentloc->node_access; + size_t currentlen = strlen (current); + const char *path = rtems_filesystem_eval_path_get_path (self); + size_t pathlen = rtems_filesystem_eval_path_get_pathlen (self); + size_t len = currentlen + pathlen; + + rtems_filesystem_eval_path_clear_path (self); + + current = realloc (current, len + 1); + if (current != NULL) { + memcpy (current + currentlen, path, pathlen); + current [len] = '\0'; + if (!rtems_tftp_is_directory (current, len)) { + fixPath (current); + } + currentloc->node_access = current; + } else { + rtems_filesystem_eval_path_error (self, ENOMEM); + } + } else { + rtems_filesystem_eval_path_error (self, EINVAL); } + } else { + rtems_filesystem_eval_path_error (self, EIO); } - - return 0; } /* @@ -547,8 +527,7 @@ static int rtems_tftp_eval_path( static int rtems_tftp_open_worker( rtems_libio_t *iop, char *full_path_name, - uint32_t flags, - uint32_t mode __attribute__((unused)) + int oflag ) { tftpfs_info_t *fs; @@ -680,7 +659,7 @@ static int rtems_tftp_open_worker( /* * Create the request */ - if ((flags & O_ACCMODE) == O_RDONLY) { + if ((oflag & O_ACCMODE) == O_RDONLY) { tp->writing = 0; tp->pkbuf.tftpRWRQ.opcode = htons (TFTP_OPCODE_RRQ); } @@ -751,91 +730,37 @@ static int rtems_tftp_open_worker( return 0; } -/* - * The IMFS open handler - */ static int rtems_tftp_open( rtems_libio_t *iop, const char *new_name, - uint32_t flags, - uint32_t mode + int oflag, + mode_t mode ) { tftpfs_info_t *fs; - const char *device; char *full_path_name; - char *na; - char *na2; - int dlen; - int nalen; - int na2len; - int sep1; int err; + full_path_name = iop->pathinfo.node_access; + + if (rtems_tftp_is_directory (full_path_name, strlen (full_path_name))) { + rtems_set_errno_and_return_minus_one (ENOTSUP); + } + /* * Get the file system info. */ fs = tftpfs_info_iop (iop); - - /* - * Tack the prefix directory if one exists from the device name. - */ - device = - rtems_filesystem_mount_device (rtems_filesystem_location_mount (&iop->pathinfo)); - dlen = strlen (device); - if (dlen == 0) - rtems_set_errno_and_return_minus_one (ENOENT); - - if (iop->pathinfo.node_access_2 == NULL) - rtems_set_errno_and_return_minus_one (ENOENT); - - if (iop->pathinfo.node_access != ROOT_NODE_ACCESS (fs)) { - na = iop->pathinfo.node_access; - nalen = strlen (na); - } - else { - na = NULL; - nalen = 0; - } - - na2 = iop->pathinfo.node_access_2; - - na2len = strlen (na2); - - if (nalen) { - sep1 = 1; - if (na[nalen] == '/') { - sep1 = 0; - if (na2[0] == '/') - ++na2; - } - else { - if (na2[0] == '/') - sep1 = 0; - else - sep1 = 1; - } - } - else - sep1 = 0; - - full_path_name = malloc (dlen + nalen + sep1 + na2len + 1); - if (full_path_name == NULL) - rtems_set_errno_and_return_minus_one(ENOMEM); - strcpy (full_path_name, device); - if (nalen) - strcat (full_path_name, na); - if (sep1) - strcat (full_path_name, "/"); - strcat (full_path_name, na2); - fixPath (full_path_name); if (fs->flags & TFTPFS_VERBOSE) - printf ("TFTPFS: %s %s %s -> %s\n", device, na, na2, full_path_name); + printf ("TFTPFS: %s\n", full_path_name); - err = rtems_tftp_open_worker (iop, full_path_name, flags, mode); - free (full_path_name); - rtems_set_errno_and_return_minus_one(err); + err = rtems_tftp_open_worker (iop, full_path_name, oflag); + if (err != 0) { + rtems_set_errno_and_return_minus_one (err); + } + + return 0; } /* @@ -1051,52 +976,70 @@ static int rtems_tftp_ftruncate( } static rtems_filesystem_node_types_t rtems_tftp_node_type( - rtems_filesystem_location_info_t *pathloc /* IN */ + const rtems_filesystem_location_info_t *loc ) { - tftpfs_info_t *fs = tftpfs_info_pathloc (pathloc); - if ((pathloc->node_access == NULL) - || (pathloc->node_access_2 != NULL) - || (pathloc->node_access == ROOT_NODE_ACCESS (fs))) - return RTEMS_FILESYSTEM_MEMORY_FILE; - return RTEMS_FILESYSTEM_DIRECTORY; + const char *path = loc->node_access; + size_t pathlen = strlen (path); + + return rtems_tftp_is_directory (path, pathlen) ? + RTEMS_FILESYSTEM_DIRECTORY + : RTEMS_FILESYSTEM_MEMORY_FILE; } -static int rtems_tftp_free_node_info( - rtems_filesystem_location_info_t *pathloc /* IN */ +static int rtems_tftp_clone( + rtems_filesystem_location_info_t *loc ) { - tftpfs_info_t *fs = tftpfs_info_pathloc (pathloc); - if (pathloc->node_access && \ - (pathloc->node_access != ROOT_NODE_ACCESS (fs))) { - free (pathloc->node_access); - pathloc->node_access = NULL; - } - if (pathloc->node_access_2) { - free (pathloc->node_access_2); - pathloc->node_access_2 = NULL; + int rv = 0; + + loc->node_access = strdup (loc->node_access); + + if (loc->node_access == NULL) { + errno = ENOMEM; + rv = -1; } - return 0; + + return rv; } +static void rtems_tftp_free_node_info( + const rtems_filesystem_location_info_t *loc +) +{ + free (loc->node_access); +} + +static bool rtems_tftp_are_nodes_equal( + const rtems_filesystem_location_info_t *a, + const rtems_filesystem_location_info_t *b +) +{ + return strcmp (a->node_access, b->node_access) == 0; +} static const rtems_filesystem_operations_table rtems_tftp_ops = { - .evalpath_h = rtems_tftp_eval_path, - .evalformake_h = rtems_tftp_evaluate_for_make, + .lock_h = rtems_filesystem_default_lock, + .unlock_h = rtems_filesystem_default_unlock, + .eval_path_h = rtems_tftp_eval_path, .link_h = rtems_filesystem_default_link, - .unlink_h = rtems_filesystem_default_unlink, + .are_nodes_equal_h = rtems_tftp_are_nodes_equal, .node_type_h = rtems_tftp_node_type, .mknod_h = rtems_filesystem_default_mknod, + .rmnod_h = rtems_filesystem_default_rmnod, + .fchmod_h = rtems_filesystem_default_fchmod, .chown_h = rtems_filesystem_default_chown, + .clonenod_h = rtems_tftp_clone, .freenod_h = rtems_tftp_free_node_info, .mount_h = rtems_filesystem_default_mount, .fsmount_me_h = rtems_tftpfs_initialize, .unmount_h = rtems_filesystem_default_unmount, .fsunmount_me_h = rtems_tftpfs_shutdown, .utime_h = rtems_filesystem_default_utime, - .eval_link_h = rtems_filesystem_default_evaluate_link, .symlink_h = rtems_filesystem_default_symlink, - .readlink_h = rtems_filesystem_default_readlink + .readlink_h = rtems_filesystem_default_readlink, + .rename_h = rtems_filesystem_default_rename, + .statvfs_h = rtems_filesystem_default_statvfs }; static const rtems_filesystem_file_handlers_r rtems_tftp_handlers = { @@ -1107,10 +1050,8 @@ static const rtems_filesystem_file_handlers_r rtems_tftp_handlers = { .ioctl_h = rtems_filesystem_default_ioctl, .lseek_h = rtems_filesystem_default_lseek, .fstat_h = rtems_filesystem_default_fstat, - .fchmod_h = rtems_filesystem_default_fchmod, .ftruncate_h = rtems_tftp_ftruncate, .fsync_h = rtems_filesystem_default_fsync, .fdatasync_h = rtems_filesystem_default_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, - .rmnod_h = rtems_filesystem_default_rmnod + .fcntl_h = rtems_filesystem_default_fcntl }; diff --git a/cpukit/libnetworking/rtems/rtems_bsdnet_internal.h b/cpukit/libnetworking/rtems/rtems_bsdnet_internal.h index c8bdfd4b44..3e1ce72455 100644 --- a/cpukit/libnetworking/rtems/rtems_bsdnet_internal.h +++ b/cpukit/libnetworking/rtems/rtems_bsdnet_internal.h @@ -13,6 +13,7 @@ #define _RTEMS_RTEMS_BSDNET_INTERNAL_H #include <rtems.h> +#include <rtems/fs.h> #ifdef __cplusplus extern "C" { @@ -198,6 +199,10 @@ int ioctl (int, ioctl_command_t, ...); # error "Network event conflict" #endif +int rtems_bsdnet_makeFdForSocket( + void *so, const rtems_filesystem_file_handlers_r *h); +struct socket *rtems_bsdnet_fdToSocket(int fd); + #ifdef __cplusplus } #endif diff --git a/cpukit/libnetworking/rtems/rtems_syscall.c b/cpukit/libnetworking/rtems/rtems_syscall.c index a5d724afbe..f043e094f4 100644 --- a/cpukit/libnetworking/rtems/rtems_syscall.c +++ b/cpukit/libnetworking/rtems/rtems_syscall.c @@ -42,9 +42,6 @@ ssize_t recv(int, void *, size_t, int); * Hooks to RTEMS I/O system */ static const rtems_filesystem_file_handlers_r socket_handlers; -int rtems_bsdnet_makeFdForSocket( - void *so, const rtems_filesystem_file_handlers_r *h); -struct socket *rtems_bsdnet_fdToSocket(int fd); /* * Package system call argument into mbuf. @@ -738,7 +735,7 @@ rtems_bsdnet_ioctl (rtems_libio_t *iop, uint32_t command, void *buffer) } static int -rtems_bsdnet_fcntl (int cmd, rtems_libio_t *iop) +rtems_bsdnet_fcntl (rtems_libio_t *iop, int cmd) { struct socket *so; @@ -758,7 +755,7 @@ rtems_bsdnet_fcntl (int cmd, rtems_libio_t *iop) } static int -rtems_bsdnet_fstat (rtems_filesystem_location_info_t *loc, struct stat *sp) +rtems_bsdnet_fstat (const rtems_filesystem_location_info_t *loc, struct stat *sp) { sp->st_mode = S_IFSOCK; return 0; @@ -772,10 +769,8 @@ static const rtems_filesystem_file_handlers_r socket_handlers = { rtems_bsdnet_ioctl, /* ioctl */ rtems_filesystem_default_lseek, /* lseek */ rtems_bsdnet_fstat, /* fstat */ - rtems_filesystem_default_fchmod, /* fchmod */ rtems_filesystem_default_ftruncate, /* ftruncate */ rtems_filesystem_default_fsync, /* fsync */ rtems_filesystem_default_fdatasync, /* fdatasync */ - rtems_bsdnet_fcntl, /* fcntl */ - rtems_filesystem_default_rmnod /* rmnod */ + rtems_bsdnet_fcntl /* fcntl */ }; diff --git a/cpukit/posix/src/sysconf.c b/cpukit/posix/src/sysconf.c index 3d64e2843f..5874661336 100644 --- a/cpukit/posix/src/sysconf.c +++ b/cpukit/posix/src/sysconf.c @@ -45,6 +45,9 @@ long sysconf( if ( name == _SC_PAGESIZE ) return PAGE_SIZE; + if ( name == _SC_SYMLOOP_MAX ) + return RTEMS_FILESYSTEM_SYMLOOP_MAX; + #if defined(__sparc__) if ( name == 515 ) /* Solaris _SC_STACK_PROT */ return 0; diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h index 89e6b5c094..8f03c876a9 100644 --- a/cpukit/sapi/include/confdefs.h +++ b/cpukit/sapi/include/confdefs.h @@ -428,9 +428,7 @@ rtems_fs_init_functions_t rtems_fs_init_helper = * the bsp overwrides this. In which case the value is set * to BSP_MAXIMUM_DEVICES. */ - #if defined(CONFIGURE_APPLICATION_DISABLE_FILESYSTEM) - #define CONFIGURE_MEMORY_FOR_DEVFS 0 - #elif defined(CONFIGURE_FILESYSTEM_DEVFS) + #ifdef CONFIGURE_FILESYSTEM_DEVFS #ifndef CONFIGURE_MAXIMUM_DEVICES #if defined(BSP_MAXIMUM_DEVICES) #define CONFIGURE_MAXIMUM_DEVICES BSP_MAXIMUM_DEVICES @@ -439,12 +437,6 @@ rtems_fs_init_functions_t rtems_fs_init_helper = #endif #endif #include <rtems/devfs.h> - uint32_t rtems_device_table_size = CONFIGURE_MAXIMUM_DEVICES; - #define CONFIGURE_MEMORY_FOR_DEVFS \ - _Configure_Object_RAM(CONFIGURE_MAXIMUM_DEVICES, \ - sizeof (rtems_device_name_t)) - #else - #define CONFIGURE_MEMORY_FOR_DEVFS 0 #endif #ifndef RTEMS_SCHEDSIM @@ -503,23 +495,31 @@ rtems_fs_init_functions_t rtems_fs_init_helper = #endif #ifndef CONFIGURE_HAS_OWN_MOUNT_TABLE - extern const rtems_filesystem_mount_table_t configuration_mount_table; - const rtems_filesystem_mount_table_t configuration_mount_table = { + #if defined(CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM) + static devFS_node devFS_root_filesystem_nodes [CONFIGURE_MAXIMUM_DEVICES]; + static const devFS_data devFS_root_filesystem_data = { + devFS_root_filesystem_nodes, + CONFIGURE_MAXIMUM_DEVICES + }; + #endif + const rtems_filesystem_mount_configuration + rtems_filesystem_root_configuration = { + NULL, + NULL, #if defined(CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM) RTEMS_FILESYSTEM_TYPE_DEVFS, #elif defined(CONFIGURE_USE_MINIIMFS_AS_BASE_FILESYSTEM) RTEMS_FILESYSTEM_TYPE_MINIIMFS, - #else /* using IMFS as base filesystem */ + #else RTEMS_FILESYSTEM_TYPE_IMFS, #endif RTEMS_FILESYSTEM_READ_WRITE, - NULL, - NULL + #if defined(CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM) + &devFS_root_filesystem_data + #else + NULL + #endif }; - - const rtems_filesystem_mount_table_t - *rtems_filesystem_mount_table = &configuration_mount_table; - const int rtems_filesystem_mount_table_size = 1; #endif #endif @@ -2020,7 +2020,6 @@ rtems_fs_init_functions_t rtems_fs_init_helper = #define CONFIGURE_EXECUTIVE_RAM_SIZE \ (( \ CONFIGURE_MEMORY_FOR_SYSTEM_OVERHEAD + \ - CONFIGURE_MEMORY_FOR_DEVFS + \ CONFIGURE_MEMORY_FOR_TASKS( \ CONFIGURE_TOTAL_TASKS_AND_THREADS, CONFIGURE_TOTAL_TASKS_AND_THREADS) + \ CONFIGURE_MEMORY_FOR_CLASSIC + \ |