summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2012-03-13 11:33:51 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2012-03-13 12:23:37 +0100
commit3b7c123c8d910eb60ab3b38dec6224e2de9847c9 (patch)
treea67335010c15af5efb5e27224ae9204883c2b5b8 /cpukit/libcsupport
parentAdd missing BSD sections. (diff)
downloadrtems-3b7c123c8d910eb60ab3b38dec6224e2de9847c9.tar.bz2
Filesystem: Reference counting for locations
o A new data structure rtems_filesystem_global_location_t was introduced to be used for o the mount point location in the mount table entry, o the file system root location in the mount table entry, o the root directory location in the user environment, and o the current directory location in the user environment. During the path evaluation global start locations are obtained to ensure that the current file system instance will be not unmounted in the meantime. o The user environment uses now reference counting and is protected from concurrent access. o The path evaluation process was completely rewritten and simplified. The IMFS, RFS, NFS, and DOSFS use now a generic path evaluation method. Recursive calls in the path evaluation have been replaced with iteration to avoid stack overflows. Only the evaluation of symbolic links is recursive. No dynamic memory allocations and intermediate buffers are used in the high level path evaluation. No global locks are held during the file system instance specific path evaluation process. o Recursive symbolic link evaluation is now limited by RTEMS_FILESYSTEM_SYMLOOP_MAX. Applications can retrieve this value via sysconf(). o The device file system (devFS) uses now no global variables and allocation from the workspace. Node names are allocated from the heap. o The upper layer lseek() performs now some parameter checks. o The upper layer ftruncate() performs now some parameter checks. o unmask() is now restricted to the RWX flags and protected from concurrent access. o The fchmod_h and rmnod_h file system node handlers are now a file system operation. o The unlink_h operation has been removed. All nodes are now destroyed with the rmnod_h operation. o New lock_h, unlock_h, clonenod_h, and are_nodes_equal_h file system operations. o The path evaluation and file system operations are now protected by per file system instance lock and unlock operations. o Fix and test file descriptor duplicate in fcntl(). o New test fstests/fsnofs01.
Diffstat (limited to 'cpukit/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;
}