summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libcsupport')
-rw-r--r--cpukit/libcsupport/Makefile.am16
-rw-r--r--cpukit/libcsupport/include/rtems/libio.h1623
-rw-r--r--cpukit/libcsupport/include/rtems/libio_.h658
-rw-r--r--cpukit/libcsupport/src/__usrenv.c247
-rw-r--r--cpukit/libcsupport/src/_rename_r.c125
-rw-r--r--cpukit/libcsupport/src/base_fs.c73
-rw-r--r--cpukit/libcsupport/src/chdir.c68
-rw-r--r--cpukit/libcsupport/src/chmod.c31
-rw-r--r--cpukit/libcsupport/src/chown.c42
-rw-r--r--cpukit/libcsupport/src/chroot.c91
-rw-r--r--cpukit/libcsupport/src/clonenode.c34
-rw-r--r--cpukit/libcsupport/src/close.c4
-rw-r--r--cpukit/libcsupport/src/eval.c151
-rw-r--r--cpukit/libcsupport/src/fchdir.c76
-rw-r--r--cpukit/libcsupport/src/fchmod.c22
-rw-r--r--cpukit/libcsupport/src/fchown.c22
-rw-r--r--cpukit/libcsupport/src/fcntl.c60
-rw-r--r--cpukit/libcsupport/src/freenode.c15
-rw-r--r--cpukit/libcsupport/src/ftruncate.c39
-rw-r--r--cpukit/libcsupport/src/getdents.c8
-rw-r--r--cpukit/libcsupport/src/lchown.c19
-rw-r--r--cpukit/libcsupport/src/libio.c114
-rw-r--r--cpukit/libcsupport/src/libio_sockets.c3
-rw-r--r--cpukit/libcsupport/src/link.c85
-rw-r--r--cpukit/libcsupport/src/lseek.c80
-rw-r--r--cpukit/libcsupport/src/lstat.c2
-rw-r--r--cpukit/libcsupport/src/mknod.c77
-rw-r--r--cpukit/libcsupport/src/mount.c326
-rw-r--r--cpukit/libcsupport/src/open.c261
-rw-r--r--cpukit/libcsupport/src/privateenv.c287
-rw-r--r--cpukit/libcsupport/src/readlink.c44
-rw-r--r--cpukit/libcsupport/src/rmdir.c100
-rw-r--r--cpukit/libcsupport/src/stat.c50
-rw-r--r--cpukit/libcsupport/src/statvfs.c41
-rw-r--r--cpukit/libcsupport/src/sup_fs_check_permissions.c66
-rw-r--r--cpukit/libcsupport/src/sup_fs_eval_path.c333
-rw-r--r--cpukit/libcsupport/src/sup_fs_eval_path_generic.c118
-rw-r--r--cpukit/libcsupport/src/sup_fs_exist_in_same_instance.c40
-rw-r--r--cpukit/libcsupport/src/sup_fs_get_start_loc.c48
-rw-r--r--cpukit/libcsupport/src/sup_fs_get_sym_start_loc.c47
-rw-r--r--cpukit/libcsupport/src/sup_fs_is_separator.c31
-rw-r--r--cpukit/libcsupport/src/sup_fs_location.c218
-rw-r--r--cpukit/libcsupport/src/sup_fs_mount_iterate.c44
-rw-r--r--cpukit/libcsupport/src/sup_fs_next_token.c58
-rw-r--r--cpukit/libcsupport/src/sup_fs_node_type.c32
-rw-r--r--cpukit/libcsupport/src/symlink.c44
-rw-r--r--cpukit/libcsupport/src/umask.c19
-rw-r--r--cpukit/libcsupport/src/unlink.c90
-rw-r--r--cpukit/libcsupport/src/unmount.c155
-rw-r--r--cpukit/libcsupport/src/utime.c41
50 files changed, 3654 insertions, 2624 deletions
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, &current_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(&current_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,
+ &currentloc->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;
}