summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/include/rtems/fs.h59
-rw-r--r--cpukit/include/rtems/userenv.h95
-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
-rw-r--r--cpukit/libfs/Makefile.am20
-rw-r--r--cpukit/libfs/src/defaults/default_are_nodes_equal.c27
-rw-r--r--cpukit/libfs/src/defaults/default_chown.c11
-rw-r--r--cpukit/libfs/src/defaults/default_clone.c26
-rw-r--r--cpukit/libfs/src/defaults/default_eval_path.c27
-rw-r--r--cpukit/libfs/src/defaults/default_evalformake.c32
-rw-r--r--cpukit/libfs/src/defaults/default_evalpath.c25
-rw-r--r--cpukit/libfs/src/defaults/default_evaluate_link.c23
-rw-r--r--cpukit/libfs/src/defaults/default_fchmod.c9
-rw-r--r--cpukit/libfs/src/defaults/default_fcntl.c4
-rw-r--r--cpukit/libfs/src/defaults/default_freenode.c13
-rw-r--r--cpukit/libfs/src/defaults/default_fstat.c14
-rw-r--r--cpukit/libfs/src/defaults/default_fsunmount.c3
-rw-r--r--cpukit/libfs/src/defaults/default_ftruncate.c5
-rw-r--r--cpukit/libfs/src/defaults/default_ftruncate_directory.c28
-rw-r--r--cpukit/libfs/src/defaults/default_handlers.c4
-rw-r--r--cpukit/libfs/src/defaults/default_link.c13
-rw-r--r--cpukit/libfs/src/defaults/default_lock_and_unlock.c33
-rw-r--r--cpukit/libfs/src/defaults/default_mknod.c14
-rw-r--r--cpukit/libfs/src/defaults/default_node_type.c2
-rw-r--r--cpukit/libfs/src/defaults/default_open.c14
-rw-r--r--cpukit/libfs/src/defaults/default_ops.c11
-rw-r--r--cpukit/libfs/src/defaults/default_readlink.c11
-rw-r--r--cpukit/libfs/src/defaults/default_rename.c14
-rw-r--r--cpukit/libfs/src/defaults/default_rmnod.c9
-rw-r--r--cpukit/libfs/src/defaults/default_statvfs.c9
-rw-r--r--cpukit/libfs/src/defaults/default_symlink.c12
-rw-r--r--cpukit/libfs/src/defaults/default_unlink.c22
-rw-r--r--cpukit/libfs/src/defaults/default_utime.c12
-rw-r--r--cpukit/libfs/src/devfs/devclose.c4
-rw-r--r--cpukit/libfs/src/devfs/devfs.h126
-rw-r--r--cpukit/libfs/src/devfs/devfs_eval.c131
-rw-r--r--cpukit/libfs/src/devfs/devfs_init.c114
-rw-r--r--cpukit/libfs/src/devfs/devfs_mknod.c95
-rw-r--r--cpukit/libfs/src/devfs/devfs_node_type.c2
-rw-r--r--cpukit/libfs/src/devfs/devfs_show.c42
-rw-r--r--cpukit/libfs/src/devfs/devioctl.c4
-rw-r--r--cpukit/libfs/src/devfs/devopen.c8
-rw-r--r--cpukit/libfs/src/devfs/devread.c4
-rw-r--r--cpukit/libfs/src/devfs/devstat.c39
-rw-r--r--cpukit/libfs/src/devfs/devwrite.c4
-rw-r--r--cpukit/libfs/src/dosfs/msdos.h125
-rw-r--r--cpukit/libfs/src/dosfs/msdos_create.c19
-rw-r--r--cpukit/libfs/src/dosfs/msdos_dir.c120
-rw-r--r--cpukit/libfs/src/dosfs/msdos_eval.c416
-rw-r--r--cpukit/libfs/src/dosfs/msdos_file.c88
-rw-r--r--cpukit/libfs/src/dosfs/msdos_free.c25
-rw-r--r--cpukit/libfs/src/dosfs/msdos_fsunmount.c22
-rw-r--r--cpukit/libfs/src/dosfs/msdos_handlers_dir.c6
-rw-r--r--cpukit/libfs/src/dosfs/msdos_handlers_file.c6
-rw-r--r--cpukit/libfs/src/dosfs/msdos_init.c43
-rw-r--r--cpukit/libfs/src/dosfs/msdos_initsupp.c6
-rw-r--r--cpukit/libfs/src/dosfs/msdos_misc.c97
-rw-r--r--cpukit/libfs/src/dosfs/msdos_mknod.c35
-rw-r--r--cpukit/libfs/src/dosfs/msdos_node_type.c8
-rw-r--r--cpukit/libfs/src/dosfs/msdos_rename.c42
-rw-r--r--cpukit/libfs/src/dosfs/msdos_rmnod.c79
-rw-r--r--cpukit/libfs/src/imfs/deviceio.c12
-rw-r--r--cpukit/libfs/src/imfs/fifoimfs_init.c16
-rw-r--r--cpukit/libfs/src/imfs/imfs.h186
-rw-r--r--cpukit/libfs/src/imfs/imfs_chown.c17
-rw-r--r--cpukit/libfs/src/imfs/imfs_creat.c47
-rw-r--r--cpukit/libfs/src/imfs/imfs_debug.c17
-rw-r--r--cpukit/libfs/src/imfs/imfs_directory.c131
-rw-r--r--cpukit/libfs/src/imfs/imfs_eval.c731
-rw-r--r--cpukit/libfs/src/imfs/imfs_fchmod.c10
-rw-r--r--cpukit/libfs/src/imfs/imfs_fifo.c14
-rw-r--r--cpukit/libfs/src/imfs/imfs_fsunmount.c33
-rw-r--r--cpukit/libfs/src/imfs/imfs_getchild.c66
-rw-r--r--cpukit/libfs/src/imfs/imfs_gtkn.c91
-rw-r--r--cpukit/libfs/src/imfs/imfs_handlers_device.c8
-rw-r--r--cpukit/libfs/src/imfs/imfs_handlers_directory.c12
-rw-r--r--cpukit/libfs/src/imfs/imfs_handlers_link.c8
-rw-r--r--cpukit/libfs/src/imfs/imfs_handlers_memfile.c8
-rw-r--r--cpukit/libfs/src/imfs/imfs_init.c20
-rw-r--r--cpukit/libfs/src/imfs/imfs_initsupp.c29
-rw-r--r--cpukit/libfs/src/imfs/imfs_link.c33
-rw-r--r--cpukit/libfs/src/imfs/imfs_load_tar.c78
-rw-r--r--cpukit/libfs/src/imfs/imfs_mknod.c98
-rw-r--r--cpukit/libfs/src/imfs/imfs_mount.c54
-rw-r--r--cpukit/libfs/src/imfs/imfs_ntype.c27
-rw-r--r--cpukit/libfs/src/imfs/imfs_readlink.c11
-rw-r--r--cpukit/libfs/src/imfs/imfs_rename.c56
-rw-r--r--cpukit/libfs/src/imfs/imfs_rmnod.c92
-rw-r--r--cpukit/libfs/src/imfs/imfs_stat.c53
-rw-r--r--cpukit/libfs/src/imfs/imfs_symlink.c37
-rw-r--r--cpukit/libfs/src/imfs/imfs_unlink.c82
-rw-r--r--cpukit/libfs/src/imfs/imfs_unmount.c63
-rw-r--r--cpukit/libfs/src/imfs/imfs_utime.c16
-rw-r--r--cpukit/libfs/src/imfs/ioman.c54
-rw-r--r--cpukit/libfs/src/imfs/memfile.c15
-rw-r--r--cpukit/libfs/src/imfs/miniimfs_init.c20
-rw-r--r--cpukit/libfs/src/nfsclient/src/librtemsNfs.h2
-rw-r--r--cpukit/libfs/src/nfsclient/src/nfs.c1165
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-dir.h41
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-file.c4
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-file.h4
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-link.c5
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c8
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c46
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c18
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-rtems-utils.c54
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-rtems.c884
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-rtems.h32
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-shell.c10
-rw-r--r--cpukit/libmisc/Makefile.am1
-rw-r--r--cpukit/libmisc/shell/main_lsof.c78
-rw-r--r--cpukit/libmisc/shell/shellconfig.h6
-rw-r--r--cpukit/libnetworking/lib/ftpfs.c107
-rw-r--r--cpukit/libnetworking/lib/tftpDriver.c319
-rw-r--r--cpukit/libnetworking/rtems/rtems_bsdnet_internal.h5
-rw-r--r--cpukit/libnetworking/rtems/rtems_syscall.c11
-rw-r--r--cpukit/posix/src/sysconf.c3
-rw-r--r--cpukit/sapi/include/confdefs.h37
166 files changed, 6155 insertions, 7519 deletions
diff --git a/cpukit/include/rtems/fs.h b/cpukit/include/rtems/fs.h
index 84b18370b5..bf5026f645 100644
--- a/cpukit/include/rtems/fs.h
+++ b/cpukit/include/rtems/fs.h
@@ -8,6 +8,9 @@
* COPYRIGHT (c) 1989-2011.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -18,6 +21,8 @@
#ifndef _RTEMS_FS_H
#define _RTEMS_FS_H
+#include <rtems/chain.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -31,9 +36,6 @@ extern "C" {
/* FIXME: shouldn't this better not be here? */
typedef struct rtems_libio_tt rtems_libio_t;
-typedef struct rtems_filesystem_location_info_tt
- rtems_filesystem_location_info_t;
-
struct rtems_filesystem_mount_table_entry_tt;
typedef struct rtems_filesystem_mount_table_entry_tt
rtems_filesystem_mount_table_entry_t;
@@ -43,18 +45,57 @@ typedef struct _rtems_filesystem_file_handlers_r
typedef struct _rtems_filesystem_operations_table
rtems_filesystem_operations_table;
-/*
- * Structure used to determine a location/filesystem in the tree.
+/**
+ * @brief File system location.
+ *
+ * @ingroup LibIO
*/
-
-struct rtems_filesystem_location_info_tt
-{
+typedef struct rtems_filesystem_location_info_tt {
+ rtems_chain_node mt_entry_node;
void *node_access;
void *node_access_2;
const rtems_filesystem_file_handlers_r *handlers;
const rtems_filesystem_operations_table *ops;
rtems_filesystem_mount_table_entry_t *mt_entry;
-};
+} rtems_filesystem_location_info_t;
+
+/**
+ * @brief Global file system location.
+ *
+ * @ingroup LibIO
+ *
+ * The global file system locations are used for
+ * - the mount point location in the mount table entry,
+ * - the file system root location in the mount table entry,
+ * - the root directory location in the user environment, and
+ * - the current directory location in the user environment.
+ *
+ * During the path evaluation global start locations are obtained to ensure
+ * that the current file system will be not unmounted in the meantime.
+ *
+ * To support a release within critical sections of the operating system a
+ * deferred release is supported. This is similar to malloc() and free().
+ *
+ * @see rtems_filesystem_global_location_obtain() and
+ * rtems_filesystem_global_location_release().
+ */
+typedef struct rtems_filesystem_global_location_t {
+ rtems_filesystem_location_info_t location;
+ int reference_count;
+
+ /**
+ * A release within a critical section of the operating system will add this
+ * location to a list of deferred released locations. This list is processed
+ * in the next rtems_filesystem_global_location_obtain() in FIFO order.
+ */
+ struct rtems_filesystem_global_location_t *deferred_released_next;
+
+ /**
+ * A release within a critical section can happen multiple times. This field
+ * counts the deferred releases.
+ */
+ int deferred_released_count;
+} rtems_filesystem_global_location_t;
/*
* Return the mount table entry for a path location.
diff --git a/cpukit/include/rtems/userenv.h b/cpukit/include/rtems/userenv.h
index 28ac69ebd3..123da98af5 100644
--- a/cpukit/include/rtems/userenv.h
+++ b/cpukit/include/rtems/userenv.h
@@ -1,13 +1,16 @@
/**
- * @file rtems/userenv.h
+ * @file
*
- * This file defines the interface for POSIX per-process environment.
+ * @ingroup LibIOEnv
*/
/*
* COPYRIGHT (c) 1989-2011.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -18,6 +21,13 @@
#ifndef _RTEMS_USERENV_H
#define _RTEMS_USERENV_H
+/*
+ * According to IEEE Std 1003.1-2001,
+ * limits.h is supposed to provide _POSIX_LOGIN_NAME_MAX
+ * XXX: We do not rely on this.
+ */
+#include <limits.h>
+
#include <rtems.h>
#include <rtems/fs.h>
@@ -25,33 +35,30 @@
extern "C" {
#endif
-/*
- * External structures
- */
-
-/*
- * According to IEEE Std 1003.1-2001,
- * limits.h is supposed to provide _POSIX_LOGIN_NAME_MAX
- * FIXME: We should not rely on this.
+/**
+ * @defgroup LibIOEnv User Environment
+ *
+ * @ingroup LibIO
+ *
+ * @brief Provides a POSIX like user environment for tasks.
+ *
+ * @{
*/
-#include <limits.h>
#ifndef LOGIN_NAME_MAX
-#ifdef _POSIX_LOGIN_NAME_MAX
-#define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX
-#else
-/* Fallback */
-#define LOGIN_NAME_MAX 9
-#endif
+ #ifdef _POSIX_LOGIN_NAME_MAX
+ #define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX
+ #else
+ /* Fallback */
+ #define LOGIN_NAME_MAX 9
+ #endif
#endif
typedef struct {
- rtems_id task_id;
- rtems_filesystem_location_info_t current_directory;
- rtems_filesystem_location_info_t root_directory;
+ rtems_filesystem_global_location_t *current_directory;
+ rtems_filesystem_global_location_t *root_directory;
/* Default mode for all files. */
mode_t umask;
- nlink_t link_counts;
/* _POSIX_types */
uid_t uid;
gid_t gid;
@@ -59,6 +66,9 @@ typedef struct {
gid_t egid;
char login_buffer[LOGIN_NAME_MAX];
pid_t pgrp; /* process group id */
+ /* User environment maintenance */
+ rtems_id task_id;
+ int reference_count;
} rtems_user_env_t;
extern rtems_user_env_t * rtems_current_user_env;
@@ -66,7 +76,6 @@ extern rtems_user_env_t rtems_global_user_env;
#define rtems_filesystem_current (rtems_current_user_env->current_directory)
#define rtems_filesystem_root (rtems_current_user_env->root_directory)
-#define rtems_filesystem_link_counts (rtems_current_user_env->link_counts)
#define rtems_filesystem_umask (rtems_current_user_env->umask)
#define _POSIX_types_Uid (rtems_current_user_env->uid)
@@ -75,14 +84,48 @@ extern rtems_user_env_t rtems_global_user_env;
#define _POSIX_types_Egid (rtems_current_user_env->egid)
#define _POSIX_types_Getlogin_buffer (rtems_current_user_env->login_buffer)
-
-/*
- * Instantiate a private copy of the per user information for the calling task.
+/**
+ * @brief Creates a private environment.
+ *
+ * If the task has already a private environment nothing will be changed. This
+ * function must be called from normal thread context and may block on a mutex.
+ * Thread dispatching is disabled to protect some critical sections.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_NO_MEMORY Not enough memory.
+ * @retval RTEMS_UNSATISFIED Cloning of the current environment failed.
+ * @retval RTEMS_TOO_MANY Cannot register the private environment.
*/
-
rtems_status_code rtems_libio_set_private_env(void);
+
+/**
+ * @brief Creates a private environment shared with another task.
+ *
+ * An attempt to share the environment with itself has no effect. This
+ * function must be called from normal thread context and may block on a mutex.
+ * Thread dispatching is disabled to protect some critical sections.
+ *
+ * @param[in] task_id The private environment is shared with the task specified
+ * by this identifier.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_UNSATISFIED No shared environment is available for this task
+ * @retval RTEMS_TOO_MANY Cannot register the shared environment.
+ * identifier.
+ */
rtems_status_code rtems_libio_share_private_env(rtems_id task_id) ;
+/**
+ * @brief Use the global environment.
+ *
+ * A private environment will be released. This function may be called from
+ * every thread context. Thread dispatching is disabled to protect the
+ * critical sections.
+ */
+void rtems_libio_use_global_env(void);
+
+/** @} */
+
#ifdef __cplusplus
}
#endif
diff --git a/cpukit/libcsupport/Makefile.am b/cpukit/libcsupport/Makefile.am
index 15e55a1e51..321eb29597 100644
--- a/cpukit/libcsupport/Makefile.am
+++ b/cpukit/libcsupport/Makefile.am
@@ -57,7 +57,7 @@ ASSOCIATION_C_FILES = src/assoclocalbyname.c \
BASE_FS_C_FILES = src/base_fs.c src/mount.c src/unmount.c src/libio.c \
src/mount-mgr.c src/mount-mktgt.c src/libio_init.c \
- src/eval.c src/privateenv.c \
+ src/privateenv.c \
src/open_dev_console.c src/__usrenv.c src/rtems_mkdir.c
if LIBNETWORKING
@@ -99,7 +99,7 @@ ID_C_FILES = src/getegid.c src/geteuid.c src/getgid.c src/getgroups.c \
MALLOC_C_FILES = src/malloc_initialize.c src/calloc.c src/malloc.c \
src/realloc.c src/_calloc_r.c src/_malloc_r.c \
- src/free.c src/freenode.c src/_free_r.c \
+ src/free.c src/_free_r.c \
src/_realloc_r.c src/mallocfreespace.c \
src/mallocgetheapptr.c src/mallocsetheapptr.c \
src/mallocinfo.c src/malloc_walk.c src/malloc_get_statistics.c \
@@ -127,8 +127,16 @@ BSD_LIBC_C_FILES = src/strlcpy.c src/strlcat.c src/issetugid.c
libcsupport_a_SOURCES = src/gxx_wrappers.c src/getchark.c src/printk.c \
src/printk_plugin.c src/putk.c src/vprintk.c \
- src/sup_fs_is_separator.c src/sup_fs_get_start_loc.c \
- src/sup_fs_get_sym_start_loc.c \
+ src/sup_fs_location.c \
+ src/sup_fs_eval_path.c \
+ src/sup_fs_eval_path_generic.c \
+ src/sup_fs_check_permissions.c \
+ src/sup_fs_next_token.c \
+ src/sup_fs_exist_in_same_instance.c \
+ src/sup_fs_mount_iterate.c \
+ src/sup_fs_node_type.c \
+ src/clonenode.c \
+ src/freenode.c \
$(BSD_LIBC_C_FILES) $(BASE_FS_C_FILES) $(MALLOC_C_FILES) \
$(ERROR_C_FILES) $(ASSOCIATION_C_FILES)
diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h
index 661fe0bc33..4a09e0c18b 100644
--- a/cpukit/libcsupport/include/rtems/libio.h
+++ b/cpukit/libcsupport/include/rtems/libio.h
@@ -10,6 +10,9 @@
* COPYRIGHT (c) 1989-2008.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -37,20 +40,15 @@ extern "C" {
#endif
/**
- * @defgroup LibIO IO Library
+ * @defgroup LibIOFSOps File System Operations
*
- * @brief Provides system call and file system interface definitions.
+ * @ingroup LibIO
*
- * General purpose communication channel for RTEMS to allow UNIX/POSIX
- * system call behavior under RTEMS. Initially this supported only
- * IO to devices but has since been enhanced to support networking
- * and support for mounted file systems.
+ * @brief File system operations.
*
* @{
*/
-typedef off_t rtems_off64_t __attribute__((deprecated));
-
/**
* @brief File system node types.
*/
@@ -64,974 +62,1044 @@ typedef enum {
} rtems_filesystem_node_types_t;
/**
- * @name File System Node Operations
+ * @brief Locks a file system instance.
*
- * @{
+ * This lock must allow nesting.
+ *
+ * @param[in, out] mt_entry The mount table entry of the file system instance.
+ *
+ * @see rtems_filesystem_default_lock().
*/
+typedef void (*rtems_filesystem_mt_entry_lock_t)(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
/**
- * This type defines the interface to the open(2) system call
- * support which is provided by a file system implementation.
+ * @brief Unlocks a file system instance.
+ *
+ * @param[in, out] mt_entry The mount table entry of the file system instance.
+ *
+ * @see rtems_filesystem_default_unlock().
*/
-typedef int (*rtems_filesystem_open_t)(
- rtems_libio_t *iop,
- const char *pathname,
- uint32_t flag,
- uint32_t mode
+typedef void (*rtems_filesystem_mt_entry_unlock_t)(
+ rtems_filesystem_mount_table_entry_t *mt_entry
);
/**
- * This type defines the interface to the close(2) system call
- * support which is provided by a file system implementation.
+ * @brief Path evaluation context.
*/
-typedef int (*rtems_filesystem_close_t)(
- rtems_libio_t *iop
-);
+typedef struct {
+ /**
+ * The contents of the remaining path to be evaluated.
+ */
+ const char *path;
+
+ /**
+ * The length of the remaining path to be evaluated.
+ */
+ size_t pathlen;
+
+ /**
+ * The contents of the token to be evaluated with respect to the current
+ * location.
+ */
+ const char *token;
+
+ /**
+ * The length of the token to be evaluated with respect to the current
+ * location.
+ */
+ size_t tokenlen;
+
+ /**
+ * The path evaluation is controlled by the following flags
+ * - RTEMS_LIBIO_PERMS_READ,
+ * - RTEMS_LIBIO_PERMS_WRITE,
+ * - RTEMS_LIBIO_PERMS_EXEC,
+ * - RTEMS_LIBIO_PERMS_SEARCH,
+ * - RTEMS_LIBIO_FOLLOW_HARD_LINK,
+ * - RTEMS_LIBIO_FOLLOW_SYM_LINK,
+ * - RTEMS_LIBIO_MAKE,
+ * - RTEMS_LIBIO_EXCLUSIVE,
+ * - RTEMS_LIBIO_ACCEPT_RESIDUAL_DELIMITERS, and
+ * - RTEMS_LIBIO_REJECT_TERMINAL_DOT.
+ */
+ int flags;
+
+ /**
+ * Symbolic link evaluation is a recursive operation. This field helps to
+ * limit the recursion level and thus prevents a stack overflow. The
+ * recursion level is limited by RTEMS_FILESYSTEM_SYMLOOP_MAX.
+ */
+ int recursionlevel;
+
+ /**
+ * This is the current file system location of the evaluation process.
+ * Tokens are evaluated with respect to the current location. The token
+ * interpretation may change the current location. The purpose of the path
+ * evaluation is to change the start location into a final current location
+ * according to the path.
+ */
+ rtems_filesystem_location_info_t currentloc;
+
+ /**
+ * The location of the root directory of the user environment during the
+ * evaluation start.
+ */
+ rtems_filesystem_global_location_t *rootloc;
+
+ /**
+ * The start location of the evaluation process. The start location my
+ * change during symbolic link evaluation.
+ */
+ rtems_filesystem_global_location_t *startloc;
+} rtems_filesystem_eval_path_context_t;
/**
- * This type defines the interface to the read(2) system call
- * support which is provided by a file system implementation.
+ * @brief Path evaluation.
+ *
+ * @param[in, out] ctx The path evaluation context.
+ *
+ * @see rtems_filesystem_default_eval_path().
*/
-typedef ssize_t (*rtems_filesystem_read_t)(
- rtems_libio_t *iop,
- void *buffer,
- size_t count
+typedef void (*rtems_filesystem_eval_path_t)(
+ rtems_filesystem_eval_path_context_t *ctx
);
/**
- * This type defines the interface to the write(2) system call
- * support which is provided by a file system implementation.
+ * @brief Creates a new link for the existing file.
+ *
+ * @param[in] parentloc The location of the parent of the new link.
+ * @param[in] targetloc The location of the target file.
+ * @param[in] name Name for the new link.
+ * @param[in] namelen Length of the name for the new link in characters.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_link().
*/
-typedef ssize_t (*rtems_filesystem_write_t)(
- rtems_libio_t *iop,
- const void *buffer,
- size_t count
+typedef int (*rtems_filesystem_link_t)(
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *targetloc,
+ const char *name,
+ size_t namelen
);
/**
- * This type defines the interface to the ioctl(2) system call
- * support which is provided by a file system implementation.
+ * @brief Changes the mode of a node.
+ *
+ * @param[in] loc The location of the node.
+ * @param[in] mode The new mode of the node
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_fchmod().
*/
-typedef int (*rtems_filesystem_ioctl_t)(
- rtems_libio_t *iop,
- uint32_t command,
- void *buffer
+typedef int (*rtems_filesystem_fchmod_t)(
+ const rtems_filesystem_location_info_t *loc,
+ mode_t mode
);
/**
- * This type defines the interface to the lseek(2) system call
- * support which is provided by a file system implementation.
+ * @brief Changes owner and group of a node.
+ *
+ * @param[in] loc The location of the node.
+ * @param[in] owner User ID for the node.
+ * @param[in] group Group ID for the node.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_chown().
*/
-typedef off_t (*rtems_filesystem_lseek_t)(
- rtems_libio_t *iop,
- off_t length,
- int whence
+typedef int (*rtems_filesystem_chown_t)(
+ const rtems_filesystem_location_info_t *loc,
+ uid_t owner,
+ gid_t group
);
/**
- * This type defines the interface to the fstat(2) system call
- * support which is provided by a file system implementation.
+ * @brief Clones a location.
+ *
+ * The location is initialized with a bitwise copy of an existing location.
+ * The caller must ensure that this location is protected from a release during
+ * the clone operation. After a successful clone operation the clone will be
+ * added to the location chain of the corresponding mount table entry.
+ *
+ * @param[in, out] loc Location to clone.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_clonenode().
*/
-typedef int (*rtems_filesystem_fstat_t)(
- rtems_filesystem_location_info_t *loc,
- struct stat *buf
+typedef int (*rtems_filesystem_clonenode_t)(
+ rtems_filesystem_location_info_t *loc
);
/**
- * This type defines the interface to the fchmod(2) system call
- * support which is provided by a file system implementation.
+ * @brief Frees the location of a node.
+ *
+ * @param[in] loc The location of the node.
+ *
+ * @see rtems_filesystem_default_freenode().
*/
-typedef int (*rtems_filesystem_fchmod_t)(
- rtems_filesystem_location_info_t *loc,
- mode_t mode
+typedef void (*rtems_filesystem_freenode_t)(
+ const rtems_filesystem_location_info_t *loc
);
/**
- * This type defines the interface to the ftruncate(2) system call
- * support which is provided by a file system implementation.
+ * @brief Mounts a file system instance in a mount point (directory).
+ *
+ * The mount point belongs to the file system instance of the handler and is
+ * specified by a field of the mount table entry. The handler must check that
+ * the mount point is capable of mounting a file system instance. This is the
+ * last step during the mount process. The file system instance is fully
+ * initialized at this point.
+ *
+ * @param[in] mt_entry The mount table entry.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_mount().
*/
-typedef int (*rtems_filesystem_ftruncate_t)(
- rtems_libio_t *iop,
- off_t length
+typedef int (*rtems_filesystem_mount_t) (
+ rtems_filesystem_mount_table_entry_t *mt_entry
);
/**
- * This type defines the interface to the fsync(2) system call
- * support which is provided by a file system implementation.
+ * @brief Initializes a file system instance.
+ *
+ * This function must initialize the file system root node in the mount table
+ * entry.
+ *
+ * @param[in] mt_entry The mount table entry.
+ * @param[in] data The data provided by the user.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
*/
-typedef int (*rtems_filesystem_fsync_t)(
- rtems_libio_t *iop
+typedef int (*rtems_filesystem_fsmount_me_t)(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ const void *data
);
/**
- * This type defines the interface to the fdatasync(2) system call
- * support which is provided by a file system implementation.
+ * @brief Unmounts a file system instance in a mount point (directory).
+ *
+ * In case this function is successful the file system instance will be marked
+ * as unmounted. The file system instance will be destroyed when the last
+ * reference to it vanishes.
+ *
+ * @param[in] mt_entry The mount table entry.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_unmount().
*/
-typedef int (*rtems_filesystem_fdatasync_t)(
- rtems_libio_t *iop
+typedef int (*rtems_filesystem_unmount_t) (
+ rtems_filesystem_mount_table_entry_t *mt_entry
);
/**
- * This type defines the interface to the fnctl(2) system call
- * support which is provided by a file system implementation.
+ * @brief Destroys a file system instance.
+ *
+ * The mount point node location of the mount table entry is invalid. This
+ * handler must free the file system root location and all remaining resources
+ * of the file system instance.
+ *
+ * @param[in] mt_entry The mount table entry.
+ *
+ * @see rtems_filesystem_default_fsunmount().
*/
-typedef int (*rtems_filesystem_fcntl_t)(
- int cmd,
- rtems_libio_t *iop
+typedef void (*rtems_filesystem_fsunmount_me_t)(
+ rtems_filesystem_mount_table_entry_t *mt_entry
);
-typedef int (*rtems_filesystem_rmnod_t)(
- rtems_filesystem_location_info_t *parent_loc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */
+/**
+ * @brief Tests if the node of one location is equal to the node of the other
+ * location.
+ *
+ * The caller ensures that both nodes are within the same file system instance.
+ *
+ * @param[in] a The one location.
+ * @param[in] b The other location.
+ *
+ * @retval true The nodes of the locations are equal.
+ * @retval false Otherwise.
+ *
+ * @see rtems_filesystem_default_are_nodes_equal().
+ */
+typedef bool (*rtems_filesystem_are_nodes_equal_t)(
+ const rtems_filesystem_location_info_t *a,
+ const rtems_filesystem_location_info_t *b
);
-/** @} */
-
/**
- * @brief File system node operations table.
+ * @brief Returns the node type.
+ *
+ * @param[in] loc The location of the node.
+ *
+ * @return Type of the node.
+ *
+ * @see rtems_filesystem_default_node_type().
*/
-struct _rtems_filesystem_file_handlers_r {
- /**
- * This field points to the file system specific implementation
- * of the support routine for the open(2) system call
- *
- * @note This method must have a filesystem specific implementation.
- *
- * @note There is no default implementation.
- */
- rtems_filesystem_open_t open_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the close(2) system call
- *
- * @note This method is REQUIRED by all file systems.
- *
- * @note There is no default implementation.
- */
- rtems_filesystem_close_t close_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the read(2) system call
- *
- * @note This method must have a filesystem specific implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_read_t read_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the write(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_write_t write_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the ioctl(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_ioctl_t ioctl_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the lseek(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_lseek_t lseek_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the fstat(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_fstat_t fstat_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the fchmod(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_fchmod_t fchmod_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the ftruncate(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_ftruncate_t ftruncate_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the fsync(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_fsync_t fsync_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the fdatasync(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_fdatasync_t fdatasync_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the fcntl(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_fcntl_t fcntl_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the rmnod(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_rmnod_t rmnod_h;
-};
-
-extern const rtems_filesystem_file_handlers_r
-rtems_filesystem_handlers_default;
+typedef rtems_filesystem_node_types_t (*rtems_filesystem_node_type_t)(
+ const rtems_filesystem_location_info_t *loc
+);
/**
- * This method defines the interface to the default open(2)
- * system call support which is provided by a file system
- * implementation.
+ * @brief Creates a new node.
+ *
+ * This handler should create a new node according to the parameters.
+ *
+ * @param[in] parentloc The location of the parent of the new node.
+ * @param[in] name Name for the new node.
+ * @param[in] namelen Length of the name for the new node in characters.
+ * @param[in] mode Mode for the new node.
+ * @param[in] dev Optional device identifier for the new node.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_mknod().
*/
-int rtems_filesystem_default_open(
- rtems_libio_t *iop,
- const char *pathname,
- uint32_t flag,
- uint32_t mode
+typedef int (*rtems_filesystem_mknod_t)(
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
);
/**
- * This method defines the interface to the default close(2)
- * system call support which is provided by a file system
- * implementation.
+ * @brief Removes a node.
+ *
+ * @param[in] parentloc The location of the parent of the node.
+ * @param[in] loc The location of the node.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_rmnod().
*/
-int rtems_filesystem_default_close(
- rtems_libio_t *iop
+typedef int (*rtems_filesystem_rmnod_t)(
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *loc
);
-
/**
- * This method defines the interface to the default read(2)
- * system call support which is provided by a file system
- * implementation.
+ * @brief Set node access and modification times.
+ *
+ * @param[in] loc The location of the node.
+ * @param[in] actime Access time for the node.
+ * @param[in] modtime Modification for the node.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_utime().
*/
-ssize_t rtems_filesystem_default_read(
- rtems_libio_t *iop,
- void *buffer,
- size_t count
+typedef int (*rtems_filesystem_utime_t)(
+ const rtems_filesystem_location_info_t *loc,
+ time_t actime,
+ time_t modtime
);
/**
- * This method defines the interface to the default write(2) system call
- * support which is provided by a file system implementation.
+ * @brief Makes a symbolic link to a node.
+ *
+ * @param[in] parentloc The location of the parent of the new symbolic link.
+ * @param[in] name Name for the new symbolic link.
+ * @param[in] namelen Length of the name for the new symbolic link in
+ * characters.
+ * @param[in] target Contents for the symbolic link.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_symlink().
*/
-ssize_t rtems_filesystem_default_write(
- rtems_libio_t *iop,
- const void *buffer,
- size_t count
+typedef int (*rtems_filesystem_symlink_t)(
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ const char *target
);
/**
- * This method defines the interface to the default ioctl(2) system call
- * support which is provided by a file system implementation.
+ * @brief Reads the contents of a symbolic link.
+ *
+ * @param[in] loc The location of the symbolic link.
+ * @param[out] buf The buffer for the contents.
+ * @param[in] bufsize The size of the buffer in characters.
+ *
+ * @retval non-negative Size of the actual contents in characters.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_readlink().
*/
-int rtems_filesystem_default_ioctl(
- rtems_libio_t *iop,
- uint32_t command,
- void *buffer
+typedef ssize_t (*rtems_filesystem_readlink_t)(
+ const rtems_filesystem_location_info_t *loc,
+ char *buf,
+ size_t bufsize
);
/**
- * This method defines the interface to the default lseek(2) system call
- * support which is provided by a file system implementation.
+ * @brief Renames a node.
+ *
+ * @param[in] oldparentloc The location of the parent of the old node.
+ * @param[in] oldloc The location of the old node.
+ * @param[in] newparentloc The location of the parent of the new node.
+ * @param[in] name Name for the new node.
+ * @param[in] namelen Length of the name for the new node in characters.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_rename().
*/
-off_t rtems_filesystem_default_lseek(
- rtems_libio_t *iop,
- off_t length,
- int whence
+typedef int (*rtems_filesystem_rename_t)(
+ const rtems_filesystem_location_info_t *oldparentloc,
+ const rtems_filesystem_location_info_t *oldloc,
+ const rtems_filesystem_location_info_t *newparentloc,
+ const char *name,
+ size_t namelen
);
/**
- * This method defines the interface to the default fstat(2) system call
- * support which is provided by a file system implementation.
+ * @brief Gets file system information.
+ *
+ * @param[in] loc The location of a node.
+ * @param[out] buf Buffer for file system information.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_statvfs().
*/
-int rtems_filesystem_default_fstat(
- rtems_filesystem_location_info_t *loc,
- struct stat *buf
+typedef int (*rtems_filesystem_statvfs_t)(
+ const rtems_filesystem_location_info_t *loc,
+ struct statvfs *buf
);
/**
- * This method defines the interface to the default fchmod(2) system call
- * support which is provided by a file system implementation.
+ * @brief File system operations table.
*/
-int rtems_filesystem_default_fchmod(
- rtems_filesystem_location_info_t *loc,
- mode_t mode
-);
+struct _rtems_filesystem_operations_table {
+ rtems_filesystem_mt_entry_lock_t lock_h;
+ rtems_filesystem_mt_entry_unlock_t unlock_h;
+ rtems_filesystem_eval_path_t eval_path_h;
+ rtems_filesystem_link_t link_h;
+ rtems_filesystem_are_nodes_equal_t are_nodes_equal_h;
+ rtems_filesystem_node_type_t node_type_h;
+ rtems_filesystem_mknod_t mknod_h;
+ rtems_filesystem_rmnod_t rmnod_h;
+ rtems_filesystem_fchmod_t fchmod_h;
+ rtems_filesystem_chown_t chown_h;
+ rtems_filesystem_clonenode_t clonenod_h;
+ rtems_filesystem_freenode_t freenod_h;
+ rtems_filesystem_mount_t mount_h;
+ rtems_filesystem_fsmount_me_t fsmount_me_h;
+ rtems_filesystem_unmount_t unmount_h;
+ rtems_filesystem_fsunmount_me_t fsunmount_me_h;
+ rtems_filesystem_utime_t utime_h;
+ rtems_filesystem_symlink_t symlink_h;
+ rtems_filesystem_readlink_t readlink_h;
+ rtems_filesystem_rename_t rename_h;
+ rtems_filesystem_statvfs_t statvfs_h;
+};
/**
- * This method defines the interface to the default ftruncate(2) system call
- * support which is provided by a file system implementation.
+ * @brief File system operations table with default operations.
*/
-int rtems_filesystem_default_ftruncate(
- rtems_libio_t *iop,
- off_t length
-);
+extern const rtems_filesystem_operations_table
+ rtems_filesystem_operations_default;
/**
- * This method defines the interface to the default fsync(2) system call
- * support which is provided by a file system implementation.
+ * @brief Obtains the IO library mutex.
+ *
+ * @see rtems_filesystem_mt_entry_lock_t.
*/
-int rtems_filesystem_default_fsync(
- rtems_libio_t *iop
+void rtems_filesystem_default_lock(
+ rtems_filesystem_mount_table_entry_t *mt_entry
);
/**
- * This method defines the interface to the default fdatasync(2) system call
- * support which is provided by a file system implementation.
+ * @brief Releases the IO library mutex.
+ *
+ * @see rtems_filesystem_mt_entry_unlock_t.
*/
-int rtems_filesystem_default_fdatasync(
- rtems_libio_t *iop
+void rtems_filesystem_default_unlock(
+ rtems_filesystem_mount_table_entry_t *mt_entry
);
/**
- * This method defines the interface to the default fnctl(2) system call
- * support which is provided by a file system implementation.
+ * @brief Terminates the path evaluation and replaces the current location with
+ * the null location.
+ *
+ * @see rtems_filesystem_eval_path_t.
*/
-int rtems_filesystem_default_fcntl(
- int cmd,
- rtems_libio_t *iop
+void rtems_filesystem_default_eval_path(
+ rtems_filesystem_eval_path_context_t *ctx
);
/**
- * This method defines the interface to the default rmnod(2) system call
- * support which is provided by a file system implementation.
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_link_t.
*/
-int rtems_filesystem_default_rmnod(
- rtems_filesystem_location_info_t *parent_loc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */
+int rtems_filesystem_default_link(
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *targetloc,
+ const char *name,
+ size_t namelen
);
/**
- * @name File System Operations
+ * @brief Tests if the node access pointer of one location is equal to
+ * the node access pointer of the other location.
*
- * @{
+ * @param[in] a The one location.
+ * @param[in] b The other location.
+ *
+ * @retval true The node access pointers of the locations are equal.
+ * @retval false Otherwise.
+ *
+ * @see rtems_filesystem_are_nodes_equal_t.
*/
+bool rtems_filesystem_default_are_nodes_equal(
+ const rtems_filesystem_location_info_t *a,
+ const rtems_filesystem_location_info_t *b
+);
/**
- * This type defines the interface to the mknod(2) system call
- * support which is provided by a file system implementation.
- *
- * @note This routine does not allocate any space and
- * rtems_filesystem_freenode_t is not called by the generic
- * after calling this routine. ie. node_access does not have
- * to contain valid data when the routine returns.
+ * @retval RTEMS_FILESYSTEM_INVALID_NODE_TYPE Always.
+ *
+ * @see rtems_filesystem_node_type_t.
*/
-typedef int (*rtems_filesystem_mknod_t)(
- const char *path, /* IN */
- mode_t mode, /* IN */
- dev_t dev, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+rtems_filesystem_node_types_t rtems_filesystem_default_node_type(
+ const rtems_filesystem_location_info_t *pathloc
);
/**
- * This type defines the interface that allows the
- * file system implementation to parse a path and
- * allocate any memory necessary for tracking purposes.
+ * @retval -1 Always. The errno is set to ENOTSUP.
*
- * @note rtems_filesystem_freenode_t must be called by
- * the generic after calling this routine
+ * @see rtems_filesystem_mknod_t.
*/
-typedef int (*rtems_filesystem_evalpath_t)(
- const char *pathname, /* IN */
- size_t pathnamelen, /* IN */
- int flags, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+int rtems_filesystem_default_mknod(
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
);
/**
- * This type defines the interface that allows the
- * file system implementation to parse a path with the
- * intent of creating a new node and to
- * allocate any memory necessary for tracking purposes.
+ * @retval -1 Always. The errno is set to ENOTSUP.
*
- * @note rtems_filesystem_freenode_t must be called by
- * the generic after calling this routine
+ * @see rtems_filesystem_rmnod_t.
*/
-typedef int (*rtems_filesystem_evalmake_t)(
- const char *path, /* IN */
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- const char **name /* OUT */
+int rtems_filesystem_default_rmnod(
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *loc
);
/**
- * This type defines the interface to the link(2) system call
- * support which is provided by a file system implementation.
- */
-typedef int (*rtems_filesystem_link_t)(
- rtems_filesystem_location_info_t *to_loc, /* IN */
- rtems_filesystem_location_info_t *parent_loc, /* IN */
- const char *name /* IN */
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_fchmod_t.
+ */
+int rtems_filesystem_default_fchmod(
+ const rtems_filesystem_location_info_t *loc,
+ mode_t mode
);
/**
- * This type defines the interface to the unlink(2) system call
- * support which is provided by a file system implementation.
- */
-typedef int (*rtems_filesystem_unlink_t)(
- rtems_filesystem_location_info_t *parent_pathloc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_chown_t.
+ */
+int rtems_filesystem_default_chown(
+ const rtems_filesystem_location_info_t *loc,
+ uid_t owner,
+ gid_t group
);
/**
- * This type defines the interface to the chown(2) system call
- * support which is provided by a file system implementation.
- */
-typedef int (*rtems_filesystem_chown_t)(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- uid_t owner, /* IN */
- gid_t group /* IN */
+ * @retval 0 Always.
+ *
+ * @see rtems_filesystem_clonenode_t.
+ */
+int rtems_filesystem_default_clonenode(
+ rtems_filesystem_location_info_t *loc
);
/**
- * This type defines the interface to the freenod(2) system call
- * support which is provided by a file system implementation.
- */
-typedef int (*rtems_filesystem_freenode_t)(
- rtems_filesystem_location_info_t *pathloc /* IN */
+ * @see rtems_filesystem_freenode_t.
+ */
+void rtems_filesystem_default_freenode(
+ const rtems_filesystem_location_info_t *loc
);
/**
- * This type defines the interface that allows the implemented
- * filesystem ot mount another filesystem at the given location.
- */
-typedef int (* rtems_filesystem_mount_t ) (
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_mount_t.
+ */
+int rtems_filesystem_default_mount (
rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
);
/**
- * This type defines the interface that allows a file system
- * implementation to do any necessary work that is needed when
- * it is being mounted.
- */
-typedef int (* rtems_filesystem_fsmount_me_t )(
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_fsmount_me_t.
+ */
+int rtems_filesystem_default_fsmount(
rtems_filesystem_mount_table_entry_t *mt_entry, /* IN */
const void *data /* IN */
);
/**
- * This type defines the interface allow the filesystem to
- * unmount a filesystem that was mounted at one of its node
- * locations.
- */
-typedef int (* rtems_filesystem_unmount_t ) (
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_unmount_t.
+ */
+int rtems_filesystem_default_unmount(
rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
);
/**
- * This type defines the interface that allows a file system
- * implementation to do any necessary work that is needed when
- * it is being unmounted.
- */
-typedef int (* rtems_filesystem_fsunmount_me_t ) (
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_fsunmount_me_t.
+ */
+void rtems_filesystem_default_fsunmount(
rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
);
/**
- * This type defines the interface that will return the
- * type of a filesystem implementations node.
- */
-typedef rtems_filesystem_node_types_t (* rtems_filesystem_node_type_t) (
- rtems_filesystem_location_info_t *pathloc /* IN */
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_utime_t.
+ */
+int rtems_filesystem_default_utime(
+ const rtems_filesystem_location_info_t *loc,
+ time_t actime,
+ time_t modtime
);
/**
- * This type defines the interface to the time(2) system call
- * support which is provided by a file system implementation.
- */
-typedef int (* rtems_filesystem_utime_t)(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- time_t actime, /* IN */
- time_t modtime /* IN */
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_symlink_t.
+ */
+int rtems_filesystem_default_symlink(
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ const char *target
);
/**
- * This type defines the interface to the link(2) system call
- * support which is provided by a file system implementation.
- */
-typedef int (*rtems_filesystem_evaluate_link_t)(
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- int flags /* IN */
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_readlink_t.
+ */
+ssize_t rtems_filesystem_default_readlink(
+ const rtems_filesystem_location_info_t *loc,
+ char *buf,
+ size_t bufsize
);
/**
- * This type defines the interface to the symlink(2) system call
- * support which is provided by a file system implementation.
- */
-typedef int (*rtems_filesystem_symlink_t)(
- rtems_filesystem_location_info_t *loc, /* IN */
- const char *link_name, /* IN */
- const char *node_name
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_rename_t.
+ */
+int rtems_filesystem_default_rename(
+ const rtems_filesystem_location_info_t *oldparentloc,
+ const rtems_filesystem_location_info_t *oldloc,
+ const rtems_filesystem_location_info_t *newparentloc,
+ const char *name,
+ size_t namelen
);
/**
- * This type defines the interface to the readlink(2) system call
- * support which is provided by a file system implementation.
- */
-typedef ssize_t (*rtems_filesystem_readlink_t)(
- rtems_filesystem_location_info_t *loc, /* IN */
- char *buf, /* OUT */
- size_t bufsize
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_statvfs_t.
+ */
+int rtems_filesystem_default_statvfs(
+ const rtems_filesystem_location_info_t *loc,
+ struct statvfs *buf
);
+/** @} */
+
/**
- * This type defines the interface to the name(2) system call
- * support which is provided by a file system implementation.
- */
-typedef int (*rtems_filesystem_rename_t)(
- rtems_filesystem_location_info_t *old_parent_loc, /* IN */
- rtems_filesystem_location_info_t *old_loc, /* IN */
- rtems_filesystem_location_info_t *new_parent_loc, /* IN */
- const char *name /* IN */
-);
+ * @defgroup LibIOFSHandler File System Node Handler
+ *
+ * @ingroup LibIO
+ *
+ * @brief File system node handler.
+ *
+ * @{
+ */
/**
- * This type defines the interface to the statvfs(2) system call
- * support which is provided by a file system implementation.
- */
-typedef int (*rtems_filesystem_statvfs_t)(
- rtems_filesystem_location_info_t *loc, /* IN */
- struct statvfs *buf /* OUT */
+ * @brief Opens a node.
+ *
+ * @param[in, out] iop The IO pointer.
+ * @param[in] path The path.
+ * @param[in] oflag The open flags.
+ * @param[in] mode Optional mode for node creation.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_open().
+ */
+typedef int (*rtems_filesystem_open_t)(
+ rtems_libio_t *iop,
+ const char *path,
+ int oflag,
+ mode_t mode
);
-/** @} */
-
/**
- * @brief File system operations table.
+ * @brief Closes a node.
+ *
+ * @param[in, out] iop The IO pointer.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_close().
*/
-struct _rtems_filesystem_operations_table {
+typedef int (*rtems_filesystem_close_t)(
+ rtems_libio_t *iop
+);
- /**
- * This field points to the file system specific implementation
- * of the support routine that evaluates a character path and
- * returns the node assocated with the last node in the path.
- *
- * @note This method must have a filesystem specific implementation.
- *
- * @note There is no default implementation.
- */
- rtems_filesystem_evalpath_t evalpath_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine that evaluates a character path and
- * returns the node assocated with next to the last node in
- * the path. The last node will be the new node to be created.
- *
- * @note This method must have a filesystem specific implementation.
- *
- * @note There is no default implementation.
- */
- rtems_filesystem_evalmake_t evalformake_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the link(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_link_t link_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the unlink(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_unlink_t unlink_h;
-
- /**
- * This field points to the file system specific implementation
- * of a method that returns the node type of the given node.
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_node_type_t node_type_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the link(2) system call
- *
- * @note This method may use a mknod implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_mknod_t mknod_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the link(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_chown_t chown_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the freenod(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_freenode_t freenod_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the mount(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_mount_t mount_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the fsmount(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_fsmount_me_t fsmount_me_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the unmount(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_unmount_t unmount_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the fsunmount(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_fsunmount_me_t fsunmount_me_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the utime(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_utime_t utime_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the eval_link(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_evaluate_link_t eval_link_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the sumlink(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_symlink_t symlink_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the readlink(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_readlink_t readlink_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the rename(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_rename_t rename_h;
-
- /**
- * This field points to the file system specific implementation
- * of the support routine for the statvfs(2) system call
- *
- * @note This method may use a default implementation.
- *
- * @note The default implementation returns -1 and sets
- * errno to ENOTSUP.
- */
- rtems_filesystem_statvfs_t statvfs_h;
-};
+/**
+ * @brief Reads from a node.
+ *
+ * @param[in, out] iop The IO pointer.
+ * @param[out] buffer The buffer for read data.
+ * @param[in] count The size of the buffer in characters.
+ *
+ * @retval non-negative Count of read characters.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_read().
+ */
+typedef ssize_t (*rtems_filesystem_read_t)(
+ rtems_libio_t *iop,
+ void *buffer,
+ size_t count
+);
-extern const rtems_filesystem_operations_table
-rtems_filesystem_operations_default;
+/**
+ * @brief Writes to a node.
+ *
+ * @param[in, out] iop The IO pointer.
+ * @param[out] buffer The buffer for write data.
+ * @param[in] count The size of the buffer in characters.
+ *
+ * @retval non-negative Count of written characters.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_write().
+ */
+typedef ssize_t (*rtems_filesystem_write_t)(
+ rtems_libio_t *iop,
+ const void *buffer,
+ size_t count
+);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of path evaluation.
+ * @brief IO control of a node.
+ *
+ * @param[in, out] iop The IO pointer.
+ * @param[in] request The IO control request.
+ * @param[in, out] buffer The buffer for IO control request data.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_ioctl().
*/
-int rtems_filesystem_default_evalpath(
- const char *pathname,
- size_t pathnamelen,
- int flags,
- rtems_filesystem_location_info_t *pathloc
+typedef int (*rtems_filesystem_ioctl_t)(
+ rtems_libio_t *iop,
+ uint32_t request,
+ void *buffer
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of path evaluation for make.
+ * @brief Moves the read/write file offset.
+ *
+ * @param[in, out] iop The IO pointer.
+ * @param[in] offset The new offset.
+ * @param[in] whence The reference position of the new offset.
+ *
+ * @retval non-negative The new offset from the beginning of the file.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_lseek().
*/
-int rtems_filesystem_default_evalformake(
- const char *path,
- rtems_filesystem_location_info_t *pathloc,
- const char **name
+typedef off_t (*rtems_filesystem_lseek_t)(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a link command.
+ * @brief Gets a node status.
+ *
+ * @param[in, out] iop The IO pointer.
+ * @param[out] stat The buffer to status information.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_fstat().
*/
-int rtems_filesystem_default_link(
- rtems_filesystem_location_info_t *to_loc, /* IN */
- rtems_filesystem_location_info_t *parent_loc, /* IN */
- const char *name /* IN */
+typedef int (*rtems_filesystem_fstat_t)(
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *buf
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a unlink command.
+ * @brief Truncates a file to a specified length.
+ *
+ * @param[in, out] iop The IO pointer.
+ * @param[in] length The new length in characters.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_ftruncate() and
+ * rtems_filesystem_default_ftruncate_directory().
*/
-int rtems_filesystem_default_unlink(
- rtems_filesystem_location_info_t *parent_pathloc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */
+typedef int (*rtems_filesystem_ftruncate_t)(
+ rtems_libio_t *iop,
+ off_t length
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation to determine the node type.
+ * @brief Synchronizes changes to a file.
+ *
+ * @param[in, out] iop The IO pointer.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_fsync().
*/
-rtems_filesystem_node_types_t rtems_filesystem_default_node_type(
- rtems_filesystem_location_info_t *pathloc
+typedef int (*rtems_filesystem_fsync_t)(
+ rtems_libio_t *iop
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation to create a new node.
+ * @brief Synchronizes the data of a file.
+ *
+ * @param[in, out] iop The IO pointer.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occured. The errno is set to indicate the error.
+ *
+ * @see rtems_filesystem_default_fdatasync().
*/
-int rtems_filesystem_default_mknod(
- const char *path, /* IN */
- mode_t mode, /* IN */
- dev_t dev, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+typedef int (*rtems_filesystem_fdatasync_t)(
+ rtems_libio_t *iop
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a chown command.
+ * @brief File control.
+ *
+ * @param[in, out] iop The IO pointer.
+ * @param[in] cmd Control command.
+ *
+ * @retval 0 Successful operation.
+ * @retval errno An error occured. This value is assigned to errno.
+ *
+ * @see rtems_filesystem_default_fcntl().
*/
-int rtems_filesystem_default_chown(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- uid_t owner, /* IN */
- gid_t group /* IN */
+typedef int (*rtems_filesystem_fcntl_t)(
+ rtems_libio_t *iop,
+ int cmd
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a freenode command.
+ * @brief File system node operations table.
+ */
+struct _rtems_filesystem_file_handlers_r {
+ rtems_filesystem_open_t open_h;
+ rtems_filesystem_close_t close_h;
+ rtems_filesystem_read_t read_h;
+ rtems_filesystem_write_t write_h;
+ rtems_filesystem_ioctl_t ioctl_h;
+ rtems_filesystem_lseek_t lseek_h;
+ rtems_filesystem_fstat_t fstat_h;
+ rtems_filesystem_ftruncate_t ftruncate_h;
+ rtems_filesystem_fsync_t fsync_h;
+ rtems_filesystem_fdatasync_t fdatasync_h;
+ rtems_filesystem_fcntl_t fcntl_h;
+};
+
+/**
+ * @brief File system node handler table with default node handlers.
+ */
+extern const rtems_filesystem_file_handlers_r
+ rtems_filesystem_handlers_default;
+
+/**
+ * @retval 0 Always.
+ *
+ * @see rtems_filesystem_open_t.
*/
-int rtems_filesystem_default_freenode(
- rtems_filesystem_location_info_t *pathloc /* IN */
+int rtems_filesystem_default_open(
+ rtems_libio_t *iop,
+ const char *path,
+ int oflag,
+ mode_t mode
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a mount command.
+ * @retval 0 Always.
+ *
+ * @see rtems_filesystem_close_t.
*/
-int rtems_filesystem_default_mount (
- rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+int rtems_filesystem_default_close(
+ rtems_libio_t *iop
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a fsmount command.
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_read_t.
*/
-int rtems_filesystem_default_fsmount(
- rtems_filesystem_mount_table_entry_t *mt_entry, /* IN */
- const void *data /* IN */
+ssize_t rtems_filesystem_default_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ size_t count
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a unmount command.
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_write_t.
*/
-int rtems_filesystem_default_unmount(
- rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+ssize_t rtems_filesystem_default_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ size_t count
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a fsunmount command.
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_ioctl_t.
*/
-int rtems_filesystem_default_fsunmount(
- rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+int rtems_filesystem_default_ioctl(
+ rtems_libio_t *iop,
+ uint32_t command,
+ void *buffer
);
+/**
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_lseek_t.
+ */
+off_t rtems_filesystem_default_lseek(
+ rtems_libio_t *iop,
+ off_t length,
+ int whence
+);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a utime command.
+ * @brief Sets the mode to S_IRWXU | S_IRWXG | S_IRWXO.
+ *
+ * @retval 0 Always.
+ *
+ * @see rtems_filesystem_fstat_t.
*/
-int rtems_filesystem_default_utime(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- time_t actime, /* IN */
- time_t modtime /* IN */
+int rtems_filesystem_default_fstat(
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *buf
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a link command.
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_ftruncate_t.
*/
-int rtems_filesystem_default_evaluate_link(
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- int flags /* IN */
+int rtems_filesystem_default_ftruncate(
+ rtems_libio_t *iop,
+ off_t length
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a symlink command.
+ * @retval -1 Always. The errno is set to EISDIR.
+ *
+ * @see rtems_filesystem_ftruncate_t.
*/
-int rtems_filesystem_default_symlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- const char *link_name, /* IN */
- const char *node_name
+int rtems_filesystem_default_ftruncate_directory(
+ rtems_libio_t *iop,
+ off_t length
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a readlink command.
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_fsync_t.
*/
-ssize_t rtems_filesystem_default_readlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- char *buf, /* OUT */
- size_t bufsize
+int rtems_filesystem_default_fsync(
+ rtems_libio_t *iop
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a rename command.
+ * @retval -1 Always. The errno is set to ENOTSUP.
+ *
+ * @see rtems_filesystem_fdatasync_t.
*/
-int rtems_filesystem_default_rename(
- rtems_filesystem_location_info_t *old_parent_loc, /* IN */
- rtems_filesystem_location_info_t *old_loc, /* IN */
- rtems_filesystem_location_info_t *new_parent_loc, /* IN */
- const char *name /* IN */
+int rtems_filesystem_default_fdatasync(
+ rtems_libio_t *iop
);
/**
- * @brief Provides a defualt routine for filesystem
- * implementation of a statvfs command.
+ * @retval 0 Always.
+ *
+ * @see rtems_filesystem_fcntl_t.
*/
-int rtems_filesystem_default_statvfs(
- rtems_filesystem_location_info_t *loc, /* IN */
- struct statvfs *buf /* OUT */
+int rtems_filesystem_default_fcntl(
+ rtems_libio_t *iop,
+ int cmd
);
+/** @} */
+
+/**
+ * @defgroup LibIO IO Library
+ *
+ * @brief Provides system call and file system interface definitions.
+ *
+ * General purpose communication channel for RTEMS to allow UNIX/POSIX
+ * system call behavior under RTEMS. Initially this supported only
+ * IO to devices but has since been enhanced to support networking
+ * and support for mounted file systems.
+ *
+ * @{
+ */
+
+typedef off_t rtems_off64_t __attribute__((deprecated));
+
/**
* @brief Gets the mount handler for the file system @a type.
*
@@ -1067,7 +1135,8 @@ typedef struct {
*
* Override in a filesystem.
*/
-extern const rtems_filesystem_limits_and_options_t rtems_filesystem_default_pathconf;
+extern const rtems_filesystem_limits_and_options_t
+ rtems_filesystem_default_pathconf;
/**
* @brief An open file data structure.
@@ -1194,12 +1263,22 @@ typedef off_t (*rtems_libio_lseek_t)(
* used to check permissions. These are similar in style to the
* mode_t bits and should stay compatible with them.
*/
-#define RTEMS_LIBIO_PERMS_READ S_IROTH
-#define RTEMS_LIBIO_PERMS_WRITE S_IWOTH
-#define RTEMS_LIBIO_PERMS_RDWR (S_IROTH|S_IWOTH)
-#define RTEMS_LIBIO_PERMS_EXEC S_IXOTH
+#define RTEMS_LIBIO_PERMS_READ 0x4
+#define RTEMS_LIBIO_PERMS_WRITE 0x2
+#define RTEMS_LIBIO_PERMS_EXEC 0x1
#define RTEMS_LIBIO_PERMS_SEARCH RTEMS_LIBIO_PERMS_EXEC
-#define RTEMS_LIBIO_PERMS_RWX S_IRWXO
+#define RTEMS_LIBIO_PERMS_RDWR \
+ (RTEMS_LIBIO_PERMS_READ | RTEMS_LIBIO_PERMS_WRITE)
+#define RTEMS_LIBIO_PERMS_RWX \
+ (RTEMS_LIBIO_PERMS_RDWR | RTEMS_LIBIO_PERMS_EXEC)
+#define RTEMS_LIBIO_FOLLOW_HARD_LINK 0x8
+#define RTEMS_LIBIO_FOLLOW_SYM_LINK 0x10
+#define RTEMS_LIBIO_FOLLOW_LINK \
+ (RTEMS_LIBIO_FOLLOW_HARD_LINK | RTEMS_LIBIO_FOLLOW_SYM_LINK)
+#define RTEMS_LIBIO_MAKE 0x20
+#define RTEMS_LIBIO_EXCLUSIVE 0x40
+#define RTEMS_LIBIO_ACCEPT_RESIDUAL_DELIMITERS 0x80
+#define RTEMS_LIBIO_REJECT_TERMINAL_DOT 0x100
/** @} */
@@ -1251,12 +1330,6 @@ static inline rtems_device_minor_number rtems_filesystem_dev_minor_t(
} while(0)
/*
- * Verifies that the permission flag is valid.
- */
-#define rtems_libio_is_valid_perms( _perm ) \
- (((~RTEMS_LIBIO_PERMS_RWX) & _perm ) == 0)
-
-/*
* Prototypes for filesystem
*/
@@ -1317,12 +1390,14 @@ extern int rtems_mkdir(const char *path, mode_t mode);
* @brief Mount table entry.
*/
struct rtems_filesystem_mount_table_entry_tt {
- rtems_chain_node Node;
- rtems_filesystem_location_info_t mt_point_node;
- rtems_filesystem_location_info_t mt_fs_root;
- int options;
+ rtems_chain_node mt_node;
+ rtems_chain_control location_chain;
+ rtems_filesystem_global_location_t *mt_point_node;
+ rtems_filesystem_global_location_t *mt_fs_root;
+ bool mounted;
+ bool writeable;
void *fs_info;
-
+ const void *immutable_fs_info;
rtems_filesystem_limits_and_options_t pathconf_limits_and_options;
/*
@@ -1369,6 +1444,8 @@ typedef struct rtems_filesystem_table_t {
*/
extern const rtems_filesystem_table_t rtems_filesystem_table [];
+extern rtems_chain_control rtems_filesystem_mount_table;
+
/**
* @brief Registers a file system @a type.
*
@@ -1498,60 +1575,46 @@ bool rtems_filesystem_iterate(
);
/**
- * @brief Per file system mount routine.
- *
- * @see rtems_filesystem_mount_iterate().
+ * @brief Mount table entry visitor.
*
* @retval true Stop the iteration.
* @retval false Continue the iteration.
+ *
+ * @see rtems_filesystem_mount_iterate().
*/
-typedef bool (*rtems_per_filesystem_mount_routine)(
+typedef bool (*rtems_filesystem_mt_entry_visitor)(
const rtems_filesystem_mount_table_entry_t *mt_entry,
void *arg
);
/**
- * @brief Iterates over all file system mounts.
- *
- * For each file system mount the @a routine will be called with the entry and
- * the @a routine_arg parameter.
+ * @brief Iterates over all file system mount entries.
*
- * Do not mount or unmount file systems in @a routine.
+ * The iteration is protected by the IO library mutex. Do not mount or unmount
+ * file systems in the visitor function.
*
- * The iteration is protected by the IO library mutex.
+ * @param[in] visitor For each file system mount entry the visitor function
+ * will be called with the entry and the visitor argument as parameters.
+ * @param[in] visitor_arg The second parameter for the visitor function.
*
- * @retval true Iteration stopped due to @a routine return status.
+ * @retval true Iteration stopped due to visitor function return status.
* @retval false Iteration through all entries.
*/
-bool
-rtems_filesystem_mount_iterate(
- rtems_per_filesystem_mount_routine routine,
- void *routine_arg
+bool rtems_filesystem_mount_iterate(
+ rtems_filesystem_mt_entry_visitor visitor,
+ void *visitor_arg
);
-/**
- * @brief Boot time mount table entry.
- */
typedef struct {
- const char *type;
- rtems_filesystem_options_t fsoptions;
- const char *device;
- const char *mount_point;
-} rtems_filesystem_mount_table_t;
-
-/**
- * @brief Boot time mount table.
- *
- * @todo Only the first entry will be evaluated. Why do we need a table?
- */
-extern const rtems_filesystem_mount_table_t *rtems_filesystem_mount_table;
-
-/**
- * @brief Boot time mount table entry count.
- *
- * @todo Only the first entry will be evaluated. Why do we need a table?
- */
-extern const int rtems_filesystem_mount_table_size;
+ const char *source;
+ const char *target;
+ const char *filesystemtype;
+ rtems_filesystem_options_t options;
+ const void *data;
+} rtems_filesystem_mount_configuration;
+
+extern const rtems_filesystem_mount_configuration
+ rtems_filesystem_root_configuration;
/** @} */
diff --git a/cpukit/libcsupport/include/rtems/libio_.h b/cpukit/libcsupport/include/rtems/libio_.h
index e0396daa24..84882908fb 100644
--- a/cpukit/libcsupport/include/rtems/libio_.h
+++ b/cpukit/libcsupport/include/rtems/libio_.h
@@ -8,6 +8,9 @@
* COPYRIGHT (c) 1989-2011.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -18,17 +21,18 @@
#ifndef _RTEMS_RTEMS_LIBIO__H
#define _RTEMS_RTEMS_LIBIO__H
-#include <rtems.h>
-#include <rtems/libio.h> /* include before standard IO */
-
-#include <sys/types.h>
-
#include <errno.h>
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/seterr.h>
+
#ifdef __cplusplus
extern "C" {
#endif
+#define RTEMS_FILESYSTEM_SYMLOOP_MAX 32
+
/*
* Semaphore to protect the io table
*/
@@ -47,6 +51,27 @@ extern rtems_libio_t *rtems_libio_iops;
extern rtems_libio_t *rtems_libio_last_iop;
extern rtems_libio_t *rtems_libio_iop_freelist;
+extern const rtems_filesystem_file_handlers_r rtems_filesystem_null_handlers;
+
+extern rtems_filesystem_mount_table_entry_t rtems_filesystem_null_mt_entry;
+
+/**
+ * @brief The global null location.
+ *
+ * Every operation and the open and fstat handlers of this location returns an
+ * error status. The errno is not touched by these operations and handlers.
+ * The purpose of this location is to deliver the error return status for a
+ * previous error condition which must set the errno accordingly.
+ *
+ * The usage of this null location instead of the NULL pointer eliminates a lot
+ * of branches.
+ *
+ * The user environment root and current directory are statically initialized
+ * with the null location. Due to that all file system services are in a
+ * defined state even if no root file system was mounted.
+ */
+extern rtems_filesystem_global_location_t rtems_filesystem_global_location_null;
+
/*
* rtems_libio_iop
*
@@ -147,28 +172,54 @@ extern rtems_libio_t *rtems_libio_iop_freelist;
#define rtems_libio_check_permissions(_iop, _flag) \
rtems_libio_check_permissions_with_error(_iop, _flag, EINVAL )
-/*
- * rtems_filesystem_freenode
+/**
+ * @brief Clones a node.
*
- * Macro to free a node.
+ * The caller must hold the file system instance lock.
+ *
+ * @param[out] clone The cloned location.
+ * @param[in] master The master location.
+ *
+ * @see rtems_filesystem_instance_lock().
*/
+void rtems_filesystem_location_clone(
+ rtems_filesystem_location_info_t *clone,
+ const rtems_filesystem_location_info_t *master
+);
-void rtems_filesystem_freenode( rtems_filesystem_location_info_t* node );
-
-/*
- * External structures
+/**
+ * @brief Returns the type of a node.
+ *
+ * This function obtains and releases the file system instance lock.
+ *
+ * @param[in] loc The location of the node.
+ *
+ * @return The node type.
+ *
+ * @see rtems_filesystem_instance_lock().
*/
-#include <rtems/userenv.h>
+rtems_filesystem_node_types_t rtems_filesystem_node_type(
+ const rtems_filesystem_location_info_t *loc
+);
-extern rtems_user_env_t * rtems_current_user_env;
-extern rtems_user_env_t rtems_global_user_env;
+/**
+ * @brief Releases all resources of a location.
+ *
+ * This function may block on a mutex and may complete an unmount process.
+ *
+ * @param[in] loc The location to free.
+ *
+ * @note The file system root location is released by the file system instance
+ * destruction handler (see @ref rtems_filesystem_fsunmount_me_t).
+ *
+ * @see rtems_filesystem_freenode_t.
+ */
+void rtems_filesystem_location_free( rtems_filesystem_location_info_t *loc );
/*
- * Instantiate a private copy of the per user information for the calling task.
+ * External structures
*/
-
-rtems_status_code rtems_libio_set_private_env(void);
-rtems_status_code rtems_libio_share_private_env(rtems_id task_id) ;
+#include <rtems/userenv.h>
static inline void rtems_libio_lock( void )
{
@@ -180,80 +231,569 @@ static inline void rtems_libio_unlock( void )
rtems_semaphore_release( rtems_libio_semaphore );
}
+static inline void rtems_filesystem_mt_lock( void )
+{
+ rtems_libio_lock();
+}
+
+static inline void rtems_filesystem_mt_unlock( void )
+{
+ rtems_libio_unlock();
+}
+
+#define rtems_filesystem_mt_entry_declare_lock_context( ctx ) \
+ rtems_interrupt_level ctx
+
+#define rtems_filesystem_mt_entry_lock( ctx ) rtems_interrupt_disable( ctx )
+
+#define rtems_filesystem_mt_entry_unlock( ctx ) rtems_interrupt_enable( ctx )
+
+static inline void rtems_filesystem_instance_lock(
+ const rtems_filesystem_location_info_t *loc
+)
+{
+ (*loc->ops->lock_h)( loc->mt_entry );
+}
+
+static inline void rtems_filesystem_instance_unlock(
+ const rtems_filesystem_location_info_t *loc
+)
+{
+ (*loc->ops->unlock_h)( loc->mt_entry );
+}
+
/*
* File Descriptor Routine Prototypes
*/
rtems_libio_t *rtems_libio_allocate(void);
-uint32_t rtems_libio_fcntl_flags(
- uint32_t fcntl_flags
-);
+uint32_t rtems_libio_fcntl_flags( int fcntl_flags );
-uint32_t rtems_libio_to_fcntl_flags(
- uint32_t flags
-);
+int rtems_libio_to_fcntl_flags( uint32_t flags );
void rtems_libio_free(
rtems_libio_t *iop
);
-int rtems_libio_is_open_files_in_fs(
- rtems_filesystem_mount_table_entry_t *mt_entry
+/*
+ * File System Routine Prototypes
+ */
+
+rtems_filesystem_location_info_t *
+rtems_filesystem_eval_path_start(
+ rtems_filesystem_eval_path_context_t *ctx,
+ const char *path,
+ int eval_flags
);
-int rtems_libio_is_file_open(
- void *node_access
+rtems_filesystem_location_info_t *
+rtems_filesystem_eval_path_start_with_parent(
+ rtems_filesystem_eval_path_context_t *ctx,
+ const char *path,
+ int eval_flags,
+ rtems_filesystem_location_info_t *parentloc,
+ int parent_eval_flags
);
-/*
- * File System Routine Prototypes
- */
+rtems_filesystem_location_info_t *
+rtems_filesystem_eval_path_start_with_root_and_current(
+ rtems_filesystem_eval_path_context_t *ctx,
+ const char *path,
+ int eval_flags,
+ rtems_filesystem_global_location_t *const *global_root_ptr,
+ rtems_filesystem_global_location_t *const *global_current_ptr
+);
+
+void rtems_filesystem_eval_path_continue(
+ rtems_filesystem_eval_path_context_t *ctx
+);
-int rtems_filesystem_evaluate_relative_path(
- const char *pathname,
- size_t pathnamelen,
- int flags,
- rtems_filesystem_location_info_t *pathloc,
- int follow_link
+void rtems_filesystem_eval_path_cleanup(
+ rtems_filesystem_eval_path_context_t *ctx
);
-int rtems_filesystem_evaluate_path(
- const char *pathname,
- size_t pathnamelen,
- int flags,
- rtems_filesystem_location_info_t *pathloc,
- int follow_link
+void rtems_filesystem_eval_path_recursive(
+ rtems_filesystem_eval_path_context_t *ctx,
+ const char *path,
+ size_t pathlen
);
-int rtems_filesystem_dirname(
- const char *pathname
+void rtems_filesystem_eval_path_cleanup_with_parent(
+ rtems_filesystem_eval_path_context_t *ctx,
+ rtems_filesystem_location_info_t *parentloc
);
-int rtems_filesystem_prefix_separators(
- const char *pathname,
- int pathnamelen
+/**
+ * @brief Requests a path evaluation restart.
+ *
+ * Sets the start and current location to the new start location. The caller
+ * must terminate its current evaluation process. The path evaluation
+ * continues in the next loop iteration within
+ * rtems_filesystem_eval_path_continue(). This avoids recursive invokations.
+ * The function obtains the new start location and clones it to set the new
+ * current location. The previous start and current locations are released.
+ *
+ * @param[in, out] ctx The path evaluation context.
+ * @param[in, out] newstartloc_ptr Pointer to new start location.
+ */
+void rtems_filesystem_eval_path_restart(
+ rtems_filesystem_eval_path_context_t *ctx,
+ rtems_filesystem_global_location_t **newstartloc_ptr
+);
+
+typedef enum {
+ RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE,
+ RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE,
+ RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY
+} rtems_filesystem_eval_path_generic_status;
+
+/**
+ * @brief Tests if the current location is a directory.
+ *
+ * @param[in, out] ctx The path evaluation context.
+ * @param[in, out] arg The handler argument.
+ *
+ * @retval true The current location is a directory.
+ * @retval false Otherwise.
+ *
+ * @see rtems_filesystem_eval_path_generic().
+ */
+typedef bool (*rtems_filesystem_eval_path_is_directory)(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg
+);
+
+/**
+ * @brief Evaluates a token.
+ *
+ * @param[in, out] ctx The path evaluation context.
+ * @param[in, out] arg The handler argument.
+ * @param[in] token The token contents.
+ * @param[in] tokenlen The token length in characters.
+ *
+ * @retval status The generic path evaluation status.
+ *
+ * @see rtems_filesystem_eval_path_generic().
+ */
+typedef rtems_filesystem_eval_path_generic_status
+(*rtems_filesystem_eval_path_eval_token)(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg,
+ const char *token,
+ size_t tokenlen
+);
+
+typedef struct {
+ rtems_filesystem_eval_path_is_directory is_directory;
+ rtems_filesystem_eval_path_eval_token eval_token;
+} rtems_filesystem_eval_path_generic_config;
+
+void rtems_filesystem_eval_path_generic(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg,
+ const rtems_filesystem_eval_path_generic_config *config
);
void rtems_filesystem_initialize(void);
-int init_fs_mount_table(void);
+/**
+ * @brief Copies a location.
+ *
+ * A bitwise copy is performed. The destination location will be added to the
+ * corresponding mount entry.
+ *
+ * @param[out] dst The destination location.
+ * @param[in] src The source location.
+ *
+ * @retval dst The destination location.
+ *
+ * @see rtems_filesystem_location_clone().
+ */
+rtems_filesystem_location_info_t *rtems_filesystem_location_copy(
+ rtems_filesystem_location_info_t *dst,
+ const rtems_filesystem_location_info_t *src
+);
+
+static inline rtems_filesystem_location_info_t *
+rtems_filesystem_location_initialize_to_null(
+ rtems_filesystem_location_info_t *loc
+)
+{
+ return rtems_filesystem_location_copy(
+ loc,
+ &rtems_filesystem_global_location_null.location
+ );
+}
-int rtems_filesystem_is_separator(char ch);
+rtems_filesystem_global_location_t *
+rtems_filesystem_location_transform_to_global(
+ rtems_filesystem_location_info_t *loc
+);
-void rtems_filesystem_get_start_loc(const char *path,
- int *index,
- rtems_filesystem_location_info_t *loc);
+/**
+ * @brief Assigns a global file system location.
+ *
+ * @param[in, out] lhs_global_loc_ptr Pointer to the global left hand side file
+ * system location. The current left hand side location will be released.
+ * @param[in] rhs_global_loc The global right hand side file system location.
+ */
+void rtems_filesystem_global_location_assign(
+ rtems_filesystem_global_location_t **lhs_global_loc_ptr,
+ rtems_filesystem_global_location_t *rhs_global_loc
+);
-void rtems_filesystem_get_sym_start_loc(const char *path,
- int *index,
- rtems_filesystem_location_info_t *loc);
+/**
+ * @brief Obtains a global file system location.
+ *
+ * Deferred releases will be processed in this function.
+ *
+ * This function must be called from normal thread context and may block on a
+ * mutex. Thread dispatching is disabled to protect some critical sections.
+ *
+ * @param[in] global_loc_ptr Pointer to the global file system location.
+ *
+ * @return A global file system location. It returns always a valid object.
+ * In case of an error, the global null location will be returned. Each
+ * operation or handler of the null location returns an error status. The
+ * errno indicates the error. The NULL pointer is never returned.
+ *
+ * @see rtems_filesystem_location_transform_to_global(),
+ * rtems_filesystem_global_location_obtain_null(), and
+ * rtems_filesystem_global_location_release().
+ */
+rtems_filesystem_global_location_t *rtems_filesystem_global_location_obtain(
+ rtems_filesystem_global_location_t *const *global_loc_ptr
+);
+
+/**
+ * @brief Releases a global file system location.
+ *
+ * In case the reference count reaches zero, all associated resources will be
+ * released. This may include the complete unmount of the corresponding file
+ * system instance.
+ *
+ * This function may block on a mutex. It may be called within critical
+ * sections of the operating system. In this case the release will be
+ * deferred. The next obtain call will do the actual release.
+ *
+ * @param[in] global_loc The global file system location. It must not be NULL.
+ *
+ * @see rtems_filesystem_global_location_obtain().
+ */
+void rtems_filesystem_global_location_release(
+ rtems_filesystem_global_location_t *global_loc
+);
+
+void rtems_filesystem_location_detach(
+ rtems_filesystem_location_info_t *detach
+);
+
+void rtems_filesystem_location_copy_and_detach(
+ rtems_filesystem_location_info_t *copy,
+ rtems_filesystem_location_info_t *detach
+);
+
+static inline rtems_filesystem_global_location_t *
+rtems_filesystem_global_location_obtain_null(void)
+{
+ rtems_filesystem_global_location_t *global_loc = NULL;
-static inline bool rtems_filesystem_is_root_location(
+ return rtems_filesystem_global_location_obtain( &global_loc );
+}
+
+static inline bool rtems_filesystem_location_is_null(
+ const rtems_filesystem_location_info_t *loc
+)
+{
+ return loc->handlers == &rtems_filesystem_null_handlers;
+}
+
+static inline bool rtems_filesystem_global_location_is_null(
+ const rtems_filesystem_global_location_t *global_loc
+)
+{
+ return rtems_filesystem_location_is_null( &global_loc->location );
+}
+
+static inline void rtems_filesystem_location_error(
+ const rtems_filesystem_location_info_t *loc,
+ int eno
+)
+{
+ if ( !rtems_filesystem_location_is_null( loc ) ) {
+ errno = eno;
+ }
+}
+
+int rtems_filesystem_mknod(
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
+);
+
+int rtems_filesystem_chdir( rtems_filesystem_location_info_t *loc );
+
+int rtems_filesystem_chown(
+ const char *path,
+ uid_t owner,
+ gid_t group,
+ int eval_follow_link
+);
+
+static inline bool rtems_filesystem_is_ready_for_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ bool ready = !mt_entry->mounted
+ && rtems_chain_has_only_one_node( &mt_entry->location_chain )
+ && mt_entry->mt_fs_root->reference_count == 1;
+
+ if ( ready ) {
+ rtems_chain_initialize_empty( &mt_entry->location_chain );
+ }
+
+ return ready;
+}
+
+static inline void rtems_filesystem_location_add_to_mt_entry(
+ rtems_filesystem_location_info_t *loc
+)
+{
+ rtems_filesystem_mt_entry_declare_lock_context( lock_context );
+
+ rtems_filesystem_mt_entry_lock( lock_context );
+ rtems_chain_append_unprotected(
+ &loc->mt_entry->location_chain,
+ &loc->mt_entry_node
+ );
+ rtems_filesystem_mt_entry_unlock( lock_context );
+}
+
+void rtems_filesystem_location_remove_from_mt_entry(
+ rtems_filesystem_location_info_t *loc
+);
+
+void rtems_filesystem_do_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+static inline bool rtems_filesystem_location_is_root(
const rtems_filesystem_location_info_t *loc
)
{
- return loc->mt_entry->mt_fs_root.node_access == loc->node_access;
+ return (*loc->ops->are_nodes_equal_h)(
+ loc,
+ &loc->mt_entry->mt_fs_root->location
+ );
+}
+
+static inline const char *rtems_filesystem_eval_path_get_path(
+ rtems_filesystem_eval_path_context_t *ctx
+)
+{
+ return ctx->path;
+}
+
+static inline size_t rtems_filesystem_eval_path_get_pathlen(
+ rtems_filesystem_eval_path_context_t *ctx
+)
+{
+ return ctx->pathlen;
+}
+
+static inline void rtems_filesystem_eval_path_set_path(
+ rtems_filesystem_eval_path_context_t *ctx,
+ const char *path,
+ size_t pathlen
+)
+{
+ ctx->path = path;
+ ctx->pathlen = pathlen;
+}
+
+static inline void rtems_filesystem_eval_path_clear_path(
+ rtems_filesystem_eval_path_context_t *ctx
+)
+{
+ ctx->pathlen = 0;
+}
+
+static inline const char *rtems_filesystem_eval_path_get_token(
+ rtems_filesystem_eval_path_context_t *ctx
+)
+{
+ return ctx->token;
+}
+
+static inline size_t rtems_filesystem_eval_path_get_tokenlen(
+ rtems_filesystem_eval_path_context_t *ctx
+)
+{
+ return ctx->tokenlen;
+}
+
+static inline void rtems_filesystem_eval_path_set_token(
+ rtems_filesystem_eval_path_context_t *ctx,
+ const char *token,
+ size_t tokenlen
+)
+{
+ ctx->token = token;
+ ctx->tokenlen = tokenlen;
+}
+
+static inline void rtems_filesystem_eval_path_clear_token(
+ rtems_filesystem_eval_path_context_t *ctx
+)
+{
+ ctx->tokenlen = 0;
+}
+
+static inline void rtems_filesystem_eval_path_put_back_token(
+ rtems_filesystem_eval_path_context_t *ctx
+)
+{
+ size_t tokenlen = ctx->tokenlen;
+
+ ctx->path -= tokenlen;
+ ctx->pathlen += tokenlen;
+ ctx->tokenlen = 0;
+}
+
+void rtems_filesystem_eval_path_eat_delimiter(
+ rtems_filesystem_eval_path_context_t *ctx
+);
+
+void rtems_filesystem_eval_path_next_token(
+ rtems_filesystem_eval_path_context_t *ctx
+);
+
+static inline void rtems_filesystem_eval_path_get_next_token(
+ rtems_filesystem_eval_path_context_t *ctx,
+ const char **token,
+ size_t *tokenlen
+)
+{
+ rtems_filesystem_eval_path_next_token(ctx);
+ *token = ctx->token;
+ *tokenlen = ctx->tokenlen;
+}
+
+static inline rtems_filesystem_location_info_t *
+rtems_filesystem_eval_path_get_currentloc(
+ rtems_filesystem_eval_path_context_t *ctx
+)
+{
+ return &ctx->currentloc;
+}
+
+static inline bool rtems_filesystem_eval_path_has_path(
+ const rtems_filesystem_eval_path_context_t *ctx
+)
+{
+ return ctx->pathlen > 0;
+}
+
+static inline bool rtems_filesystem_eval_path_has_token(
+ const rtems_filesystem_eval_path_context_t *ctx
+)
+{
+ return ctx->tokenlen > 0;
+}
+
+static inline int rtems_filesystem_eval_path_get_flags(
+ const rtems_filesystem_eval_path_context_t *ctx
+)
+{
+ return ctx->flags;
+}
+
+static inline void rtems_filesystem_eval_path_set_flags(
+ rtems_filesystem_eval_path_context_t *ctx,
+ int flags
+)
+{
+ ctx->flags = flags;
+}
+
+static inline void rtems_filesystem_eval_path_clear_and_set_flags(
+ rtems_filesystem_eval_path_context_t *ctx,
+ int clear,
+ int set
+)
+{
+ int flags = ctx->flags;
+
+ flags &= ~clear;
+ flags |= set;
+
+ ctx->flags = flags;
+}
+
+static inline void rtems_filesystem_eval_path_extract_currentloc(
+ rtems_filesystem_eval_path_context_t *ctx,
+ rtems_filesystem_location_info_t *get
+)
+{
+ rtems_filesystem_location_copy_and_detach(
+ get,
+ &ctx->currentloc
+ );
+}
+
+void rtems_filesystem_eval_path_error(
+ rtems_filesystem_eval_path_context_t *ctx,
+ int eno
+);
+
+/**
+ * @brief Checks that the locations exist in the same file system instance.
+ *
+ * @retval 0 The locations exist and are in the same file system instance.
+ * @retval -1 An error occured. The @c errno indicates the error.
+ */
+int rtems_filesystem_location_exists_in_same_fs_instance_as(
+ const rtems_filesystem_location_info_t *a,
+ const rtems_filesystem_location_info_t *b
+);
+
+bool rtems_filesystem_check_access(
+ int eval_flags,
+ mode_t node_mode,
+ uid_t node_uid,
+ gid_t node_gid
+);
+
+bool rtems_filesystem_eval_path_check_access(
+ rtems_filesystem_eval_path_context_t *ctx,
+ int eval_flags,
+ mode_t node_mode,
+ uid_t node_uid,
+ gid_t node_gid
+);
+
+static inline bool rtems_filesystem_is_delimiter(char c)
+{
+ return c == '/' || c == '\\';
+}
+
+static inline bool rtems_filesystem_is_current_directory(
+ const char *token,
+ size_t tokenlen
+)
+{
+ return tokenlen == 1 && token [0] == '.';
+}
+
+static inline bool rtems_filesystem_is_parent_directory(
+ const char *token,
+ size_t tokenlen
+)
+{
+ return tokenlen == 2 && token [0] == '.' && token [1] == '.';
}
#ifdef __cplusplus
diff --git a/cpukit/libcsupport/src/__usrenv.c b/cpukit/libcsupport/src/__usrenv.c
index 0b3469fa1a..d26e73658f 100644
--- a/cpukit/libcsupport/src/__usrenv.c
+++ b/cpukit/libcsupport/src/__usrenv.c
@@ -2,6 +2,9 @@
* COPYRIGHT (c) 1989-2008.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -10,18 +13,246 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <rtems.h>
-#include <rtems/libio.h>
+#include <sys/stat.h>
+
#include <rtems/libio_.h>
-/*
- * Global information for POSIX Process Environment Support
- */
+static int null_handler_open(
+ rtems_libio_t *iop,
+ const char *path,
+ int oflag,
+ mode_t mode
+)
+{
+ return -1;
+}
+
+static int null_handler_fstat(
+ const rtems_filesystem_location_info_t *pathloc,
+ struct stat *buf
+)
+{
+ return -1;
+}
+
+const rtems_filesystem_file_handlers_r rtems_filesystem_null_handlers = {
+ .open_h = null_handler_open,
+ .close_h = rtems_filesystem_default_close,
+ .read_h = rtems_filesystem_default_read,
+ .write_h = rtems_filesystem_default_write,
+ .ioctl_h = rtems_filesystem_default_ioctl,
+ .lseek_h = rtems_filesystem_default_lseek,
+ .fstat_h = null_handler_fstat,
+ .ftruncate_h = rtems_filesystem_default_ftruncate,
+ .fsync_h = rtems_filesystem_default_fsync,
+ .fdatasync_h = rtems_filesystem_default_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl
+};
+
+static void null_op_lock_or_unlock(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ /* Do nothing */
+}
+
+static int null_op_mknod(
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
+)
+{
+ return -1;
+}
+
+static int null_op_rmnod(
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *loc
+)
+{
+ return -1;
+}
+
+static int null_op_link(
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *targetloc,
+ const char *name,
+ size_t namelen
+)
+{
+ return -1;
+}
+
+static int null_op_fchmod(
+ const rtems_filesystem_location_info_t *pathloc,
+ mode_t mode
+)
+{
+ return -1;
+}
+
+static int null_op_chown(
+ const rtems_filesystem_location_info_t *loc,
+ uid_t owner,
+ gid_t group
+)
+{
+ return -1;
+}
+
+static int null_op_clonenode(
+ rtems_filesystem_location_info_t *loc
+)
+{
+ return -1;
+}
+
+static int null_op_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ return -1;
+}
+
+static int null_op_fsmount_me(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ const void *data
+)
+{
+ return -1;
+}
+
+static int null_op_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ return -1;
+}
+
+static void null_op_fsunmount_me(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ /* Do nothing */
+}
+
+static int null_op_utime(
+ const rtems_filesystem_location_info_t *loc,
+ time_t actime,
+ time_t modtime
+)
+{
+ return -1;
+}
+
+static int null_op_symlink(
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ const char *target
+)
+{
+ return -1;
+}
+
+static ssize_t null_op_readlink(
+ const rtems_filesystem_location_info_t *loc,
+ char *buf,
+ size_t bufsize
+)
+{
+ return -1;
+}
+
+static int null_op_rename(
+ const rtems_filesystem_location_info_t *oldparentloc,
+ const rtems_filesystem_location_info_t *oldloc,
+ const rtems_filesystem_location_info_t *newparentloc,
+ const char *name,
+ size_t namelen
+)
+{
+ return -1;
+}
+
+static int null_op_statvfs(
+ const rtems_filesystem_location_info_t *loc,
+ struct statvfs *buf
+)
+{
+ return -1;
+}
+
+static const rtems_filesystem_operations_table null_ops = {
+ .lock_h = null_op_lock_or_unlock,
+ .unlock_h = null_op_lock_or_unlock,
+ .eval_path_h = rtems_filesystem_default_eval_path,
+ .link_h = null_op_link,
+ .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
+ .node_type_h = rtems_filesystem_default_node_type,
+ .mknod_h = null_op_mknod,
+ .rmnod_h = null_op_rmnod,
+ .fchmod_h = null_op_fchmod,
+ .chown_h = null_op_chown,
+ .clonenod_h = null_op_clonenode,
+ .freenod_h = rtems_filesystem_default_freenode,
+ .mount_h = null_op_mount,
+ .fsmount_me_h = null_op_fsmount_me,
+ .unmount_h = null_op_unmount,
+ .fsunmount_me_h = null_op_fsunmount_me,
+ .utime_h = null_op_utime,
+ .symlink_h = null_op_symlink,
+ .readlink_h = null_op_readlink,
+ .rename_h = null_op_rename,
+ .statvfs_h = null_op_statvfs
+};
+
+rtems_filesystem_mount_table_entry_t rtems_filesystem_null_mt_entry = {
+ .location_chain = {
+ .Head = {
+ .Node = {
+ .next = &rtems_filesystem_global_location_null.location.mt_entry_node,
+ .previous = NULL
+ },
+ .fill = &rtems_filesystem_global_location_null.location.mt_entry_node,
+ }
+ },
+ .mt_point_node = &rtems_filesystem_global_location_null,
+ .mt_fs_root = &rtems_filesystem_global_location_null,
+ .mounted = false,
+ .writeable = false
+};
+
+rtems_filesystem_global_location_t rtems_filesystem_global_location_null = {
+ .location = {
+ .mt_entry_node = {
+ .next = &rtems_filesystem_null_mt_entry.location_chain.Tail.Node,
+ .previous = &rtems_filesystem_null_mt_entry.location_chain.Head.Node
+ },
+ .handlers = &rtems_filesystem_null_handlers,
+ .ops = &null_ops,
+ .mt_entry = &rtems_filesystem_null_mt_entry
+ },
-rtems_user_env_t rtems_global_user_env;
-rtems_user_env_t * rtems_current_user_env = &rtems_global_user_env;
+ /*
+ * The initial reference count accounts for the following references
+ * o the root directory of the user environment,
+ * o the current directory of the user environment,
+ * o the root node of the null file system instance, and
+ * o the mount point node of the null file system instance.
+ */
+ .reference_count = 4
+};
+rtems_user_env_t rtems_global_user_env = {
+ .current_directory = &rtems_filesystem_global_location_null,
+ .root_directory = &rtems_filesystem_global_location_null,
+ .umask = S_IWGRP | S_IWOTH
+};
+rtems_user_env_t *rtems_current_user_env = &rtems_global_user_env;
diff --git a/cpukit/libcsupport/src/_rename_r.c b/cpukit/libcsupport/src/_rename_r.c
index 51010df28e..7a2637aa89 100644
--- a/cpukit/libcsupport/src/_rename_r.c
+++ b/cpukit/libcsupport/src/_rename_r.c
@@ -4,6 +4,9 @@
* COPYRIGHT (c) 1989-2007.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -16,12 +19,10 @@
#endif
#if defined(RTEMS_NEWLIB) && !defined(HAVE__RENAME_R)
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
+
+#include <stdio.h>
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
int _rename_r(
struct _reent *ptr __attribute__((unused)),
@@ -29,85 +30,47 @@ int _rename_r(
const char *new
)
{
- int old_parent_pathlen;
- rtems_filesystem_location_info_t old_loc;
- rtems_filesystem_location_info_t old_parent_loc;
- rtems_filesystem_location_info_t new_parent_loc;
- int i;
- int result;
- const char *name;
- bool free_old_parentloc = false;
-
- /*
- * Get the parent node of the old path to be renamed. Find the parent path.
- */
-
- old_parent_pathlen = rtems_filesystem_dirname ( old );
-
- if ( old_parent_pathlen == 0 )
- rtems_filesystem_get_start_loc( old, &i, &old_parent_loc );
- else {
- result = rtems_filesystem_evaluate_path( old, old_parent_pathlen,
- RTEMS_LIBIO_PERMS_WRITE,
- &old_parent_loc,
- false );
- if ( result != 0 )
- return -1;
-
- free_old_parentloc = true;
+ int rv = 0;
+ rtems_filesystem_eval_path_context_t old_ctx;
+ int old_eval_flags = 0;
+ rtems_filesystem_location_info_t old_parentloc;
+ int old_parent_eval_flags = RTEMS_LIBIO_PERMS_WRITE
+ | RTEMS_LIBIO_FOLLOW_HARD_LINK;
+ const rtems_filesystem_location_info_t *old_currentloc =
+ rtems_filesystem_eval_path_start_with_parent(
+ &old_ctx,
+ old,
+ old_eval_flags,
+ &old_parentloc,
+ old_parent_eval_flags
+ );
+ rtems_filesystem_eval_path_context_t new_ctx;
+
+ /* FIXME: This is not POSIX conform */
+ int new_eval_flags = RTEMS_LIBIO_FOLLOW_HARD_LINK
+ | RTEMS_LIBIO_MAKE
+ | RTEMS_LIBIO_EXCLUSIVE;
+
+ const rtems_filesystem_location_info_t *new_currentloc =
+ rtems_filesystem_eval_path_start( &new_ctx, new, new_eval_flags );
+
+ rv = rtems_filesystem_location_exists_in_same_fs_instance_as(
+ old_currentloc,
+ new_currentloc
+ );
+ if ( rv == 0 ) {
+ rv = (*new_currentloc->ops->rename_h)(
+ &old_parentloc,
+ old_currentloc,
+ new_currentloc,
+ rtems_filesystem_eval_path_get_token( &new_ctx ),
+ rtems_filesystem_eval_path_get_tokenlen( &new_ctx )
+ );
}
- /*
- * Start from the parent to find the node that should be under it.
- */
-
- old_loc = old_parent_loc;
- name = old + old_parent_pathlen;
- name += rtems_filesystem_prefix_separators( name, strlen( name ) );
-
- result = rtems_filesystem_evaluate_relative_path( name , strlen( name ),
- 0, &old_loc, false );
- if ( result != 0 ) {
- if ( free_old_parentloc )
- rtems_filesystem_freenode( &old_parent_loc );
- return -1;
- }
-
- /*
- * Get the parent of the new node we are renaming to.
- */
-
- rtems_filesystem_get_start_loc( new, &i, &new_parent_loc );
-
- result = (*new_parent_loc.ops->evalformake_h)( &new[i], &new_parent_loc, &name );
- if ( result != 0 ) {
- rtems_filesystem_freenode( &new_parent_loc );
- if ( free_old_parentloc )
- rtems_filesystem_freenode( &old_parent_loc );
- rtems_filesystem_freenode( &old_loc );
- return -1;
- }
-
- /*
- * Check to see if the caller is trying to rename across file system
- * boundaries.
- */
-
- if ( old_parent_loc.mt_entry != new_parent_loc.mt_entry ) {
- rtems_filesystem_freenode( &new_parent_loc );
- if ( free_old_parentloc )
- rtems_filesystem_freenode( &old_parent_loc );
- rtems_filesystem_freenode( &old_loc );
- rtems_set_errno_and_return_minus_one( EXDEV );
- }
-
- result = (*new_parent_loc.ops->rename_h)( &old_parent_loc, &old_loc, &new_parent_loc, name );
-
- rtems_filesystem_freenode( &new_parent_loc );
- if ( free_old_parentloc )
- rtems_filesystem_freenode( &old_parent_loc );
- rtems_filesystem_freenode( &old_loc );
+ rtems_filesystem_eval_path_cleanup_with_parent( &old_ctx, &old_parentloc );
+ rtems_filesystem_eval_path_cleanup( &new_ctx );
- return result;
+ return rv;
}
#endif
diff --git a/cpukit/libcsupport/src/base_fs.c b/cpukit/libcsupport/src/base_fs.c
index b5681eda63..bbf6d8d4be 100644
--- a/cpukit/libcsupport/src/base_fs.c
+++ b/cpukit/libcsupport/src/base_fs.c
@@ -4,6 +4,9 @@
* COPYRIGHT (c) 1989-2008.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -35,62 +38,20 @@
void rtems_filesystem_initialize( void )
{
- int status;
- const rtems_filesystem_mount_table_t *mt;
- rtems_filesystem_location_info_t loc;
-
- /*
- * Set the default umask to "022".
- */
-
- rtems_filesystem_umask = 022;
-
- /*
- * mount the first filesystem.
- */
- if ( rtems_filesystem_mount_table_size == 0 )
- rtems_fatal_error_occurred( 0xABCD0001 );
-
- mt = &rtems_filesystem_mount_table[0];
-
- status = mount( mt->device, mt->mount_point, mt->type, mt->fsoptions, NULL );
- if ( status == -1 )
+ int rv = 0;
+ const rtems_filesystem_mount_configuration *root_config =
+ &rtems_filesystem_root_configuration;
+
+ rv = mount(
+ root_config->source,
+ root_config->target,
+ root_config->filesystemtype,
+ root_config->options,
+ root_config->data
+ );
+ if ( rv != 0 )
rtems_fatal_error_occurred( 0xABCD0002 );
- rtems_filesystem_link_counts = 0;
-
- /* setup the 'current' and 'root' directories
- *
- * NOTE: cloning the pathlocs is not strictly
- * necessary. Since we implicitely let
- * all threads that don't call
- * libio_set_private_env() share the same
- * (initial) 'root' and 'current' locs,
- * we (also implicitely) assume that the
- * root filesystem doesn't care about
- * reference counts.
- * I just inserted the code snippet below
- * to remind everybody of the fact by
- * making it more explicit...
- * Ideally, every thread would have to
- * call either share_private_env() or
- * set_private_env() - but then: that's
- * gonna hit performance.
- *
- * Till Straumann, 10/25/2002
- */
- /* Clone the root pathloc */
- rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
- rtems_filesystem_root = loc;
- /* One more clone for the current node */
- rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
- rtems_filesystem_current = loc;
-
- /* Note: the global_env's refcnt doesn't matter
- * as the global env is never released
- */
-
-
/*
* Traditionally RTEMS devices are under "/dev" so install this directory.
*
@@ -100,8 +61,8 @@ void rtems_filesystem_initialize( void )
* created that way by the IMFS.
*/
- status = mkdir( "/dev", 0777);
- if ( status != 0 )
+ rv = mkdir( "/dev", 0777);
+ if ( rv != 0 )
rtems_fatal_error_occurred( 0xABCD0003 );
/*
diff --git a/cpukit/libcsupport/src/chdir.c b/cpukit/libcsupport/src/chdir.c
index c9d05f0bef..df65170936 100644
--- a/cpukit/libcsupport/src/chdir.c
+++ b/cpukit/libcsupport/src/chdir.c
@@ -4,6 +4,9 @@
* COPYRIGHT (c) 1989-2010.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -12,46 +15,47 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <rtems.h>
-
#include <unistd.h>
-#include <errno.h>
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-int chdir(
- const char *pathname
-)
+int rtems_filesystem_chdir( rtems_filesystem_location_info_t *loc )
{
- rtems_filesystem_location_info_t loc;
- int result;
-
- if ( !pathname )
- rtems_set_errno_and_return_minus_one( EFAULT );
-
- /*
- * Get the node where we wish to go.
- */
- result = rtems_filesystem_evaluate_path(
- pathname, strlen( pathname ), RTEMS_LIBIO_PERMS_SEARCH, &loc, true );
- if ( result != 0 )
- return -1;
-
- /*
- * Verify you can change directory into this node.
- */
- if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
- rtems_filesystem_freenode( &loc );
- rtems_set_errno_and_return_minus_one( ENOTDIR );
+ int rv = 0;
+ rtems_filesystem_global_location_t *global_loc =
+ rtems_filesystem_location_transform_to_global( loc );
+ rtems_filesystem_node_types_t type =
+ rtems_filesystem_node_type( &global_loc->location );
+
+ if ( type == RTEMS_FILESYSTEM_DIRECTORY ) {
+ rtems_filesystem_global_location_assign(
+ &rtems_filesystem_current,
+ global_loc
+ );
+ } else {
+ rtems_filesystem_location_error( &global_loc->location, ENOTDIR );
+ rtems_filesystem_global_location_release( global_loc );
+ rv = -1;
}
- rtems_filesystem_freenode( &rtems_filesystem_current );
-
- rtems_filesystem_current = loc;
+ return rv;
+}
- return 0;
+int chdir( const char *path )
+{
+ int rv = 0;
+ rtems_filesystem_eval_path_context_t ctx;
+ int eval_flags = RTEMS_LIBIO_PERMS_EXEC
+ | RTEMS_LIBIO_FOLLOW_LINK;
+ rtems_filesystem_location_info_t pathloc;
+
+ rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
+ rtems_filesystem_eval_path_extract_currentloc( &ctx, &pathloc );
+ rv = rtems_filesystem_chdir( &pathloc );
+ rtems_filesystem_eval_path_cleanup( &ctx );
+
+ return rv;
}
diff --git a/cpukit/libcsupport/src/chmod.c b/cpukit/libcsupport/src/chmod.c
index d1d9ae0f5f..ff3039a557 100644
--- a/cpukit/libcsupport/src/chmod.c
+++ b/cpukit/libcsupport/src/chmod.c
@@ -12,35 +12,24 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <rtems.h>
-#include <rtems/libio.h>
#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-int chmod(
- const char *path,
- mode_t mode
-)
+int chmod( const char *path, mode_t mode )
{
- int status;
- rtems_filesystem_location_info_t loc;
- int result;
+ int rv = 0;
+ rtems_filesystem_eval_path_context_t ctx;
+ int eval_flags = RTEMS_LIBIO_FOLLOW_LINK;
+ const rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
- status = rtems_filesystem_evaluate_path( path, strlen( path ), 0, &loc, true );
- if ( status != 0 )
- return -1;
+ rv = (*currentloc->ops->fchmod_h)( currentloc, mode );
- result = (*loc.handlers->fchmod_h)( &loc, mode );
+ rtems_filesystem_eval_path_cleanup( &ctx );
- rtems_filesystem_freenode( &loc );
-
- return result;
+ return rv;
}
diff --git a/cpukit/libcsupport/src/chown.c b/cpukit/libcsupport/src/chown.c
index 9ecaea11f7..1d07384d7d 100644
--- a/cpukit/libcsupport/src/chown.c
+++ b/cpukit/libcsupport/src/chown.c
@@ -4,6 +4,9 @@
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -12,39 +15,38 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
#include <unistd.h>
-#include <rtems.h>
#include <rtems/libio_.h>
-int _chown_helper(
+int rtems_filesystem_chown(
const char *path,
- uid_t owner,
- gid_t group,
- int follow_link
+ uid_t owner,
+ gid_t group,
+ int eval_follow_link
)
{
- rtems_filesystem_location_info_t loc;
- int result;
-
- if ( rtems_filesystem_evaluate_path( path, strlen( path ), 0x00, &loc, follow_link ) )
- return -1;
+ int rv = 0;
+ rtems_filesystem_eval_path_context_t ctx;
+ int eval_flags = eval_follow_link;
+ const rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
- result = (*loc.ops->chown_h)( &loc, owner, group );
+ rv = (*currentloc->ops->chown_h)(
+ currentloc,
+ owner,
+ group
+ );
- rtems_filesystem_freenode( &loc );
+ rtems_filesystem_eval_path_cleanup( &ctx );
- return result;
+ return rv;
}
-int chown(
- const char *path,
- uid_t owner,
- gid_t group
-)
+int chown( const char *path, uid_t owner, gid_t group )
{
- return _chown_helper( path, owner, group, true );
+ return rtems_filesystem_chown( path, owner, group, RTEMS_LIBIO_FOLLOW_LINK );
}
diff --git a/cpukit/libcsupport/src/chroot.c b/cpukit/libcsupport/src/chroot.c
index ccda4d6d7a..fd802ff32b 100644
--- a/cpukit/libcsupport/src/chroot.c
+++ b/cpukit/libcsupport/src/chroot.c
@@ -5,6 +5,9 @@
* COPYRIGHT (c) 1989-2008.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -13,43 +16,77 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <rtems.h>
-
#include <unistd.h>
-#include <errno.h>
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-int chroot(
- const char *pathname
-)
+int chroot( const char *path )
{
- int result;
- rtems_filesystem_location_info_t loc;
-
- /* an automatic call to new private env the first time */
- if (rtems_current_user_env == &rtems_global_user_env) {
- rtems_libio_set_private_env(); /* try to set a new private env*/
- if (rtems_current_user_env == &rtems_global_user_env) /* not ok */
- rtems_set_errno_and_return_minus_one( ENOTSUP );
- }
+ int rv = 0;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_filesystem_eval_path_context_t ctx;
+ int eval_flags = RTEMS_LIBIO_PERMS_SEARCH
+ | RTEMS_LIBIO_FOLLOW_LINK;
+ rtems_filesystem_location_info_t loc;
+ rtems_filesystem_global_location_t *new_current_loc;
+
+ /*
+ * We use the global environment for path evaluation. This makes it possible
+ * to escape from a chroot environment referencing an unmounted file system.
+ */
+ rtems_filesystem_eval_path_start_with_root_and_current(
+ &ctx,
+ path,
+ eval_flags,
+ &rtems_global_user_env.root_directory,
+ &rtems_global_user_env.current_directory
+ );
- result = chdir(pathname);
- if (result) {
- rtems_set_errno_and_return_minus_one( errno );
+ rtems_filesystem_eval_path_extract_currentloc( &ctx, &loc );
+ new_current_loc = rtems_filesystem_location_transform_to_global( &loc );
+ if ( !rtems_filesystem_global_location_is_null( new_current_loc ) ) {
+ rtems_filesystem_global_location_t *new_root_loc =
+ rtems_filesystem_global_location_obtain( &new_current_loc );
+ rtems_filesystem_node_types_t type =
+ (*new_root_loc->location.ops->node_type_h)( &new_root_loc->location );
+
+ if ( type == RTEMS_FILESYSTEM_DIRECTORY ) {
+ sc = rtems_libio_set_private_env();
+ if (sc == RTEMS_SUCCESSFUL) {
+ rtems_filesystem_global_location_assign(
+ &rtems_filesystem_root,
+ new_root_loc
+ );
+ rtems_filesystem_global_location_assign(
+ &rtems_filesystem_current,
+ new_current_loc
+ );
+ } else {
+ if (sc != RTEMS_UNSATISFIED) {
+ errno = ENOMEM;
+ }
+ rv = -1;
+ }
+ } else {
+ rtems_filesystem_location_error( &new_root_loc->location, ENOTDIR );
+ rv = -1;
+ }
+
+ if ( rv != 0 ) {
+ rtems_filesystem_global_location_release( new_root_loc );
+ }
+ } else {
+ rv = -1;
}
- /* clone the new root location */
- if (rtems_filesystem_evaluate_path(".", 1, 0, &loc, 0)) {
- /* our cwd has changed, though - but there is no easy way of return :-( */
- rtems_set_errno_and_return_minus_one( errno );
+ rtems_filesystem_eval_path_cleanup( &ctx );
+
+ if ( rv != 0 ) {
+ rtems_filesystem_global_location_release( new_current_loc );
}
- rtems_filesystem_freenode(&rtems_filesystem_root);
- rtems_filesystem_root = loc;
- return 0;
+ return rv;
}
diff --git a/cpukit/libcsupport/src/clonenode.c b/cpukit/libcsupport/src/clonenode.c
new file mode 100644
index 0000000000..380ad90699
--- /dev/null
+++ b/cpukit/libcsupport/src/clonenode.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+
+void rtems_filesystem_location_clone(
+ rtems_filesystem_location_info_t *clone,
+ const rtems_filesystem_location_info_t *master
+)
+{
+ int rv = 0;
+
+ clone = rtems_filesystem_location_copy( clone, master );
+ rv = (*clone->ops->clonenod_h)( clone );
+ if ( rv != 0 ) {
+ rtems_filesystem_location_remove_from_mt_entry( clone );
+ rtems_filesystem_location_initialize_to_null( clone );
+ }
+}
diff --git a/cpukit/libcsupport/src/close.c b/cpukit/libcsupport/src/close.c
index 726bca11d9..3cdd0bffba 100644
--- a/cpukit/libcsupport/src/close.c
+++ b/cpukit/libcsupport/src/close.c
@@ -22,16 +22,14 @@ int close(
)
{
rtems_libio_t *iop;
- rtems_status_code rc;
+ int rc;
rtems_libio_check_fd(fd);
iop = rtems_libio_iop(fd);
rtems_libio_check_is_open(iop);
- rc = RTEMS_SUCCESSFUL;
rc = (*iop->pathinfo.handlers->close_h)( iop );
- rtems_filesystem_freenode( &iop->pathinfo );
rtems_libio_free( iop );
return rc;
diff --git a/cpukit/libcsupport/src/eval.c b/cpukit/libcsupport/src/eval.c
deleted file mode 100644
index 5a9118d3e1..0000000000
--- a/cpukit/libcsupport/src/eval.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * rtems_filesystem_evaluate_path()
- *
- * Routine to seed the evaluate path routine.
- *
- * COPYRIGHT (c) 1989-2010.
- * On-Line Applications Research Corporation (OAR).
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
- *
- * $Id$
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <rtems.h>
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-
-int rtems_filesystem_evaluate_relative_path(
- const char *pathname,
- size_t pathnamelen,
- int flags,
- rtems_filesystem_location_info_t *pathloc,
- int follow_link
-)
-{
- int result;
- rtems_filesystem_node_types_t type;
-
- #if defined(RTEMS_DEBUG)
- /*
- * Verify Input parameters that should never be bad unless someone
- * is implementing a new filesystem and has bugs.
- */
- if ( !pathname )
- rtems_set_errno_and_return_minus_one( EFAULT );
-
- if ( !pathloc )
- rtems_set_errno_and_return_minus_one( EIO );
- #endif
-
- result = (*pathloc->ops->evalpath_h)( pathname, pathnamelen, flags, pathloc );
-
- /*
- * Get the Node type and determine if you need to follow the link or
- * not.
- */
-
- if ( (result == 0) && follow_link ) {
-
- type = (*pathloc->ops->node_type_h)( pathloc );
-
- if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) ||
- ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) {
-
- /* what to do with the valid node pathloc points to
- * if eval_link_h fails?
- * Let the FS implementation deal with this case. It
- * should probably free pathloc in either case:
- * - if the link evaluation fails, it must free the
- * original (valid) pathloc because we are going
- * to return -1 and hence the FS generics won't
- * cleanup pathloc.
- * - if the link evaluation is successful, the updated
- * pathloc will be passed up (and eventually released).
- * Hence, the (valid) originial node that we submit to
- * eval_link_h() should be released by the handler.
- */
-
- result = (*pathloc->ops->eval_link_h)( pathloc, flags );
- }
- }
-
- return result;
-}
-
-int rtems_filesystem_evaluate_path(
- const char *pathname,
- size_t pathnamelen,
- int flags,
- rtems_filesystem_location_info_t *pathloc,
- int follow_link
-)
-{
- int i = 0;
-
- #if defined(RTEMS_DEBUG)
- /*
- * Verify Input parameters that should never be bad unless someone
- * is implementing a new filesystem and has bugs.
- */
- if ( !pathname )
- rtems_set_errno_and_return_minus_one( EFAULT );
-
- if ( !pathloc )
- rtems_set_errno_and_return_minus_one( EIO );
- #endif
-
- /*
- * Evaluate the path using the optable evalpath.
- */
-
- rtems_filesystem_get_start_loc( pathname, &i, pathloc );
-
- /*
- * We evaluation the path relative to the start location we get got.
- */
- return rtems_filesystem_evaluate_relative_path( &pathname[i],
- pathnamelen - i,
- flags,
- pathloc,
- follow_link );
-}
-
-int rtems_filesystem_dirname(
- const char *pathname
-)
-{
- int len = strlen( pathname );
-
- while ( len ) {
- len--;
- if ( rtems_filesystem_is_separator( pathname[len] ) )
- break;
- }
-
- return len;
-}
-
-int rtems_filesystem_prefix_separators(
- const char *pathname,
- int pathnamelen
-)
-{
- /*
- * Eat any separators at start of the path.
- */
- int stripped = 0;
- while ( *pathname && pathnamelen && rtems_filesystem_is_separator( *pathname ) )
- {
- pathname++;
- pathnamelen--;
- stripped++;
- }
- return stripped;
-}
diff --git a/cpukit/libcsupport/src/fchdir.c b/cpukit/libcsupport/src/fchdir.c
index c95e2b7fb3..7b64ea8f21 100644
--- a/cpukit/libcsupport/src/fchdir.c
+++ b/cpukit/libcsupport/src/fchdir.c
@@ -4,6 +4,9 @@
* COPYRIGHT (c) 1989-2011.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -12,65 +15,50 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
#include <unistd.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <rtems.h>
-#include <rtems/libio.h>
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-int fchdir(
- int fd
-)
+int fchdir( int fd )
{
+ int rv = 0;
rtems_libio_t *iop;
- rtems_filesystem_location_info_t loc, saved;
+ struct stat st;
+ rtems_filesystem_location_info_t loc;
+
+ st.st_mode = 0;
+ st.st_uid = 0;
+ st.st_gid = 0;
rtems_libio_check_fd( fd );
iop = rtems_libio_iop( fd );
- rtems_libio_check_is_open(iop);
+ rtems_libio_check_is_open( iop );
- /*
- * Verify you can change directory into this node.
- */
+ rtems_filesystem_instance_lock( &iop->pathinfo );
+ rv = (*iop->pathinfo.handlers->fstat_h)( &iop->pathinfo, &st );
+ if ( rv == 0 ) {
+ bool access_ok = rtems_filesystem_check_access(
+ RTEMS_LIBIO_PERMS_EXEC,
+ st.st_mode,
+ st.st_uid,
+ st.st_gid
+ );
- if ( (*iop->pathinfo.ops->node_type_h)( &iop->pathinfo ) !=
- RTEMS_FILESYSTEM_DIRECTORY ) {
- rtems_set_errno_and_return_minus_one( ENOTDIR );
+ if ( access_ok ) {
+ rtems_filesystem_location_clone( &loc, &iop->pathinfo );
+ } else {
+ errno = EACCES;
+ rv = -1;
+ }
}
+ rtems_filesystem_instance_unlock( &iop->pathinfo );
-
- /*
- * FIXME : I feel there should be another call to
- * actually take into account the extra reference to
- * this node which we are making here. I can
- * see the freenode interface but do not see
- * allocnode node interface. It maybe node_type.
- *
- * FIXED: T.Straumann: it is evaluate_path()
- * but note the race condition. Threads who
- * share their rtems_filesystem_current better
- * be synchronized!
- */
-
- saved = rtems_filesystem_current;
- rtems_filesystem_current = iop->pathinfo;
-
- /* clone the current node */
- if (rtems_filesystem_evaluate_path(".", 1, 0, &loc, 0)) {
- /* cloning failed; restore original and bail out */
- rtems_filesystem_current = saved;
- return -1;
+ if ( rv == 0 ) {
+ rv = rtems_filesystem_chdir( &loc );
}
- /* release the old one */
- rtems_filesystem_freenode( &saved );
-
- rtems_filesystem_current = loc;
- return 0;
+ return rv;
}
diff --git a/cpukit/libcsupport/src/fchmod.c b/cpukit/libcsupport/src/fchmod.c
index e90a155bdb..e651066a77 100644
--- a/cpukit/libcsupport/src/fchmod.c
+++ b/cpukit/libcsupport/src/fchmod.c
@@ -12,31 +12,25 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <unistd.h>
#include <sys/stat.h>
-#include <errno.h>
-#include <rtems.h>
-#include <rtems/libio.h>
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-int fchmod(
- int fd,
- mode_t mode
-)
+int fchmod( int fd, mode_t mode )
{
+ int rv;
rtems_libio_t *iop;
rtems_libio_check_fd( fd );
iop = rtems_libio_iop( fd );
rtems_libio_check_is_open(iop);
- /*
- * Now process the fchmod().
- */
- return (*iop->pathinfo.handlers->fchmod_h)( &iop->pathinfo, mode );
+ rtems_filesystem_instance_lock( &iop->pathinfo );
+ rv = (*iop->pathinfo.ops->fchmod_h)( &iop->pathinfo, mode );
+ rtems_filesystem_instance_unlock( &iop->pathinfo );
+
+ return rv;
}
diff --git a/cpukit/libcsupport/src/fchown.c b/cpukit/libcsupport/src/fchown.c
index 13bb2b9da0..b5891bf36d 100644
--- a/cpukit/libcsupport/src/fchown.c
+++ b/cpukit/libcsupport/src/fchown.c
@@ -12,24 +12,16 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <sys/stat.h>
-#include <errno.h>
-
-#include <rtems.h>
-#include <rtems/libio.h>
+#include <unistd.h>
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-int fchown(
- int fd,
- uid_t owner,
- gid_t group
-)
+int fchown( int fd, uid_t owner, gid_t group )
{
+ int rv = 0;
rtems_libio_t *iop;
rtems_libio_check_fd( fd );
@@ -38,5 +30,9 @@ int fchown(
rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
- return (*iop->pathinfo.ops->chown_h)( &iop->pathinfo, owner, group );
+ rtems_filesystem_instance_lock( &iop->pathinfo );
+ rv = (*iop->pathinfo.ops->chown_h)( &iop->pathinfo, owner, group );
+ rtems_filesystem_instance_unlock( &iop->pathinfo );
+
+ return rv;
}
diff --git a/cpukit/libcsupport/src/fcntl.c b/cpukit/libcsupport/src/fcntl.c
index 988a9414ee..10f783b910 100644
--- a/cpukit/libcsupport/src/fcntl.c
+++ b/cpukit/libcsupport/src/fcntl.c
@@ -12,17 +12,53 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
-#include <errno.h>
-#include <rtems.h>
#include <rtems/libio_.h>
+static int duplicate_iop( rtems_libio_t *iop, int fd2 )
+{
+ int rv = 0;
+
+ /*
+ * FIXME: We ignore the start value fd2 for the file descriptor search. This
+ * is not POSIX conform.
+ */
+ rtems_libio_t *diop = rtems_libio_allocate();
+
+ if (diop != NULL) {
+ int oflag = rtems_libio_to_fcntl_flags( iop->flags );
+
+ oflag &= ~O_CREAT;
+ diop->flags |= rtems_libio_fcntl_flags( oflag );
+
+ rtems_filesystem_instance_lock( &iop->pathinfo );
+ rtems_filesystem_location_clone( &diop->pathinfo, &iop->pathinfo );
+ rtems_filesystem_instance_unlock( &iop->pathinfo );
+
+ /*
+ * XXX: We call the open handler here to have a proper open and close pair.
+ *
+ * FIXME: What to do with the path?
+ */
+ rv = (*diop->pathinfo.handlers->open_h)( diop, NULL, oflag, 0 );
+ if ( rv == 0 ) {
+ rv = diop - rtems_libio_iops;
+ } else {
+ rtems_libio_free( diop );
+ }
+ } else {
+ rv = -1;
+ }
+
+ return rv;
+}
+
static int vfcntl(
int fd,
int cmd,
@@ -30,7 +66,6 @@ static int vfcntl(
)
{
rtems_libio_t *iop;
- rtems_libio_t *diop;
int fd2;
int flags;
int mask;
@@ -51,20 +86,7 @@ static int vfcntl(
switch ( cmd ) {
case F_DUPFD: /* dup */
fd2 = va_arg( ap, int );
- if ( fd2 )
- diop = rtems_libio_iop( fd2 );
- else {
- /* allocate a file control block */
- diop = rtems_libio_allocate();
- if ( diop == 0 ) {
- ret = -1;
- break;
- }
- }
-
- diop->flags = iop->flags;
- diop->pathinfo = iop->pathinfo;
- ret = (int) (diop - rtems_libio_iops);
+ ret = duplicate_iop( iop, fd2 );
break;
case F_GETFD: /* get f_flags */
@@ -138,7 +160,7 @@ static int vfcntl(
*/
if (ret >= 0) {
- int err = (*iop->pathinfo.handlers->fcntl_h)( cmd, iop );
+ int err = (*iop->pathinfo.handlers->fcntl_h)( iop, cmd );
if (err) {
errno = err;
ret = -1;
diff --git a/cpukit/libcsupport/src/freenode.c b/cpukit/libcsupport/src/freenode.c
index 21a9c1de91..cc05b6034a 100644
--- a/cpukit/libcsupport/src/freenode.c
+++ b/cpukit/libcsupport/src/freenode.c
@@ -4,6 +4,9 @@
* COPYRIGHT (c) 1989-2010.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -11,10 +14,16 @@
* $Id$
*/
-#include <stdlib.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
-void rtems_filesystem_freenode( rtems_filesystem_location_info_t *_node )
+void rtems_filesystem_location_free( rtems_filesystem_location_info_t *loc )
{
- _node->ops->freenod_h(_node );
+ rtems_filesystem_instance_lock( loc );
+ (*loc->ops->freenod_h)( loc );
+ rtems_filesystem_instance_unlock( loc );
+ rtems_filesystem_location_remove_from_mt_entry( loc );
}
diff --git a/cpukit/libcsupport/src/ftruncate.c b/cpukit/libcsupport/src/ftruncate.c
index 9c50ca2fbe..66c1dc0cc6 100644
--- a/cpukit/libcsupport/src/ftruncate.c
+++ b/cpukit/libcsupport/src/ftruncate.c
@@ -12,39 +12,30 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
#include <unistd.h>
-#include <errno.h>
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-int ftruncate(
- int fd,
- off_t length
-)
+int ftruncate( int fd, off_t length )
{
- rtems_libio_t *iop;
- rtems_filesystem_location_info_t loc;
+ int rv = 0;
- rtems_libio_check_fd( fd );
- iop = rtems_libio_iop( fd );
- rtems_libio_check_is_open(iop);
- rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+ if ( length >= 0 ) {
+ rtems_libio_t *iop;
- /*
- * Now process the ftruncate() request.
- */
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open( iop );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
- /*
- * Make sure we are not working on a directory
- */
+ rv = (*iop->pathinfo.handlers->ftruncate_h)( iop, length );
+ } else {
+ errno = EINVAL;
+ rv = -1;
+ }
- loc = iop->pathinfo;
- if ( (*loc.ops->node_type_h)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
- rtems_set_errno_and_return_minus_one( EISDIR );
-
- return (*iop->pathinfo.handlers->ftruncate_h)( iop, length );
+ return rv;
}
diff --git a/cpukit/libcsupport/src/getdents.c b/cpukit/libcsupport/src/getdents.c
index d0b787cd88..82fa678978 100644
--- a/cpukit/libcsupport/src/getdents.c
+++ b/cpukit/libcsupport/src/getdents.c
@@ -32,8 +32,8 @@ int getdents(
int dd_len
)
{
- rtems_libio_t *iop;
- rtems_filesystem_location_info_t loc;
+ rtems_libio_t *iop;
+ rtems_filesystem_node_types_t type;
/*
* Get the file control block structure associated with the file descriptor
@@ -43,8 +43,8 @@ int getdents(
/*
* Make sure we are working on a directory
*/
- loc = iop->pathinfo;
- if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ type = rtems_filesystem_node_type( &iop->pathinfo );
+ if ( type != RTEMS_FILESYSTEM_DIRECTORY )
rtems_set_errno_and_return_minus_one( ENOTDIR );
/*
diff --git a/cpukit/libcsupport/src/lchown.c b/cpukit/libcsupport/src/lchown.c
index 1092f9017e..83bdf6f95c 100644
--- a/cpukit/libcsupport/src/lchown.c
+++ b/cpukit/libcsupport/src/lchown.c
@@ -12,20 +12,19 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
#include <unistd.h>
-#include <rtems.h>
+#include <rtems/libio_.h>
-int _chown_helper( const char *path, uid_t owner, gid_t group, int follow_link);
-
-int lchown(
- const char *path,
- uid_t owner,
- gid_t group
-)
+int lchown( const char *path, uid_t owner, gid_t group )
{
- return _chown_helper( path, owner, group, false );
+ return rtems_filesystem_chown(
+ path,
+ owner,
+ group,
+ RTEMS_LIBIO_FOLLOW_HARD_LINK
+ );
}
diff --git a/cpukit/libcsupport/src/libio.c b/cpukit/libcsupport/src/libio.c
index d080d01596..985ad8bad9 100644
--- a/cpukit/libcsupport/src/libio.c
+++ b/cpukit/libcsupport/src/libio.c
@@ -47,14 +47,14 @@
* Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
*/
-const rtems_assoc_t access_modes_assoc[] = {
+static const rtems_assoc_t access_modes_assoc[] = {
{ "READ", LIBIO_FLAGS_READ, O_RDONLY },
{ "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY },
{ "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
{ 0, 0, 0 },
};
-const rtems_assoc_t status_flags_assoc[] = {
+static const rtems_assoc_t status_flags_assoc[] = {
#ifdef ACCEPT_O_NDELAY_ALIAS
{ "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY },
#endif
@@ -64,9 +64,7 @@ const rtems_assoc_t status_flags_assoc[] = {
{ 0, 0, 0 },
};
-uint32_t rtems_libio_fcntl_flags(
- uint32_t fcntl_flags
-)
+uint32_t rtems_libio_fcntl_flags( int fcntl_flags )
{
uint32_t flags = 0;
uint32_t access_modes;
@@ -75,7 +73,7 @@ uint32_t rtems_libio_fcntl_flags(
* Access mode is a small integer
*/
- access_modes = fcntl_flags & O_ACCMODE;
+ access_modes = (uint32_t) (fcntl_flags & O_ACCMODE);
fcntl_flags &= ~O_ACCMODE;
flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes );
@@ -83,8 +81,11 @@ uint32_t rtems_libio_fcntl_flags(
* Everything else is single bits
*/
- flags |=
- rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
+ flags |= rtems_assoc_local_by_remote_bitfield(
+ status_flags_assoc,
+ (uint32_t) fcntl_flags
+ );
+
return flags;
}
@@ -94,11 +95,9 @@ uint32_t rtems_libio_fcntl_flags(
* Convert RTEMS internal flags to UNIX fnctl(2) flags
*/
-uint32_t rtems_libio_to_fcntl_flags(
- uint32_t flags
-)
+int rtems_libio_to_fcntl_flags( uint32_t flags )
{
- uint32_t fcntl_flags = 0;
+ int fcntl_flags = 0;
if ( (flags & LIBIO_FLAGS_READ_WRITE) == LIBIO_FLAGS_READ_WRITE ) {
fcntl_flags |= O_RDWR;
@@ -176,6 +175,8 @@ void rtems_libio_free(
rtems_libio_t *iop
)
{
+ rtems_filesystem_location_free( &iop->pathinfo );
+
rtems_libio_lock();
if (iop->sem)
@@ -187,92 +188,3 @@ void rtems_libio_free(
rtems_libio_unlock();
}
-
-/*
- * rtems_libio_is_open_files_in_fs
- *
- * This routine scans the entire file descriptor table to determine if the
- * are any active file descriptors that refer to the at least one node in the
- * file system that we are trying to dismount.
- *
- * If there is at least one node in the file system referenced by the mount
- * table entry a 1 is returned, otherwise a 0 is returned.
- */
-
-int rtems_libio_is_open_files_in_fs(
- rtems_filesystem_mount_table_entry_t * fs_mt_entry
-)
-{
- rtems_libio_t *iop;
- int result = 0;
- uint32_t i;
-
- rtems_libio_lock();
-
- /*
- * Look for any active file descriptor entry.
- */
-
- for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){
-
- if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
-
- /*
- * Check if this node is under the file system that we
- * are trying to dismount.
- */
-
- if ( iop->pathinfo.mt_entry == fs_mt_entry ) {
- result = 1;
- break;
- }
- }
- }
-
- rtems_libio_unlock();
-
- return result;
-}
-
-/*
- * rtems_libio_is_file_open
- *
- * This routine scans the entire file descriptor table to determine if the
- * given file refers to an active file descriptor.
- *
- * If the given file is open a 1 is returned, otherwise a 0 is returned.
- */
-
-int rtems_libio_is_file_open(
- void *node_access
-)
-{
- rtems_libio_t *iop;
- int result=0;
- uint32_t i;
-
- rtems_libio_lock();
-
- /*
- * Look for any active file descriptor entry.
- */
-
- for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){
- if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
-
- /*
- * Check if this node is under the file system that we
- * are trying to dismount.
- */
-
- if ( iop->pathinfo.node_access == node_access ) {
- result = 1;
- break;
- }
- }
- }
-
- rtems_libio_unlock();
-
- return result;
-}
diff --git a/cpukit/libcsupport/src/libio_sockets.c b/cpukit/libcsupport/src/libio_sockets.c
index c67e19d78c..ff02e0f4ea 100644
--- a/cpukit/libcsupport/src/libio_sockets.c
+++ b/cpukit/libcsupport/src/libio_sockets.c
@@ -18,6 +18,7 @@
#include <rtems/libio_.h>
#include <rtems/seterr.h>
+#include <rtems/rtems_bsdnet_internal.h>
/*
* Convert an RTEMS file descriptor to a BSD socket pointer.
@@ -69,5 +70,7 @@ int rtems_bsdnet_makeFdForSocket(
iop->data1 = so;
iop->pathinfo.handlers = h;
iop->pathinfo.ops = &rtems_filesystem_operations_default;
+ iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry;
+ rtems_filesystem_location_add_to_mt_entry(&iop->pathinfo);
return fd;
}
diff --git a/cpukit/libcsupport/src/link.c b/cpukit/libcsupport/src/link.c
index 11b6521dea..cf370fb9dc 100644
--- a/cpukit/libcsupport/src/link.c
+++ b/cpukit/libcsupport/src/link.c
@@ -12,65 +12,44 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <rtems.h>
-#include <rtems/libio.h>
-#include <errno.h>
+#include <unistd.h>
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-int link(
- const char *existing,
- const char *new
-)
+int link( const char *path1, const char *path2 )
{
- rtems_filesystem_location_info_t existing_loc;
- rtems_filesystem_location_info_t parent_loc;
- int i;
- int result;
- const char *name_start;
-
- /*
- * Get the node we are linking to.
- */
-
- result = rtems_filesystem_evaluate_path( existing, strlen( existing ),
- 0, &existing_loc, true );
- if ( result != 0 )
- return -1;
-
- /*
- * Get the parent of the node we are creating.
- */
-
- rtems_filesystem_get_start_loc( new, &i, &parent_loc );
-
- result = (*parent_loc.ops->evalformake_h)( &new[i], &parent_loc, &name_start );
- if ( result != 0 ) {
- rtems_filesystem_freenode( &existing_loc );
- return -1;
+ int rv = 0;
+ rtems_filesystem_eval_path_context_t ctx_1;
+ rtems_filesystem_eval_path_context_t ctx_2;
+ int eval_flags_1 = RTEMS_LIBIO_FOLLOW_LINK;
+ int eval_flags_2 = RTEMS_LIBIO_FOLLOW_LINK
+ | RTEMS_LIBIO_MAKE
+ | RTEMS_LIBIO_EXCLUSIVE;
+ const rtems_filesystem_location_info_t *currentloc_1 =
+ rtems_filesystem_eval_path_start( &ctx_1, path1, eval_flags_1 );
+ const rtems_filesystem_location_info_t *currentloc_2 =
+ rtems_filesystem_eval_path_start( &ctx_2, path2, eval_flags_2 );
+
+ rv = rtems_filesystem_location_exists_in_same_fs_instance_as(
+ currentloc_1,
+ currentloc_2
+ );
+ if ( rv == 0 ) {
+ rv = (*currentloc_2->ops->link_h)(
+ currentloc_2,
+ currentloc_1,
+ rtems_filesystem_eval_path_get_token( &ctx_2 ),
+ rtems_filesystem_eval_path_get_tokenlen( &ctx_2 )
+ );
}
- /*
- * Check to see if the caller is trying to link across file system
- * boundaries.
- */
-
- if ( parent_loc.mt_entry != existing_loc.mt_entry ) {
- rtems_filesystem_freenode( &existing_loc );
- rtems_filesystem_freenode( &parent_loc );
- rtems_set_errno_and_return_minus_one( EXDEV );
- }
-
- result = (*parent_loc.ops->link_h)( &existing_loc, &parent_loc, name_start );
-
- rtems_filesystem_freenode( &existing_loc );
- rtems_filesystem_freenode( &parent_loc );
+ rtems_filesystem_eval_path_cleanup( &ctx_1 );
+ rtems_filesystem_eval_path_cleanup( &ctx_2 );
- return result;
+ return rv;
}
/*
@@ -85,10 +64,10 @@ int link(
int _link_r(
struct _reent *ptr __attribute__((unused)),
- const char *existing,
- const char *new
+ const char *path1,
+ const char *path2
)
{
- return link( existing, new );
+ return link( path1, path2 );
}
#endif
diff --git a/cpukit/libcsupport/src/lseek.c b/cpukit/libcsupport/src/lseek.c
index 3f37029807..7c1f76b36b 100644
--- a/cpukit/libcsupport/src/lseek.c
+++ b/cpukit/libcsupport/src/lseek.c
@@ -12,64 +12,74 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <stdio.h>
+#include <unistd.h>
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-off_t lseek(
- int fd,
- off_t offset,
- int whence
-)
+off_t lseek( int fd, off_t offset, int whence )
{
+ off_t rv = 0;
rtems_libio_t *iop;
- off_t old_offset;
- off_t status;
+ off_t reference_offset;
+ off_t old_offset;
+ off_t new_offset;
rtems_libio_check_fd( fd );
iop = rtems_libio_iop( fd );
rtems_libio_check_is_open(iop);
- /*
- * Now process the lseek().
- */
-
old_offset = iop->offset;
switch ( whence ) {
case SEEK_SET:
- iop->offset = offset;
+ reference_offset = 0;
break;
-
case SEEK_CUR:
- iop->offset += offset;
+ reference_offset = old_offset;
break;
-
case SEEK_END:
- iop->offset = iop->size + offset;
+ reference_offset = iop->size;
break;
-
default:
- rtems_set_errno_and_return_minus_one( EINVAL );
+ errno = EINVAL;
+ rv = (off_t) -1;
+ break;
+ }
+ new_offset = reference_offset + offset;
+
+ if ( rv == 0 ) {
+ if (
+ (reference_offset >= 0 && new_offset >= offset)
+ || (reference_offset < 0 && new_offset <= offset)
+ ) {
+ switch ( rtems_filesystem_node_type( &iop->pathinfo ) ) {
+ case RTEMS_FILESYSTEM_DIRECTORY:
+ case RTEMS_FILESYSTEM_MEMORY_FILE:
+ if ( new_offset < 0 ) {
+ errno = EINVAL;
+ rv = (off_t) -1;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if ( rv == 0 ) {
+ iop->offset = new_offset;
+ rv = (*iop->pathinfo.handlers->lseek_h)( iop, offset, whence );
+ if ( rv == (off_t) -1 ) {
+ iop->offset = old_offset;
+ }
+ }
+ } else {
+ errno = EOVERFLOW;
+ rv = (off_t) -1;
+ }
}
- /*
- * At this time, handlers assume iop->offset has the desired
- * new offset.
- */
-
- status = (*iop->pathinfo.handlers->lseek_h)( iop, offset, whence );
- if ( status == (off_t) -1 )
- iop->offset = old_offset;
-
- /*
- * So if the operation failed, we have to restore iop->offset.
- */
-
- return status;
+ return rv;
}
/*
diff --git a/cpukit/libcsupport/src/lstat.c b/cpukit/libcsupport/src/lstat.c
index f034f4aa76..d35713eb04 100644
--- a/cpukit/libcsupport/src/lstat.c
+++ b/cpukit/libcsupport/src/lstat.c
@@ -17,6 +17,6 @@
#define _STAT_NAME lstat
#define _STAT_R_NAME _lstat_r
-#define _STAT_FOLLOW_LINKS false
+#define _STAT_FOLLOW_LINKS RTEMS_LIBIO_FOLLOW_HARD_LINK
#include "stat.c"
diff --git a/cpukit/libcsupport/src/mknod.c b/cpukit/libcsupport/src/mknod.c
index 29aff43c31..dae2b3bf98 100644
--- a/cpukit/libcsupport/src/mknod.c
+++ b/cpukit/libcsupport/src/mknod.c
@@ -16,58 +16,65 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-int mknod(
- const char *pathname,
- mode_t mode,
- dev_t dev
+int rtems_filesystem_mknod(
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
)
{
- rtems_filesystem_location_info_t temp_loc;
- int i;
- const char *name_start;
- int result;
+ int rv = 0;
- /*
- * The file type is field within the mode. Check we have a sane mode set.
- */
- switch (mode & S_IFMT)
- {
- case S_IFDIR:
- case S_IFCHR:
+ mode &= ~rtems_filesystem_umask;
+
+ switch (mode & S_IFMT) {
case S_IFBLK:
- case S_IFREG:
+ case S_IFCHR:
+ case S_IFDIR:
case S_IFIFO:
+ case S_IFREG:
break;
default:
- rtems_set_errno_and_return_minus_one( EINVAL );
+ errno = EINVAL;
+ rv = -1;
+ break;
}
- rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
+ if ( rv == 0 ) {
+ rv = (*parentloc->ops->mknod_h)( parentloc, name, namelen, mode, dev );
+ }
- result = (*temp_loc.ops->evalformake_h)(
- &pathname[i],
- &temp_loc,
- &name_start
- );
- if ( result != 0 )
- return -1;
+ return rv;
+}
- result = (*temp_loc.ops->mknod_h)( name_start, mode, dev, &temp_loc );
+int mknod( const char *path, mode_t mode, dev_t dev )
+{
+ int rv = 0;
+ rtems_filesystem_eval_path_context_t ctx;
+ int eval_flags = RTEMS_LIBIO_FOLLOW_LINK
+ | RTEMS_LIBIO_MAKE
+ | RTEMS_LIBIO_EXCLUSIVE
+ | (S_ISDIR(mode) ? RTEMS_LIBIO_ACCEPT_RESIDUAL_DELIMITERS : 0);
+ const rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
+
+ rv = rtems_filesystem_mknod(
+ currentloc,
+ rtems_filesystem_eval_path_get_token( &ctx ),
+ rtems_filesystem_eval_path_get_tokenlen( &ctx ),
+ mode,
+ dev
+ );
- rtems_filesystem_freenode( &temp_loc );
+ rtems_filesystem_eval_path_cleanup( &ctx );
- return result;
+ return rv;
}
diff --git a/cpukit/libcsupport/src/mount.c b/cpukit/libcsupport/src/mount.c
index 00a07aab3a..47c08f7dba 100644
--- a/cpukit/libcsupport/src/mount.c
+++ b/cpukit/libcsupport/src/mount.c
@@ -20,22 +20,15 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <rtems/chain.h>
-#include <rtems/seterr.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <rtems/libio_.h>
-static RTEMS_CHAIN_DEFINE_EMPTY(mount_chain);
+RTEMS_CHAIN_DEFINE_EMPTY(rtems_filesystem_mount_table);
/*
* Default pathconfs.
@@ -55,14 +48,6 @@ const rtems_filesystem_limits_and_options_t rtems_filesystem_default_pathconf =
0 /* posix_vdisable: special char processing, 0=no, 1=yes */
};
-static bool is_node_fs_root(
- const rtems_filesystem_mount_table_entry_t *mt_entry,
- void *arg
-)
-{
- return arg == mt_entry->mt_fs_root.node_access;
-}
-
static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry(
const char *source_or_null,
const char *target_or_null,
@@ -76,11 +61,15 @@ static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry(
strlen( source_or_null ) + 1 : 0;
size_t target_size = strlen( target ) + 1;
size_t size = sizeof( rtems_filesystem_mount_table_entry_t )
- + filesystemtype_size + source_size + target_size;
+ + filesystemtype_size + source_size + target_size
+ + sizeof( rtems_filesystem_global_location_t );
rtems_filesystem_mount_table_entry_t *mt_entry = calloc( 1, size );
if ( mt_entry != NULL ) {
- char *str = (char *) mt_entry + sizeof( *mt_entry );
+ rtems_filesystem_global_location_t *mt_fs_root =
+ (rtems_filesystem_global_location_t *)
+ ((char *) mt_entry + sizeof( *mt_entry ));
+ char *str = (char *) mt_fs_root + sizeof( *mt_fs_root );
memcpy( str, filesystemtype, filesystemtype_size );
mt_entry->type = str;
@@ -92,6 +81,23 @@ static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry(
memcpy( str, target, target_size );
mt_entry->target = str;
+ str += target_size;
+
+ mt_entry->mounted = true;
+ mt_entry->mt_fs_root = mt_fs_root;
+ mt_entry->pathconf_limits_and_options = rtems_filesystem_default_pathconf;
+
+ mt_fs_root->location.mt_entry = mt_entry;
+ mt_fs_root->reference_count = 1;
+
+ rtems_chain_initialize(
+ &mt_entry->location_chain,
+ mt_fs_root,
+ 1,
+ sizeof(*mt_fs_root)
+ );
+ } else {
+ free( mt_entry );
}
*target_length_ptr = target_size - 1;
@@ -99,184 +105,140 @@ static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry(
return mt_entry;
}
-/*
- * mount
- *
- * This routine will attempt to mount a new file system at the specified
- * mount point. A series of tests will be run to determine if any of the
- * following reasons exist to prevent the mount operation:
- *
- * 1) The file system type or options are not valid
- * 2) No new file system root node is specified
- * 3) The selected file system has already been mounted
- * 4) The mount point exists with the proper permissions to allow mounting
- * 5) The selected mount point already has a file system mounted to it
- *
- */
-
-int mount(
- const char *source,
- const char *target,
- const char *filesystemtype,
- rtems_filesystem_options_t options,
- const void *data
+static int register_subordinate_file_system(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ const char *target
)
{
- rtems_filesystem_fsmount_me_t mount_h = NULL;
- rtems_filesystem_location_info_t loc;
- rtems_filesystem_mount_table_entry_t *mt_entry = NULL;
- rtems_filesystem_location_info_t *loc_to_free = NULL;
- bool has_target = target != NULL;
- size_t target_length = 0;
-
- /*
- * Are the file system options valid?
- */
-
- if ( options != RTEMS_FILESYSTEM_READ_ONLY &&
- options != RTEMS_FILESYSTEM_READ_WRITE )
- rtems_set_errno_and_return_minus_one( EINVAL );
-
- /*
- * Get mount handler
- */
- mount_h = rtems_filesystem_get_mount_handler( filesystemtype );
- if ( !mount_h )
- rtems_set_errno_and_return_minus_one( EINVAL );
-
- /*
- * Allocate a mount table entry
- */
- mt_entry = alloc_mount_table_entry(
- source,
- target,
- filesystemtype,
- &target_length
- );
- if ( !mt_entry )
- rtems_set_errno_and_return_minus_one( ENOMEM );
-
- mt_entry->mt_fs_root.mt_entry = mt_entry;
- mt_entry->options = options;
- mt_entry->pathconf_limits_and_options = rtems_filesystem_default_pathconf;
-
- /*
- * The mount_point should be a directory with read/write/execute
- * permissions in the existing tree.
- */
-
- if ( has_target ) {
- if ( rtems_filesystem_evaluate_path(
- target, target_length, RTEMS_LIBIO_PERMS_RWX, &loc, true ) == -1 )
- goto cleanup_and_bail;
-
- loc_to_free = &loc;
-
- /*
- * Test to see if it is a directory
- */
-
- if ( loc.ops->node_type_h( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
- errno = ENOTDIR;
- goto cleanup_and_bail;
+ int rv = 0;
+ rtems_filesystem_eval_path_context_t ctx;
+ int eval_flags = RTEMS_LIBIO_PERMS_RWX
+ | RTEMS_LIBIO_FOLLOW_LINK;
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_start( &ctx, target, eval_flags );
+
+ if ( !rtems_filesystem_location_is_root( currentloc ) ) {
+ rtems_filesystem_location_info_t targetloc;
+ rtems_filesystem_global_location_t *mt_point_node;
+
+ rtems_filesystem_eval_path_extract_currentloc( &ctx, &targetloc );
+ mt_point_node = rtems_filesystem_location_transform_to_global( &targetloc );
+ mt_entry->mt_point_node = mt_point_node;
+ rv = (*mt_point_node->location.ops->mount_h)( mt_entry );
+ if ( rv == 0 ) {
+ rtems_filesystem_mt_lock();
+ rtems_chain_append_unprotected(
+ &rtems_filesystem_mount_table,
+ &mt_entry->mt_node
+ );
+ rtems_filesystem_mt_unlock();
+ } else {
+ rtems_filesystem_global_location_release( mt_point_node );
}
+ } else {
+ rtems_filesystem_eval_path_error( &ctx, EBUSY );
+ rv = -1;
+ }
- /*
- * You can only mount one file system onto a single mount point.
- */
+ rtems_filesystem_eval_path_cleanup( &ctx );
- if ( rtems_filesystem_mount_iterate( is_node_fs_root, loc.node_access ) ) {
- errno = EBUSY;
- goto cleanup_and_bail;
- }
+ return rv;
+}
- /*
- * This must be a good mount point, so move the location information
- * into the allocated mount entry. Note: the information that
- * may have been allocated in loc should not be sent to freenode
- * until the system is unmounted. It may be needed to correctly
- * traverse the tree.
- */
-
- mt_entry->mt_point_node.node_access = loc.node_access;
- mt_entry->mt_point_node.handlers = loc.handlers;
- mt_entry->mt_point_node.ops = loc.ops;
- mt_entry->mt_point_node.mt_entry = loc.mt_entry;
-
- /*
- * This link to the parent is only done when we are dealing with system
- * below the base file system
- */
-
- if ( loc.ops->mount_h( mt_entry ) ) {
- goto cleanup_and_bail;
- }
+static int register_root_file_system(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ int rv = 0;
+
+ rtems_filesystem_mt_lock();
+ if ( rtems_chain_is_empty( &rtems_filesystem_mount_table ) ) {
+ rtems_chain_append_unprotected(
+ &rtems_filesystem_mount_table,
+ &mt_entry->mt_node
+ );
} else {
- /*
- * Do we already have a base file system ?
- */
- if ( !rtems_chain_is_empty( &mount_chain ) ) {
- errno = EINVAL;
- goto cleanup_and_bail;
- }
-
- /*
- * This is a mount of the base file system --> The
- * mt_point_node.node_access will be left to null to indicate that this
- * is the root of the entire file system.
- */
+ errno = EINVAL;
+ rv = -1;
}
-
- if ( (*mount_h)( mt_entry, data ) ) {
- /*
- * Try to undo the mount operation
- */
- loc.ops->unmount_h( mt_entry );
- goto cleanup_and_bail;
+ rtems_filesystem_mt_unlock();
+
+ if ( rv == 0 ) {
+ rtems_filesystem_global_location_t *new_fs_root =
+ rtems_filesystem_global_location_obtain( &mt_entry->mt_fs_root );
+ rtems_filesystem_global_location_t *new_fs_current =
+ rtems_filesystem_global_location_obtain( &mt_entry->mt_fs_root );
+
+ rtems_filesystem_global_location_assign(
+ &rtems_filesystem_root,
+ new_fs_root
+ );
+ rtems_filesystem_global_location_assign(
+ &rtems_filesystem_current,
+ new_fs_current
+ );
}
- /*
- * Add the mount table entry to the mount table chain
- */
- rtems_libio_lock();
- rtems_chain_append( &mount_chain, &mt_entry->Node );
- rtems_libio_unlock();
-
- if ( !has_target )
- rtems_filesystem_root = mt_entry->mt_fs_root;
-
- return 0;
-
-cleanup_and_bail:
-
- free( mt_entry );
-
- if ( loc_to_free )
- rtems_filesystem_freenode( loc_to_free );
-
- return -1;
+ return rv;
}
-bool rtems_filesystem_mount_iterate(
- rtems_per_filesystem_mount_routine routine,
- void *routine_arg
+int mount(
+ const char *source,
+ const char *target,
+ const char *filesystemtype,
+ rtems_filesystem_options_t options,
+ const void *data
)
{
- rtems_chain_node *node = NULL;
- bool stop = false;
-
- rtems_libio_lock();
- for (
- node = rtems_chain_first( &mount_chain );
- !rtems_chain_is_tail( &mount_chain, node ) && !stop;
- node = rtems_chain_next( node )
- ) {
- const rtems_filesystem_mount_table_entry_t *mt_entry =
- (rtems_filesystem_mount_table_entry_t *) node;
+ int rv = 0;
- stop = (*routine)( mt_entry, routine_arg );
+ if (
+ options == RTEMS_FILESYSTEM_READ_ONLY
+ || options == RTEMS_FILESYSTEM_READ_WRITE
+ ) {
+ rtems_filesystem_fsmount_me_t fsmount_me_h =
+ rtems_filesystem_get_mount_handler( filesystemtype );
+
+ if ( fsmount_me_h != NULL ) {
+ size_t target_length = 0;
+ rtems_filesystem_mount_table_entry_t *mt_entry = alloc_mount_table_entry(
+ source,
+ target,
+ filesystemtype,
+ &target_length
+ );
+
+ if ( mt_entry != NULL ) {
+ mt_entry->writeable = options == RTEMS_FILESYSTEM_READ_WRITE;
+
+ rv = (*fsmount_me_h)( mt_entry, data );
+ if ( rv == 0 ) {
+ if ( target != NULL ) {
+ rv = register_subordinate_file_system( mt_entry, target );
+ } else {
+ rv = register_root_file_system( mt_entry );
+ }
+
+ if ( rv != 0 ) {
+ (*mt_entry->mt_fs_root->location.ops->fsunmount_me_h)( mt_entry );
+ }
+ }
+
+ if ( rv != 0 ) {
+ free( mt_entry );
+ }
+ } else {
+ errno = ENOMEM;
+ rv = -1;
+ }
+ } else {
+ errno = EINVAL;
+ rv = -1;
+ }
+ } else {
+ errno = EINVAL;
+ rv = -1;
}
- rtems_libio_unlock();
- return stop;
+ return rv;
}
diff --git a/cpukit/libcsupport/src/open.c b/cpukit/libcsupport/src/open.c
index a2e1b507e3..6fa7783322 100644
--- a/cpukit/libcsupport/src/open.c
+++ b/cpukit/libcsupport/src/open.c
@@ -4,6 +4,9 @@
* COPYRIGHT (c) 1989-2010.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -12,185 +15,135 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <stdarg.h>
+#include <sys/stat.h>
#include <fcntl.h>
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-
+#include <stdarg.h>
#include <unistd.h>
-/*
- * Returns file descriptor on success or -1 and errno set to one of the
- * following:
- *
- * EACCESS - Seach permission is denied on a component of the path prefix,
- * or the file exists and the permissions specified by the
- * flags are denied, or the file does not exist and write
- * permission is denied for the parent directory of the file
- * to be created, or O_TRUNC is specified and write permission
- * is denied.
- * EEXIST - O_CREAT and O_EXCL are set and the named file exists.
- * EINTR - The open( operation was interrupted by a signal.
- * EINVAL - This implementation does not support synchronized IO for this
- * file.
- * EISDIR - The named file is a directory and the flags argument
- * specified write or read/write access.
- * EMFILE - Too many file descriptors are in used by this process.
- * ENAMETOOLONG -
- * The length of the path exceeds PATH_MAX or a pathname
- * component is longer than NAME_MAX while POSIX_NO_TRUNC
- * is in effect.
- * ENFILE - Too many files are open in the system.
- * ENOENT - O_CREAT is not set and and the anmed file does not exist,
- * or O_CREAT is set and either the path prefix does not exist
- * or the path argument points to an empty string.
- * ENOSPC - The directory or file system that would contain the new file
- * cannot be extended.
- * ENOTDIR - A component of the path prefix is not a directory.
- * ENXIO - O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is
- * set, and no process has the file open for reading.
- * EROFS - The named file resides on a read-only file system and either
- * O_WRONLY, O_RDWR, O_CREAT (if the file does not exist), or
- * O_TRUNC is set in the flags argument.
- */
+#include <rtems/libio_.h>
-int open(
- const char *pathname,
- int flags,
- ...
+static void create_regular_file(
+ rtems_filesystem_eval_path_context_t *ctx,
+ mode_t mode
)
{
- va_list ap;
- mode_t mode;
- int rc;
- rtems_libio_t *iop = 0;
- int status;
- rtems_filesystem_location_info_t loc;
- rtems_filesystem_location_info_t *loc_to_free = NULL;
- int eval_flags;
-
- /*
- * Set the Evaluation flags
- */
- eval_flags = 0;
- status = flags + 1;
- if ( ( status & _FREAD ) == _FREAD )
- eval_flags |= RTEMS_LIBIO_PERMS_READ;
- if ( ( status & _FWRITE ) == _FWRITE )
- eval_flags |= RTEMS_LIBIO_PERMS_WRITE;
-
- va_start(ap, flags);
-
- mode = va_arg( ap, mode_t );
+ int rv = 0;
+ const rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc( ctx );
+ const char *token = rtems_filesystem_eval_path_get_token( ctx );
+ size_t tokenlen = rtems_filesystem_eval_path_get_tokenlen( ctx );
+
+ rv = rtems_filesystem_mknod(
+ currentloc,
+ token,
+ tokenlen,
+ S_IFREG | mode,
+ 0
+ );
+
+ if ( rv == 0 ) {
+ /* The mode only applies to future accesses of the newly created file */
+ rtems_filesystem_eval_path_set_flags( ctx, 0 );
+
+ rtems_filesystem_eval_path_set_path( ctx, token, tokenlen );
+ rtems_filesystem_eval_path_continue( ctx );
+ } else {
+ rtems_filesystem_eval_path_error( ctx, 0 );
+ }
+}
- /*
- * NOTE: This comment is OBSOLETE. The proper way to do this now
- * would be to support a magic mounted file system.
- *
- * Additional external I/O handlers would be supported by adding
- * code to pick apart the pathname appropriately. The networking
- * code does not require changes here since network file
- * descriptors are obtained using socket(), not open().
- */
-
- /* allocate a file control block */
- iop = rtems_libio_allocate();
- if ( iop == 0 ) {
- rc = ENFILE;
- goto done;
+static int do_open(
+ rtems_libio_t *iop,
+ const char *path,
+ int oflag,
+ mode_t mode
+)
+{
+ int rv = 0;
+ int fd = iop - rtems_libio_iops;
+ int rwflag = oflag + 1;
+ bool read_access = (rwflag & _FREAD) == _FREAD;
+ bool write_access = (rwflag & _FWRITE) == _FWRITE;
+ bool make = (oflag & O_CREAT) == O_CREAT;
+ bool exclusive = (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL);
+ bool truncate = (oflag & O_TRUNC) == O_TRUNC;
+ int eval_flags = RTEMS_LIBIO_FOLLOW_LINK
+ | (read_access ? RTEMS_LIBIO_PERMS_READ : 0)
+ | (write_access ? RTEMS_LIBIO_PERMS_WRITE : 0)
+ | (make ? RTEMS_LIBIO_MAKE : 0)
+ | (exclusive ? RTEMS_LIBIO_EXCLUSIVE : 0);
+ rtems_filesystem_eval_path_context_t ctx;
+
+ rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
+
+ if ( rtems_filesystem_eval_path_has_token( &ctx ) ) {
+ create_regular_file( &ctx, mode );
}
- /*
- * See if the file exists.
- */
- status = rtems_filesystem_evaluate_path(
- pathname, strlen( pathname ), eval_flags, &loc, true );
+ if ( write_access ) {
+ const rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc( &ctx );
+ rtems_filesystem_node_types_t type =
+ (*currentloc->ops->node_type_h)( currentloc );
- if ( status == -1 ) {
- if ( errno != ENOENT ) {
- rc = errno;
- goto done;
+ if ( type == RTEMS_FILESYSTEM_DIRECTORY ) {
+ rtems_filesystem_eval_path_error( &ctx, EISDIR );
}
+ }
- /* If the file does not exist and we are not trying to create it--> error */
- if ( !(flags & O_CREAT) ) {
- rc = ENOENT;
- goto done;
- }
+ iop->flags |= rtems_libio_fcntl_flags( oflag );
+ rtems_filesystem_eval_path_extract_currentloc( &ctx, &iop->pathinfo );
+ rtems_filesystem_eval_path_cleanup( &ctx );
- /* Create the node for the new regular file */
- rc = mknod( pathname, S_IFREG | mode, 0LL );
- if ( rc ) {
- rc = errno;
- goto done;
+ rv = (*iop->pathinfo.handlers->open_h)( iop, path, oflag, mode );
+
+ if ( rv == 0 ) {
+ if ( truncate ) {
+ rv = ftruncate( fd, 0 );
+ if ( rv != 0 ) {
+ (*iop->pathinfo.handlers->close_h)( iop );
+ }
}
- /*
- * After we do the mknod(), we have to evaluate the path to get the
- * "loc" structure needed to actually have the file itself open.
- * So we created it, and then we need to have "look it up."
- */
- status = rtems_filesystem_evaluate_path(
- pathname, strlen( pathname ), 0x0, &loc, true );
- if ( status != 0 ) { /* The file did not exist */
- rc = EACCES;
- goto done;
+ if ( rv == 0 ) {
+ rv = fd;
+ } else {
+ rv = -1;
}
+ }
- } else if ((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) {
- /* We were trying to create a file that already exists */
- rc = EEXIST;
- loc_to_free = &loc;
- goto done;
+ if ( rv < 0 ) {
+ rtems_libio_free( iop );
}
- loc_to_free = &loc;
+ return rv;
+}
+
+int open( const char *path, int oflag, ... )
+{
+ int rv = 0;
+ va_list ap;
+ mode_t mode = 0;
+ rtems_libio_t *iop = NULL;
- /*
- * Fill in the file control block based on the loc structure
- * returned by successful path evaluation.
- */
- iop->flags |= rtems_libio_fcntl_flags( flags );
- iop->pathinfo = loc;
+ va_start( ap, oflag );
- rc = (*iop->pathinfo.handlers->open_h)( iop, pathname, flags, mode );
- if ( rc ) {
- rc = errno;
- goto done;
- }
+ mode = va_arg( ap, mode_t );
- /*
- * Optionally truncate the file.
- */
- if ( (flags & O_TRUNC) == O_TRUNC ) {
- rc = ftruncate( iop - rtems_libio_iops, 0 );
- if ( rc ) {
- if(errno) rc = errno;
- close( iop - rtems_libio_iops );
- /* those are released by close(): */
- iop = 0;
- loc_to_free = NULL;
- }
+ iop = rtems_libio_allocate();
+ if ( iop != NULL ) {
+ rv = do_open( iop, path, oflag, mode );
+ } else {
+ errno = ENFILE;
+ rv = -1;
}
- /*
- * Single exit and clean up path.
- */
-done:
- va_end(ap);
-
- if ( rc ) {
- if ( iop )
- rtems_libio_free( iop );
- if ( loc_to_free )
- rtems_filesystem_freenode( loc_to_free );
- rtems_set_errno_and_return_minus_one( rc );
- }
+ va_end( ap );
- return iop - rtems_libio_iops;
+ return rv;
}
/*
@@ -206,10 +159,10 @@ done:
int _open_r(
struct _reent *ptr __attribute__((unused)),
const char *buf,
- int flags,
+ int oflag,
int mode
)
{
- return open( buf, flags, mode );
+ return open( buf, oflag, mode );
}
#endif
diff --git a/cpukit/libcsupport/src/privateenv.c b/cpukit/libcsupport/src/privateenv.c
index 89137200b7..28f866272b 100644
--- a/cpukit/libcsupport/src/privateenv.c
+++ b/cpukit/libcsupport/src/privateenv.c
@@ -1,3 +1,9 @@
+/**
+ * @file
+ *
+ * @ingroup LibIOEnv
+ */
+
/*
* Instantiate a private user environment for the calling thread.
*
@@ -14,191 +20,148 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <stdlib.h> /* free */
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+
+#include <stdlib.h>
-#include <rtems.h>
-#include <rtems/chain.h>
#include <rtems/libio_.h>
+#include <rtems/score/thread.h>
-/* cleanup a user environment
- * NOTE: this must be called with
- * thread dispatching disabled!
- */
-static void
-free_user_env(void *venv)
+static void free_user_env(void *arg)
{
- rtems_user_env_t *env = (rtems_user_env_t*) venv ;
-
- if (env != &rtems_global_user_env
- #ifdef HAVE_USERENV_REFCNT
- && --env->refcnt <= 0
- #endif
- ) {
- rtems_filesystem_freenode( &env->current_directory);
- rtems_filesystem_freenode( &env->root_directory);
- free(env);
+ rtems_user_env_t *env = arg;
+ bool uses_global_env = env == &rtems_global_user_env;
+
+ if (!uses_global_env) {
+ if (env->reference_count == 1) {
+ rtems_filesystem_global_location_release(env->current_directory);
+ rtems_filesystem_global_location_release(env->root_directory);
+ free(env);
+ } else {
+ --env->reference_count;
+ }
}
}
+static void free_user_env_protected(rtems_user_env_t *env)
+{
+ _Thread_Disable_dispatch();
+ free_user_env(env);
+ _Thread_Enable_dispatch();
+}
+
rtems_status_code rtems_libio_set_private_env(void)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
- rtems_id task_id = rtems_task_self();
- rtems_filesystem_location_info_t root_loc;
- rtems_filesystem_location_info_t current_loc;
- rtems_user_env_t *new_env = NULL;
- int rv = 0;
-
- rv = rtems_filesystem_evaluate_path("/", 1, 0, &root_loc, 0);
- if (rv != 0)
- goto error_0;
-
- rv = rtems_filesystem_evaluate_path("/", 1, 0, &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;
}
diff --git a/cpukit/libfs/Makefile.am b/cpukit/libfs/Makefile.am
index 20a974c33e..ad103482ef 100644
--- a/cpukit/libfs/Makefile.am
+++ b/cpukit/libfs/Makefile.am
@@ -11,22 +11,27 @@ EXTRA_DIST = README
noinst_LIBRARIES = libdefaultfs.a
libdefaultfs_a_SOURCES = \
+ src/defaults/default_clone.c \
+ src/defaults/default_are_nodes_equal.c \
+ src/defaults/default_lock_and_unlock.c \
+ src/defaults/default_eval_path.c \
src/defaults/default_fchmod.c src/defaults/default_freenode.c \
src/defaults/default_fsync.c src/defaults/default_link.c \
src/defaults/default_read.c src/defaults/default_rmnod.c \
- src/defaults/default_unlink.c src/defaults/default_chown.c \
+ src/defaults/default_chown.c \
src/defaults/default_fcntl.c src/defaults/default_fsmount.c \
src/defaults/default_ftruncate.c src/defaults/default_lseek.c \
src/defaults/default_readlink.c src/defaults/default_statvfs.c \
- src/defaults/default_utime.c src/defaults/default_evalpath.c \
+ src/defaults/default_utime.c \
src/defaults/default_fdatasync.c src/defaults/default_fstat.c \
src/defaults/default_ioctl.c src/defaults/default_mount.c \
src/defaults/default_rename.c src/defaults/default_symlink.c \
src/defaults/default_write.c \
- src/defaults/default_unmount.c src/defaults/default_evaluate_link.c \
+ src/defaults/default_unmount.c \
src/defaults/default_open.c src/defaults/default_close.c \
src/defaults/default_fsunmount.c src/defaults/default_mknod.c \
- src/defaults/default_node_type.c src/defaults/default_evalformake.c \
+ src/defaults/default_node_type.c \
+ src/defaults/default_ftruncate_directory.c \
src/defaults/default_handlers.c src/defaults/default_ops.c
noinst_LIBRARIES += libimfs.a
@@ -37,14 +42,14 @@ libimfs_a_SOURCES += src/imfs/deviceerrno.c src/imfs/deviceio.c \
src/imfs/imfs_creat.c src/imfs/imfs_debug.c src/imfs/imfs_directory.c \
src/imfs/imfs_eval.c src/imfs/imfs_fchmod.c \
src/imfs/imfs_fdatasync.c src/imfs/imfs_fifo.c \
- src/imfs/imfs_fsunmount.c src/imfs/imfs_getchild.c \
- src/imfs/imfs_gtkn.c src/imfs/imfs_handlers_device.c \
+ src/imfs/imfs_fsunmount.c \
+ src/imfs/imfs_handlers_device.c \
src/imfs/imfs_handlers_directory.c src/imfs/imfs_handlers_link.c \
src/imfs/imfs_handlers_memfile.c src/imfs/imfs_init.c \
src/imfs/imfs_initsupp.c src/imfs/imfs_link.c src/imfs/imfs_load_tar.c \
src/imfs/imfs_mknod.c src/imfs/imfs_mount.c src/imfs/imfs_ntype.c \
src/imfs/imfs_readlink.c src/imfs/imfs_rename.c src/imfs/imfs_rmnod.c \
- src/imfs/imfs_stat.c src/imfs/imfs_symlink.c src/imfs/imfs_unlink.c \
+ src/imfs/imfs_stat.c src/imfs/imfs_symlink.c \
src/imfs/imfs_unmount.c src/imfs/imfs_utime.c src/imfs/ioman.c \
src/imfs/memfile.c src/imfs/miniimfs_init.c src/imfs/imfs.h
@@ -74,6 +79,7 @@ libdosfs_a_SOURCES += src/dosfs/msdos_create.c src/dosfs/msdos_dir.c \
src/dosfs/msdos_handlers_file.c src/dosfs/msdos_init.c \
src/dosfs/msdos_initsupp.c src/dosfs/msdos_misc.c \
src/dosfs/msdos_mknod.c src/dosfs/msdos_node_type.c \
+ src/dosfs/msdos_rmnod.c \
src/dosfs/msdos_conv.c src/dosfs/msdos.h src/dosfs/msdos_format.c \
src/dosfs/dosfs.h src/dosfs/msdos_rename.c
endif
diff --git a/cpukit/libfs/src/defaults/default_are_nodes_equal.c b/cpukit/libfs/src/defaults/default_are_nodes_equal.c
new file mode 100644
index 0000000000..c1e7777c40
--- /dev/null
+++ b/cpukit/libfs/src/defaults/default_are_nodes_equal.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+
+bool rtems_filesystem_default_are_nodes_equal(
+ const rtems_filesystem_location_info_t *a,
+ const rtems_filesystem_location_info_t *b
+)
+{
+ return a->node_access == b->node_access;
+}
diff --git a/cpukit/libfs/src/defaults/default_chown.c b/cpukit/libfs/src/defaults/default_chown.c
index 82cb0b694f..55c7da9d15 100644
--- a/cpukit/libfs/src/defaults/default_chown.c
+++ b/cpukit/libfs/src/defaults/default_chown.c
@@ -9,14 +9,17 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
#include <rtems/seterr.h>
int rtems_filesystem_default_chown(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- uid_t owner, /* IN */
- gid_t group /* IN */
+ const rtems_filesystem_location_info_t *loc,
+ uid_t owner,
+ gid_t group
)
{
rtems_set_errno_and_return_minus_one( ENOTSUP );
diff --git a/cpukit/libfs/src/defaults/default_clone.c b/cpukit/libfs/src/defaults/default_clone.c
new file mode 100644
index 0000000000..5224b01d19
--- /dev/null
+++ b/cpukit/libfs/src/defaults/default_clone.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+
+int rtems_filesystem_default_clonenode(
+ rtems_filesystem_location_info_t *loc
+)
+{
+ return 0;
+}
diff --git a/cpukit/libfs/src/defaults/default_eval_path.c b/cpukit/libfs/src/defaults/default_eval_path.c
new file mode 100644
index 0000000000..e639f9985c
--- /dev/null
+++ b/cpukit/libfs/src/defaults/default_eval_path.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+
+void rtems_filesystem_default_eval_path(
+ rtems_filesystem_eval_path_context_t *ctx
+)
+{
+ ctx->pathlen = 0;
+ rtems_filesystem_location_detach(&ctx->currentloc);
+}
diff --git a/cpukit/libfs/src/defaults/default_evalformake.c b/cpukit/libfs/src/defaults/default_evalformake.c
deleted file mode 100644
index 891d961dc1..0000000000
--- a/cpukit/libfs/src/defaults/default_evalformake.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * @file
- *
- * @ingroup LibIO
- *
- * @brief rtems_filesystem_default_evalformake() implementation.
- */
-
-/*
- * Copyright (c) 2010
- * embedded brains GmbH
- * Obere Lagerstr. 30
- * D-82178 Puchheim
- * Germany
- * <rtems@embedded-brains.de>
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
- */
-
-#include <rtems/libio.h>
-#include <rtems/seterr.h>
-
-int rtems_filesystem_default_evalformake(
- const char *path,
- rtems_filesystem_location_info_t *pathloc,
- const char **name
-)
-{
- rtems_set_errno_and_return_minus_one( ENOTSUP );
-}
diff --git a/cpukit/libfs/src/defaults/default_evalpath.c b/cpukit/libfs/src/defaults/default_evalpath.c
deleted file mode 100644
index 1e3f762cbe..0000000000
--- a/cpukit/libfs/src/defaults/default_evalpath.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * COPYRIGHT (c) 2010.
- * On-Line Applications Research Corporation (OAR).
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
- *
- * $Id$
- */
-
-#include <rtems/libio.h>
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-
-int rtems_filesystem_default_evalpath(
- const char *pathname, /* IN */
- size_t pathnamelen, /* IN */
- int flags, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
-)
-{
- rtems_set_errno_and_return_minus_one( ENOTSUP );
-}
-
diff --git a/cpukit/libfs/src/defaults/default_evaluate_link.c b/cpukit/libfs/src/defaults/default_evaluate_link.c
deleted file mode 100644
index a82c73729f..0000000000
--- a/cpukit/libfs/src/defaults/default_evaluate_link.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * COPYRIGHT (c) 2010.
- * On-Line Applications Research Corporation (OAR).
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
- *
- * $Id$
- */
-
-#include <rtems/libio.h>
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-
-int rtems_filesystem_default_evaluate_link(
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- int flags /* IN */
-)
-{
- rtems_set_errno_and_return_minus_one( ENOTSUP );
-}
-
diff --git a/cpukit/libfs/src/defaults/default_fchmod.c b/cpukit/libfs/src/defaults/default_fchmod.c
index cda32c82d5..652e24322f 100644
--- a/cpukit/libfs/src/defaults/default_fchmod.c
+++ b/cpukit/libfs/src/defaults/default_fchmod.c
@@ -9,13 +9,16 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
#include <rtems/seterr.h>
int rtems_filesystem_default_fchmod(
- rtems_filesystem_location_info_t *loc,
- mode_t mode
+ const rtems_filesystem_location_info_t *loc,
+ mode_t mode
)
{
rtems_set_errno_and_return_minus_one( ENOTSUP );
diff --git a/cpukit/libfs/src/defaults/default_fcntl.c b/cpukit/libfs/src/defaults/default_fcntl.c
index d9d8602e40..0374a4f4fa 100644
--- a/cpukit/libfs/src/defaults/default_fcntl.c
+++ b/cpukit/libfs/src/defaults/default_fcntl.c
@@ -14,8 +14,8 @@
#include <rtems/seterr.h>
int rtems_filesystem_default_fcntl(
- int cmd,
- rtems_libio_t *iop
+ rtems_libio_t *iop,
+ int cmd
)
{
return 0;
diff --git a/cpukit/libfs/src/defaults/default_freenode.c b/cpukit/libfs/src/defaults/default_freenode.c
index bb231d13f7..2a5f8f1338 100644
--- a/cpukit/libfs/src/defaults/default_freenode.c
+++ b/cpukit/libfs/src/defaults/default_freenode.c
@@ -9,14 +9,15 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-int rtems_filesystem_default_freenode(
- rtems_filesystem_location_info_t *pathloc /* IN */
+void rtems_filesystem_default_freenode(
+ const rtems_filesystem_location_info_t *loc
)
{
- return 0;
+ /* Do nothing */
}
-
diff --git a/cpukit/libfs/src/defaults/default_fstat.c b/cpukit/libfs/src/defaults/default_fstat.c
index 6c8d501a21..564d4e6201 100644
--- a/cpukit/libfs/src/defaults/default_fstat.c
+++ b/cpukit/libfs/src/defaults/default_fstat.c
@@ -9,14 +9,18 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
int rtems_filesystem_default_fstat(
- rtems_filesystem_location_info_t *loc,
- struct stat *buf
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *buf
)
{
- rtems_set_errno_and_return_minus_one( ENOTSUP );
+ buf->st_mode = S_IRWXU | S_IRWXG | S_IRWXO;
+
+ return 0;
}
diff --git a/cpukit/libfs/src/defaults/default_fsunmount.c b/cpukit/libfs/src/defaults/default_fsunmount.c
index e879f5c2f8..ba4a0a1fa4 100644
--- a/cpukit/libfs/src/defaults/default_fsunmount.c
+++ b/cpukit/libfs/src/defaults/default_fsunmount.c
@@ -13,9 +13,8 @@
#include <rtems/libio_.h>
#include <rtems/seterr.h>
-int rtems_filesystem_default_fsunmount(
+void rtems_filesystem_default_fsunmount(
rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
)
{
- return 0;
}
diff --git a/cpukit/libfs/src/defaults/default_ftruncate.c b/cpukit/libfs/src/defaults/default_ftruncate.c
index b1e958f36c..ad8777487d 100644
--- a/cpukit/libfs/src/defaults/default_ftruncate.c
+++ b/cpukit/libfs/src/defaults/default_ftruncate.c
@@ -9,7 +9,10 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
#include <rtems/seterr.h>
diff --git a/cpukit/libfs/src/defaults/default_ftruncate_directory.c b/cpukit/libfs/src/defaults/default_ftruncate_directory.c
new file mode 100644
index 0000000000..e438154d77
--- /dev/null
+++ b/cpukit/libfs/src/defaults/default_ftruncate_directory.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int rtems_filesystem_default_ftruncate_directory(
+ rtems_libio_t *iop,
+ off_t length
+)
+{
+ rtems_set_errno_and_return_minus_one( EISDIR );
+}
diff --git a/cpukit/libfs/src/defaults/default_handlers.c b/cpukit/libfs/src/defaults/default_handlers.c
index ce6288bbd9..286c2b4157 100644
--- a/cpukit/libfs/src/defaults/default_handlers.c
+++ b/cpukit/libfs/src/defaults/default_handlers.c
@@ -29,10 +29,8 @@ const rtems_filesystem_file_handlers_r rtems_filesystem_handlers_default = {
.ioctl_h = rtems_filesystem_default_ioctl,
.lseek_h = rtems_filesystem_default_lseek,
.fstat_h = rtems_filesystem_default_fstat,
- .fchmod_h = rtems_filesystem_default_fchmod,
.ftruncate_h = rtems_filesystem_default_ftruncate,
.fsync_h = rtems_filesystem_default_fsync,
.fdatasync_h = rtems_filesystem_default_fdatasync,
- .fcntl_h = rtems_filesystem_default_fcntl,
- .rmnod_h = rtems_filesystem_default_rmnod
+ .fcntl_h = rtems_filesystem_default_fcntl
};
diff --git a/cpukit/libfs/src/defaults/default_link.c b/cpukit/libfs/src/defaults/default_link.c
index d9bc913b27..40b70a89f8 100644
--- a/cpukit/libfs/src/defaults/default_link.c
+++ b/cpukit/libfs/src/defaults/default_link.c
@@ -9,16 +9,19 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
#include <rtems/seterr.h>
int rtems_filesystem_default_link(
- rtems_filesystem_location_info_t *to_loc, /* IN */
- rtems_filesystem_location_info_t *parent_loc, /* IN */
- const char *name /* IN */
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *targetloc,
+ const char *name,
+ size_t namelen
)
{
rtems_set_errno_and_return_minus_one( ENOTSUP );
}
-
diff --git a/cpukit/libfs/src/defaults/default_lock_and_unlock.c b/cpukit/libfs/src/defaults/default_lock_and_unlock.c
new file mode 100644
index 0000000000..de29a076f1
--- /dev/null
+++ b/cpukit/libfs/src/defaults/default_lock_and_unlock.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+
+void rtems_filesystem_default_lock(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ rtems_libio_lock();
+}
+
+void rtems_filesystem_default_unlock(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ rtems_libio_unlock();
+}
diff --git a/cpukit/libfs/src/defaults/default_mknod.c b/cpukit/libfs/src/defaults/default_mknod.c
index fcd03be4c2..17a208a772 100644
--- a/cpukit/libfs/src/defaults/default_mknod.c
+++ b/cpukit/libfs/src/defaults/default_mknod.c
@@ -9,15 +9,19 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
#include <rtems/seterr.h>
int rtems_filesystem_default_mknod(
- const char *path, /* IN */
- mode_t mode, /* IN */
- dev_t dev, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
)
{
rtems_set_errno_and_return_minus_one( ENOTSUP );
diff --git a/cpukit/libfs/src/defaults/default_node_type.c b/cpukit/libfs/src/defaults/default_node_type.c
index a118a04f72..6627fbf5dd 100644
--- a/cpukit/libfs/src/defaults/default_node_type.c
+++ b/cpukit/libfs/src/defaults/default_node_type.c
@@ -22,7 +22,7 @@
#include <rtems/libio.h>
rtems_filesystem_node_types_t rtems_filesystem_default_node_type(
- rtems_filesystem_location_info_t *pathloc
+ const rtems_filesystem_location_info_t *loc
)
{
return RTEMS_FILESYSTEM_INVALID_NODE_TYPE;
diff --git a/cpukit/libfs/src/defaults/default_open.c b/cpukit/libfs/src/defaults/default_open.c
index b119fbf5be..aa856bfb8f 100644
--- a/cpukit/libfs/src/defaults/default_open.c
+++ b/cpukit/libfs/src/defaults/default_open.c
@@ -9,16 +9,18 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
int rtems_filesystem_default_open(
rtems_libio_t *iop,
- const char *pathname,
- uint32_t flag,
- uint32_t mode
+ const char *path,
+ int oflag,
+ mode_t mode
)
{
- rtems_set_errno_and_return_minus_one( ENOTSUP );
+ return 0;
}
diff --git a/cpukit/libfs/src/defaults/default_ops.c b/cpukit/libfs/src/defaults/default_ops.c
index 575cf6b2d4..dfd1ba2009 100644
--- a/cpukit/libfs/src/defaults/default_ops.c
+++ b/cpukit/libfs/src/defaults/default_ops.c
@@ -22,20 +22,23 @@
#include <rtems/libio.h>
const rtems_filesystem_operations_table rtems_filesystem_operations_default = {
- .evalpath_h = rtems_filesystem_default_evalpath,
- .evalformake_h = rtems_filesystem_default_evalformake,
+ .lock_h = rtems_filesystem_default_lock,
+ .unlock_h = rtems_filesystem_default_unlock,
+ .eval_path_h = rtems_filesystem_default_eval_path,
.link_h = rtems_filesystem_default_link,
- .unlink_h = rtems_filesystem_default_unlink,
+ .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
.node_type_h = rtems_filesystem_default_node_type,
.mknod_h = rtems_filesystem_default_mknod,
+ .rmnod_h = rtems_filesystem_default_rmnod,
+ .fchmod_h = rtems_filesystem_default_fchmod,
.chown_h = rtems_filesystem_default_chown,
+ .clonenod_h = rtems_filesystem_default_clonenode,
.freenod_h = rtems_filesystem_default_freenode,
.mount_h = rtems_filesystem_default_mount,
.fsmount_me_h = rtems_filesystem_default_fsmount,
.unmount_h = rtems_filesystem_default_unmount,
.fsunmount_me_h = rtems_filesystem_default_fsunmount,
.utime_h = rtems_filesystem_default_utime,
- .eval_link_h = rtems_filesystem_default_evaluate_link,
.symlink_h = rtems_filesystem_default_symlink,
.readlink_h = rtems_filesystem_default_readlink,
.rename_h = rtems_filesystem_default_rename,
diff --git a/cpukit/libfs/src/defaults/default_readlink.c b/cpukit/libfs/src/defaults/default_readlink.c
index 1d07970999..028eb3f75a 100644
--- a/cpukit/libfs/src/defaults/default_readlink.c
+++ b/cpukit/libfs/src/defaults/default_readlink.c
@@ -9,14 +9,17 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
#include <rtems/seterr.h>
ssize_t rtems_filesystem_default_readlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- char *buf, /* OUT */
- size_t bufsize
+ const rtems_filesystem_location_info_t *loc,
+ char *buf,
+ size_t bufsize
)
{
rtems_set_errno_and_return_minus_one( ENOTSUP );
diff --git a/cpukit/libfs/src/defaults/default_rename.c b/cpukit/libfs/src/defaults/default_rename.c
index 93bf15f2e0..748d74b3ec 100644
--- a/cpukit/libfs/src/defaults/default_rename.c
+++ b/cpukit/libfs/src/defaults/default_rename.c
@@ -9,15 +9,19 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
#include <rtems/seterr.h>
int rtems_filesystem_default_rename(
- rtems_filesystem_location_info_t *old_parent_loc, /* IN */
- rtems_filesystem_location_info_t *old_loc, /* IN */
- rtems_filesystem_location_info_t *new_parent_loc, /* IN */
- const char *name /* IN */
+ const rtems_filesystem_location_info_t *oldparentloc,
+ const rtems_filesystem_location_info_t *oldloc,
+ const rtems_filesystem_location_info_t *newparentloc,
+ const char *name,
+ size_t namelen
)
{
rtems_set_errno_and_return_minus_one( ENOTSUP );
diff --git a/cpukit/libfs/src/defaults/default_rmnod.c b/cpukit/libfs/src/defaults/default_rmnod.c
index 776ee4b659..8c1014bb98 100644
--- a/cpukit/libfs/src/defaults/default_rmnod.c
+++ b/cpukit/libfs/src/defaults/default_rmnod.c
@@ -9,13 +9,16 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
#include <rtems/seterr.h>
int rtems_filesystem_default_rmnod(
- rtems_filesystem_location_info_t *parent_loc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *loc
)
{
rtems_set_errno_and_return_minus_one( ENOTSUP );
diff --git a/cpukit/libfs/src/defaults/default_statvfs.c b/cpukit/libfs/src/defaults/default_statvfs.c
index 22d891815f..f26ecc6a7c 100644
--- a/cpukit/libfs/src/defaults/default_statvfs.c
+++ b/cpukit/libfs/src/defaults/default_statvfs.c
@@ -9,13 +9,16 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
#include <rtems/seterr.h>
int rtems_filesystem_default_statvfs(
- rtems_filesystem_location_info_t *loc, /* IN */
- struct statvfs *buf /* OUT */
+ const rtems_filesystem_location_info_t *loc,
+ struct statvfs *buf
)
{
rtems_set_errno_and_return_minus_one( ENOTSUP );
diff --git a/cpukit/libfs/src/defaults/default_symlink.c b/cpukit/libfs/src/defaults/default_symlink.c
index 8985d76aef..95ae455379 100644
--- a/cpukit/libfs/src/defaults/default_symlink.c
+++ b/cpukit/libfs/src/defaults/default_symlink.c
@@ -9,14 +9,18 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
#include <rtems/seterr.h>
int rtems_filesystem_default_symlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- const char *link_name, /* IN */
- const char *node_name
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ const char *target
)
{
rtems_set_errno_and_return_minus_one( ENOTSUP );
diff --git a/cpukit/libfs/src/defaults/default_unlink.c b/cpukit/libfs/src/defaults/default_unlink.c
deleted file mode 100644
index cf633c6ce1..0000000000
--- a/cpukit/libfs/src/defaults/default_unlink.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * COPYRIGHT (c) 2010.
- * On-Line Applications Research Corporation (OAR).
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
- *
- * $Id$
- */
-
-#include <rtems/libio.h>
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-
-int rtems_filesystem_default_unlink(
- rtems_filesystem_location_info_t *parent_pathloc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */
-)
-{
- rtems_set_errno_and_return_minus_one( ENOTSUP );
-}
diff --git a/cpukit/libfs/src/defaults/default_utime.c b/cpukit/libfs/src/defaults/default_utime.c
index 77a2f2e8d6..b1f57c7f5b 100644
--- a/cpukit/libfs/src/defaults/default_utime.c
+++ b/cpukit/libfs/src/defaults/default_utime.c
@@ -9,16 +9,18 @@
* $Id$
*/
-#include <rtems/libio.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <rtems/libio_.h>
#include <rtems/seterr.h>
int rtems_filesystem_default_utime(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- time_t actime, /* IN */
- time_t modtime /* IN */
+ const rtems_filesystem_location_info_t *loc,
+ time_t actime,
+ time_t modtime
)
{
rtems_set_errno_and_return_minus_one( ENOTSUP );
}
-
diff --git a/cpukit/libfs/src/devfs/devclose.c b/cpukit/libfs/src/devfs/devclose.c
index 773cade5c6..f69ac291fe 100644
--- a/cpukit/libfs/src/devfs/devclose.c
+++ b/cpukit/libfs/src/devfs/devclose.c
@@ -21,9 +21,7 @@ int devFS_close(
{
rtems_libio_open_close_args_t args;
rtems_status_code status;
- rtems_device_name_t *np;
-
- np = (rtems_device_name_t *)iop->pathinfo.node_access;
+ const devFS_node *np = iop->pathinfo.node_access;
args.iop = iop;
args.flags = 0;
diff --git a/cpukit/libfs/src/devfs/devfs.h b/cpukit/libfs/src/devfs/devfs.h
index 6e4f2478c7..758edf932b 100644
--- a/cpukit/libfs/src/devfs/devfs.h
+++ b/cpukit/libfs/src/devfs/devfs.h
@@ -17,38 +17,54 @@ extern "C" {
/**
* This structure define the type of device table
*/
-
-typedef struct
-{
- /** This member points to device name which is a null-terminated string */
- const char *device_name;
+typedef struct {
+ /** This member points to device name which is not a null-terminated string */
+ const char *name;
/** This member is the name length of a device */
- uint32_t device_name_length;
+ size_t namelen;
/** major number of a device */
rtems_device_major_number major;
/** minor number of a device */
rtems_device_minor_number minor;
/** device creation mode, only device file can be created */
mode_t mode;
+} devFS_node;
-} rtems_device_name_t;
+typedef struct {
+ devFS_node *nodes;
+ size_t count;
+} devFS_data;
+/**
+ * The following defines the device-only filesystem operating
+ * operations.
+ */
+extern const rtems_filesystem_operations_table devFS_ops;
/**
- * This routine associates RTEMS status code with errno
+ * The following defines the device-only filesystem operating
+ * handlers.
*/
-extern int rtems_deviceio_errno(rtems_status_code code);
-
+extern const rtems_filesystem_file_handlers_r devFS_file_handlers;
/**
- * The following defines the device table size. This values
- * is configured during application configuration time by
- * the user. The default value is set to 4.
+ * This routine associates RTEMS status code with errno
*/
-extern uint32_t rtems_device_table_size;
+extern int rtems_deviceio_errno(rtems_status_code code);
+
+static inline const devFS_data *devFS_get_data(
+ const rtems_filesystem_location_info_t *loc
+)
+{
+ return loc->mt_entry->immutable_fs_info;
+}
+
+extern void devFS_eval_path(
+ rtems_filesystem_eval_path_context_t *ctx
+);
/**
* This handler maps open operation to rtems_io_open.
@@ -62,8 +78,8 @@ extern uint32_t rtems_device_table_size;
extern int devFS_open(
rtems_libio_t *iop,
const char *pathname,
- uint32_t flag,
- uint32_t mode
+ int oflag,
+ mode_t mode
);
@@ -142,8 +158,8 @@ extern int devFS_ioctl(
*/
extern int devFS_stat(
- rtems_filesystem_location_info_t *loc,
- struct stat *buf
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *buf
);
@@ -153,63 +169,15 @@ extern int devFS_stat(
* Since this is a device-only filesystem, so there is only
* one node type in the system.
*
- * @param pathloc contains filesytem access information, this
+ * @param loc contains filesytem access information, this
* parameter is ignored
* @retval always returns RTEMS_FILESYSTEM_DEVICE
*/
extern rtems_filesystem_node_types_t devFS_node_type(
- rtems_filesystem_location_info_t *pathloc
+ const rtems_filesystem_location_info_t*loc
);
-
-
-/**
- * This routine is invoked to determine if 'pathname' exists.
- * This routine first check access flags, then it searches
- * the device table to get the information.
- *
- * @param pathname device name to be searched
- * @param flags access flags
- * @param pathloc contains filesystem access information
- * @retval upon success(pathname exists), this routines
- * returns 0; if 'flag' is invalid, it returns -1 and errno
- * is set to EIO; otherwise, it returns -1 and errno is set to ENOENT
- */
-
-extern int devFS_evaluate_path(
- const char *pathname,
- size_t pathnamelen,
- int flags,
- rtems_filesystem_location_info_t *pathloc
-);
-
-
-/**
- * This routine is given a path to evaluate and a valid start
- * location. It is responsible for finding the parent node for
- * a requested make command, setting pathloc information to
- * identify the parent node, and setting the name pointer to
- * the first character of the name of the new node. In device
- * only filesystem, devices do not has a tree hierarchy, there
- * are no parent-child relationship. So this routine is rather
- * simple, it just set *name to path and returns
- *
- * @param path device path to be evaluated
- * @param pathloc contains filesystem access information, this
- * parameter is ignored
- * @param name
- * @retval always returns 0
- */
-
-extern int devFS_evaluate_for_make(
- const char *path,
- rtems_filesystem_location_info_t *pathloc,
- const char **name
-);
-
-
-
/**
* This routine is invoked upon registration of a new device
* file. It is responsible for creating a item in the main
@@ -217,21 +185,15 @@ extern int devFS_evaluate_for_make(
* sequential order, when found a empty slot, it fills the slot
* with proper values.
*
- * @param path the device file name to be registered
- * @param mode file mode, this parameter is ignored
- * @param dev device major and minor number
- * @param pathloc contains filesystem access information
- * @retval upon success, this routine returns 0; if 'path'
- * already exist, it returns -1 and errno is set to EEXIST;
- * if device table is full, it returns -1 and errno is set
- * to ENOMEM
+ * @see rtems_filesystem_mknod_t.
*/
extern int devFS_mknod(
- const char *path,
- mode_t mode,
- dev_t dev,
- rtems_filesystem_location_info_t *pathloc
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
);
@@ -266,11 +228,9 @@ extern int devFS_initialize(
*
* This routine is intended for debugging, and can be used by shell
* program to provide user with the system information.
- *
- * @retval 0
*/
-extern int devFS_Show(void);
+extern void devFS_Show(void);
#ifdef __cplusplus
}
diff --git a/cpukit/libfs/src/devfs/devfs_eval.c b/cpukit/libfs/src/devfs/devfs_eval.c
index a3169fb3fa..b7a31ee921 100644
--- a/cpukit/libfs/src/devfs/devfs_eval.c
+++ b/cpukit/libfs/src/devfs/devfs_eval.c
@@ -7,79 +7,84 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <rtems/seterr.h>
-#include <fcntl.h>
-#include <assert.h>
-#include "devfs.h"
-
-/**
- * The following defines the device-only filesystem operating
- * handlers.
- */
+#include <string.h>
-extern rtems_filesystem_operations_table devFS_ops;
-
-/**
- * The following defines the device-only filesystem operating
- * handlers.
- */
-
-extern rtems_filesystem_file_handlers_r devFS_file_handlers;
+#include "devfs.h"
-int devFS_evaluate_path(
- const char *pathname,
- size_t pathnamelen,
- int flags,
- rtems_filesystem_location_info_t *pathloc
+static devFS_node *devFS_search_node(
+ const devFS_data *data,
+ const char *path,
+ size_t pathlen,
+ devFS_node **free_node_ptr
)
{
- int i;
- rtems_device_name_t *device_name_table;
-
- /* see if 'flags' is valid */
- if ( !rtems_libio_is_valid_perms( flags ) )
- rtems_set_errno_and_return_minus_one( EPERM );
-
- /* get the device name table */
- device_name_table = (rtems_device_name_t *)pathloc->node_access;
- if (!device_name_table)
- rtems_set_errno_and_return_minus_one( EFAULT );
-
- for (i = 0; i < rtems_device_table_size; i++) {
- if (!device_name_table[i].device_name)
- continue;
-
- if (strncmp(pathname, device_name_table[i].device_name, pathnamelen) != 0)
- continue;
-
- if (device_name_table[i].device_name[pathnamelen] != '\0')
- continue;
-
- /* find the device, set proper values */
- pathloc->node_access = (void *)&device_name_table[i];
- pathloc->handlers = &devFS_file_handlers;
- pathloc->ops = &devFS_ops;
- pathloc->mt_entry = rtems_filesystem_root.mt_entry;
- return 0;
+ size_t i = 0;
+ size_t n = data->count;
+ devFS_node *nodes = data->nodes;
+ devFS_node *node = NULL;
+ devFS_node *free_node = NULL;
+
+ for (i = 0; (free_node == NULL || node == NULL) && i < n; ++i) {
+ devFS_node *current = nodes + i;
+
+ if (current->name != NULL) {
+ if (
+ current->namelen == pathlen
+ && memcmp(current->name, path, pathlen) == 0
+ ) {
+ node = current;
+ }
+ } else {
+ free_node = current;
+ }
}
- /* no such file or directory */
- rtems_set_errno_and_return_minus_one( ENOENT );
-}
-
+ *free_node_ptr = free_node;
+ return node;
+}
-int devFS_evaluate_for_make(
- const char *path,
- rtems_filesystem_location_info_t *pathloc,
- const char **name
+void devFS_eval_path(
+ rtems_filesystem_eval_path_context_t *ctx
)
{
- /* we do nothing, just set name to path */
- *name = path;
- return 0;
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc(ctx);
+ devFS_node *free_node;
+ devFS_node *node = devFS_search_node(
+ devFS_get_data(currentloc),
+ rtems_filesystem_eval_path_get_path(ctx),
+ rtems_filesystem_eval_path_get_pathlen(ctx),
+ &free_node
+ );
+ int eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
+
+ if (node != NULL) {
+ if ((eval_flags & RTEMS_LIBIO_EXCLUSIVE) == 0) {
+ currentloc->node_access = node;
+ rtems_filesystem_eval_path_clear_path(ctx);
+ } else {
+ rtems_filesystem_eval_path_error(ctx, EEXIST);
+ }
+ } else {
+ if ((eval_flags & RTEMS_LIBIO_MAKE) != 0) {
+ if (free_node != NULL) {
+ free_node->mode = S_IRWXU | S_IRWXG | S_IRWXO;
+ currentloc->node_access = free_node;
+ rtems_filesystem_eval_path_set_token(
+ ctx,
+ rtems_filesystem_eval_path_get_path(ctx),
+ rtems_filesystem_eval_path_get_pathlen(ctx)
+ );
+ rtems_filesystem_eval_path_clear_path(ctx);
+ } else {
+ rtems_filesystem_eval_path_error(ctx, ENOSPC);
+ }
+ } else {
+ rtems_filesystem_eval_path_error(ctx, ENOENT);
+ }
+ }
}
-
diff --git a/cpukit/libfs/src/devfs/devfs_init.c b/cpukit/libfs/src/devfs/devfs_init.c
index bd741e41a2..070aced2a4 100644
--- a/cpukit/libfs/src/devfs/devfs_init.c
+++ b/cpukit/libfs/src/devfs/devfs_init.c
@@ -7,85 +7,65 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <stdlib.h>
-#include <rtems.h>
-#include <rtems/seterr.h>
-#include <rtems/score/wkspace.h>
#include "devfs.h"
-rtems_filesystem_operations_table devFS_ops =
-{
- devFS_evaluate_path,
- devFS_evaluate_for_make,
- rtems_filesystem_default_link,
- rtems_filesystem_default_unlink,
- devFS_node_type,
- devFS_mknod,
- rtems_filesystem_default_chown,
- rtems_filesystem_default_freenode,
- rtems_filesystem_default_mount,
- devFS_initialize,
- rtems_filesystem_default_unmount,
- rtems_filesystem_default_fsunmount,
- rtems_filesystem_default_utime,
- rtems_filesystem_default_evaluate_link,
- rtems_filesystem_default_symlink,
- rtems_filesystem_default_readlink,
- rtems_filesystem_default_rename,
- rtems_filesystem_default_statvfs
+const rtems_filesystem_operations_table devFS_ops = {
+ .lock_h = rtems_filesystem_default_lock,
+ .unlock_h = rtems_filesystem_default_unlock,
+ .eval_path_h = devFS_eval_path,
+ .link_h = rtems_filesystem_default_link,
+ .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
+ .node_type_h = devFS_node_type,
+ .mknod_h = devFS_mknod,
+ .rmnod_h = rtems_filesystem_default_rmnod,
+ .fchmod_h = rtems_filesystem_default_fchmod,
+ .chown_h = rtems_filesystem_default_chown,
+ .clonenod_h = rtems_filesystem_default_clonenode,
+ .freenod_h = rtems_filesystem_default_freenode,
+ .mount_h = rtems_filesystem_default_mount,
+ .fsmount_me_h = devFS_initialize,
+ .unmount_h = rtems_filesystem_default_unmount,
+ .fsunmount_me_h = rtems_filesystem_default_fsunmount,
+ .utime_h = rtems_filesystem_default_utime,
+ .symlink_h = rtems_filesystem_default_symlink,
+ .readlink_h = rtems_filesystem_default_readlink,
+ .rename_h = rtems_filesystem_default_rename,
+ .statvfs_h = rtems_filesystem_default_statvfs
};
-
-rtems_filesystem_file_handlers_r devFS_file_handlers =
-{
- devFS_open,
- devFS_close,
- devFS_read,
- devFS_write,
- devFS_ioctl,
- rtems_filesystem_default_lseek,
- devFS_stat,
- rtems_filesystem_default_fchmod,
- rtems_filesystem_default_ftruncate,
- rtems_filesystem_default_fsync,
- rtems_filesystem_default_fdatasync,
- rtems_filesystem_default_fcntl,
- rtems_filesystem_default_rmnod
+const rtems_filesystem_file_handlers_r devFS_file_handlers = {
+ .open_h = devFS_open,
+ .close_h = devFS_close,
+ .read_h = devFS_read,
+ .write_h = devFS_write,
+ .ioctl_h = devFS_ioctl,
+ .lseek_h = rtems_filesystem_default_lseek,
+ .fstat_h = devFS_stat,
+ .ftruncate_h = rtems_filesystem_default_ftruncate,
+ .fsync_h = rtems_filesystem_default_fsync,
+ .fdatasync_h = rtems_filesystem_default_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl
};
-
-
int devFS_initialize(
- rtems_filesystem_mount_table_entry_t *temp_mt_entry,
- const void *data
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ const void *data
)
{
- rtems_device_name_t *device_name_table;
-
- /* allocate device only filesystem name table */
- device_name_table = (rtems_device_name_t *)_Workspace_Allocate(
- sizeof( rtems_device_name_t ) * ( rtems_device_table_size )
- );
-
- /* no memory for device filesystem */
- if (!device_name_table)
- rtems_set_errno_and_return_minus_one( ENOMEM );
-
- memset(
- device_name_table, 0,
- sizeof( rtems_device_name_t ) * ( rtems_device_table_size )
- );
-
- /* set file handlers */
- temp_mt_entry->mt_fs_root.handlers = &devFS_file_handlers;
- temp_mt_entry->mt_fs_root.ops = &devFS_ops;
+ int rv = 0;
- /* Set the node_access to device name table */
- temp_mt_entry->mt_fs_root.node_access = (void *)device_name_table;
+ if (data != NULL) {
+ mt_entry->immutable_fs_info = data;
+ mt_entry->mt_fs_root->location.handlers = &devFS_file_handlers;
+ mt_entry->mt_fs_root->location.ops = &devFS_ops;
+ } else {
+ errno = EINVAL;
+ rv = -1;
+ }
- return 0;
+ return rv;
}
diff --git a/cpukit/libfs/src/devfs/devfs_mknod.c b/cpukit/libfs/src/devfs/devfs_mknod.c
index 4a8b8b3523..9760c5e5c7 100644
--- a/cpukit/libfs/src/devfs/devfs_mknod.c
+++ b/cpukit/libfs/src/devfs/devfs_mknod.c
@@ -7,75 +7,52 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
#include <stdlib.h>
+#include <string.h>
-#include <rtems/seterr.h>
#include "devfs.h"
int devFS_mknod(
- const char *path,
- mode_t mode,
- dev_t dev,
- rtems_filesystem_location_info_t *pathloc
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
)
{
- int i;
- int slot;
- rtems_device_name_t *device_name_table;
- rtems_device_major_number major;
- rtems_device_minor_number minor;
- ISR_Level level;
-
- /*
- * This is a special case. In rtems_filesystem_initialize,
- * a special device '/dev' will be created. We check this
- * condition and do not create the '/dev' and the 'path'
- * actually passed in is 'dev', not '/dev'. Just return 0 to
- * indicate we are OK.
- */
-
- if ((path[0] == 'd') && (path[1] == 'e') &&
- (path[2] == 'v') && (path[3] == '\0'))
- return 0;
-
- /* must be a character device or a block device */
- if (!S_ISBLK(mode) && !S_ISCHR(mode))
- rtems_set_errno_and_return_minus_one( EINVAL );
- else
- rtems_filesystem_split_dev_t(dev, major, minor);
-
- /* Find an empty slot in device name table */
- device_name_table = (rtems_device_name_t *)pathloc->node_access;
- if (!device_name_table)
- rtems_set_errno_and_return_minus_one( EFAULT );
-
- for (slot = -1, i = 0; i < rtems_device_table_size; i++){
- if (device_name_table[i].device_name == NULL)
- slot = i;
- else
- if (strcmp(path, device_name_table[i].device_name) == 0)
- rtems_set_errno_and_return_minus_one( EEXIST );
+ int rv = 0;
+
+ if (namelen != 3 || name [0] != 'd' || name [1] != 'e' || name [2] != 'v') {
+ if (S_ISBLK(mode) || S_ISCHR(mode)) {
+ char *dupname = malloc(namelen);
+
+ if (dupname != NULL) {
+ devFS_node *node = parentloc->node_access;
+
+ node->name = dupname;
+ node->namelen = namelen;
+ node->major = rtems_filesystem_dev_major_t(dev);
+ node->minor = rtems_filesystem_dev_minor_t(dev);
+ node->mode = mode;
+ memcpy(dupname, name, namelen);
+ } else {
+ errno = ENOMEM;
+ rv = -1;
+ }
+ } else {
+ errno = ENOTSUP;
+ rv = -1;
+ }
+ } else {
+ if (!S_ISDIR(mode)) {
+ errno = ENOTSUP;
+ rv = -1;
+ }
}
- if (slot == -1)
- rtems_set_errno_and_return_minus_one( ENOMEM );
-
- _ISR_Disable(level);
- device_name_table[slot].device_name = path;
- device_name_table[slot].device_name_length = strlen(path);
- device_name_table[slot].major = major;
- device_name_table[slot].minor = minor;
- device_name_table[slot].mode = mode;
- _ISR_Enable(level);
-
- return 0;
+ return rv;
}
-
diff --git a/cpukit/libfs/src/devfs/devfs_node_type.c b/cpukit/libfs/src/devfs/devfs_node_type.c
index 0bede52d2d..c4bd488680 100644
--- a/cpukit/libfs/src/devfs/devfs_node_type.c
+++ b/cpukit/libfs/src/devfs/devfs_node_type.c
@@ -13,7 +13,7 @@
#include "devfs.h"
rtems_filesystem_node_types_t devFS_node_type(
- rtems_filesystem_location_info_t *pathloc
+ const rtems_filesystem_location_info_t *loc
)
{
/*
diff --git a/cpukit/libfs/src/devfs/devfs_show.c b/cpukit/libfs/src/devfs/devfs_show.c
index e449caf49f..6d30d3f5d6 100644
--- a/cpukit/libfs/src/devfs/devfs_show.c
+++ b/cpukit/libfs/src/devfs/devfs_show.c
@@ -7,30 +7,38 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <rtems/seterr.h>
#include "devfs.h"
-int devFS_Show(void)
+void devFS_Show(void)
{
- int i;
- rtems_filesystem_location_info_t *temp_loc;
- rtems_device_name_t *device_name_table;
+ rtems_filesystem_location_info_t *rootloc = &rtems_filesystem_root->location;
- temp_loc = &rtems_filesystem_root;
- device_name_table = (rtems_device_name_t *)temp_loc->node_access;
- if (!device_name_table)
- rtems_set_errno_and_return_minus_one( EFAULT );
+ if (rootloc->ops == &devFS_ops) {
+ const devFS_data *data = devFS_get_data(rootloc);
+ size_t i = 0;
+ size_t n = data->count;
+ devFS_node *nodes = data->nodes;
- for (i = 0; i < rtems_device_table_size; i++){
- if (device_name_table[i].device_name){
- printk("/%s %d %d\n", device_name_table[i].device_name,
- device_name_table[i].major, device_name_table[i].minor);
+ for (i = 0; i < n; ++i) {
+ devFS_node *current = nodes + i;
+
+ if (current->name != NULL) {
+ size_t j = 0;
+ size_t m = current->namelen;
+
+ printk("/");
+ for (j = 0; j < m; ++j) {
+ printk("%c", current->name [j]);
+ }
+ printk(
+ " %lu %lu\n",
+ (unsigned long) current->major,
+ (unsigned long) current->minor
+ );
+ }
}
}
- return 0;
}
-
-
diff --git a/cpukit/libfs/src/devfs/devioctl.c b/cpukit/libfs/src/devfs/devioctl.c
index 15965b8c0e..457596fdc4 100644
--- a/cpukit/libfs/src/devfs/devioctl.c
+++ b/cpukit/libfs/src/devfs/devioctl.c
@@ -23,9 +23,7 @@ int devFS_ioctl(
{
rtems_libio_ioctl_args_t args;
rtems_status_code status;
- rtems_device_name_t *np;
-
- np = (rtems_device_name_t *)iop->pathinfo.node_access;
+ const devFS_node *np = iop->pathinfo.node_access;
args.iop = iop;
args.command = command;
diff --git a/cpukit/libfs/src/devfs/devopen.c b/cpukit/libfs/src/devfs/devopen.c
index 67be3678e1..1b100e1cc7 100644
--- a/cpukit/libfs/src/devfs/devopen.c
+++ b/cpukit/libfs/src/devfs/devopen.c
@@ -18,15 +18,13 @@
int devFS_open(
rtems_libio_t *iop,
const char *pathname,
- uint32_t flag,
- uint32_t mode
+ int oflag,
+ mode_t mode
)
{
rtems_libio_open_close_args_t args;
rtems_status_code status;
- rtems_device_name_t *np;
-
- np = (rtems_device_name_t *)iop->pathinfo.node_access;
+ const devFS_node *np = iop->pathinfo.node_access;
args.iop = iop;
args.flags = iop->flags;
diff --git a/cpukit/libfs/src/devfs/devread.c b/cpukit/libfs/src/devfs/devread.c
index 10f74e81c9..31d3f35db9 100644
--- a/cpukit/libfs/src/devfs/devread.c
+++ b/cpukit/libfs/src/devfs/devread.c
@@ -23,9 +23,7 @@ ssize_t devFS_read(
{
rtems_libio_rw_args_t args;
rtems_status_code status;
- rtems_device_name_t *np;
-
- np = (rtems_device_name_t *)iop->pathinfo.node_access;
+ const devFS_node *np = iop->pathinfo.node_access;
args.iop = iop;
args.offset = iop->offset;
diff --git a/cpukit/libfs/src/devfs/devstat.c b/cpukit/libfs/src/devfs/devstat.c
index e0c52b8b3d..1b780cc58b 100644
--- a/cpukit/libfs/src/devfs/devstat.c
+++ b/cpukit/libfs/src/devfs/devstat.c
@@ -7,40 +7,25 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <rtems.h>
-#include <rtems/io.h>
-#include <rtems/seterr.h>
-#include <rtems/libio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
#include "devfs.h"
int devFS_stat(
- rtems_filesystem_location_info_t *loc,
- struct stat *buf
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *buf
)
{
- rtems_device_name_t *the_dev;
-
- the_dev = (rtems_device_name_t *)loc->node_access;
+ int rv = 0;
+ const devFS_node *the_dev = loc->node_access;
- /*
- * stat() invokes devFS_evaluate_path() which checks that node_access
- * is not NULL. So this should NEVER be NULL unless someone breaks
- * other code in this filesystem.
- */
- #if defined(RTEMS_DEBUG)
- if (!the_dev)
- rtems_set_errno_and_return_minus_one( EFAULT );
- #endif
+ if (the_dev != NULL) {
+ buf->st_rdev = rtems_filesystem_make_dev_t( the_dev->major, the_dev->minor );
+ buf->st_mode = the_dev->mode;
+ } else {
+ rv = rtems_filesystem_default_fstat(loc, buf);
+ }
- buf->st_rdev = rtems_filesystem_make_dev_t( the_dev->major, the_dev->minor );
- buf->st_mode = the_dev->mode;
- return 0;
+ return rv;
}
-
-
diff --git a/cpukit/libfs/src/devfs/devwrite.c b/cpukit/libfs/src/devfs/devwrite.c
index 5389c69bc5..2b3aac412b 100644
--- a/cpukit/libfs/src/devfs/devwrite.c
+++ b/cpukit/libfs/src/devfs/devwrite.c
@@ -23,9 +23,7 @@ ssize_t devFS_write(
{
rtems_libio_rw_args_t args;
rtems_status_code status;
- rtems_device_name_t *np;
-
- np = (rtems_device_name_t *)iop->pathinfo.node_access;
+ const devFS_node *np = iop->pathinfo.node_access;
args.iop = iop;
args.offset = iop->offset;
diff --git a/cpukit/libfs/src/dosfs/msdos.h b/cpukit/libfs/src/dosfs/msdos.h
index 5e24d6ad1d..9bdfd881ec 100644
--- a/cpukit/libfs/src/dosfs/msdos.h
+++ b/cpukit/libfs/src/dosfs/msdos.h
@@ -168,7 +168,6 @@ typedef rtems_filesystem_node_types_t msdos_node_type_t;
/*
* Macros for names parsing and formatting
*/
-#define msdos_is_separator(_ch) rtems_filesystem_is_separator(_ch)
#define MSDOS_SHORT_BASE_LEN 8 /* 8 characters */
#define MSDOS_SHORT_EXT_LEN 3 /* 3 characters */
@@ -224,44 +223,40 @@ typedef enum msdos_token_types_e
#define MSDOS_DPS512_NUM 16
/* Prototypes */
-int msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry);
+void msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry);
-int msdos_eval_path(
- const char *pathname, /* IN */
- size_t pathnamelen, /* IN */
- int flags, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
-);
-
-int msdos_eval4make(
- const char *path, /* IN */
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- const char **name /* OUT */
-);
+void msdos_eval_path(rtems_filesystem_eval_path_context_t *ctx);
-int msdos_unlink(rtems_filesystem_location_info_t *pathloc /* IN */);
+void msdos_free_node_info(const rtems_filesystem_location_info_t *pathloc);
-int msdos_free_node_info(rtems_filesystem_location_info_t *pathloc /* IN */);
-
-rtems_filesystem_node_types_t msdos_node_type(rtems_filesystem_location_info_t *pathloc);
+rtems_filesystem_node_types_t msdos_node_type(
+ const rtems_filesystem_location_info_t *loc
+);
int msdos_mknod(
- const char *path, /* IN */
- mode_t mode, /* IN */
- dev_t dev, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+ const rtems_filesystem_location_info_t *loc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
);
-int msdos_utime(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- time_t actime, /* IN */
- time_t modtime /* IN */
+int msdos_rmnod(
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *loc
);
-int msdos_rename(rtems_filesystem_location_info_t *old_parent_loc,
- rtems_filesystem_location_info_t *old_loc,
- rtems_filesystem_location_info_t *new_parent_loc,
- const char *new_name);
+int msdos_rename(
+ const rtems_filesystem_location_info_t *old_parent_loc,
+ const rtems_filesystem_location_info_t *old_loc,
+ const rtems_filesystem_location_info_t *new_parent_loc,
+ const char *new_name,
+ size_t new_namelen
+);
+
+void msdos_lock(rtems_filesystem_mount_table_entry_t *mt_entry);
+
+void msdos_unlock(rtems_filesystem_mount_table_entry_t *mt_entry);
int msdos_initialize_support(
rtems_filesystem_mount_table_entry_t *temp_mt_entry,
@@ -273,8 +268,8 @@ int msdos_initialize_support(
int msdos_file_open(
rtems_libio_t *iop, /* IN */
const char *pathname, /* IN */
- uint32_t flag, /* IN */
- uint32_t mode /* IN */
+ int oflag, /* IN */
+ mode_t mode /* IN */
);
int msdos_file_close(rtems_libio_t *iop /* IN */);
@@ -298,8 +293,8 @@ off_t msdos_file_lseek(
);
int msdos_file_stat(
- rtems_filesystem_location_info_t *loc, /* IN */
- struct stat *buf /* OUT */
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *buf
);
int
@@ -312,26 +307,11 @@ int msdos_file_sync(rtems_libio_t *iop);
int msdos_file_datasync(rtems_libio_t *iop);
-int msdos_file_ioctl(
- rtems_libio_t *iop, /* IN */
- uint32_t command, /* IN */
- void *buffer /* IN */
-);
-
-int
-msdos_dir_chmod(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- mode_t mode /* IN */
-);
-
-int msdos_file_rmnod(rtems_filesystem_location_info_t *parent_pathloc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */);
-
int msdos_dir_open(
rtems_libio_t *iop, /* IN */
const char *pathname, /* IN */
- uint32_t flag, /* IN */
- uint32_t mode /* IN */
+ int oflag, /* IN */
+ mode_t mode /* IN */
);
int msdos_dir_close(rtems_libio_t *iop /* IN */);
@@ -348,34 +328,21 @@ off_t msdos_dir_lseek(
int whence /* IN */
);
-int
-msdos_file_chmod(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- mode_t mode /* IN */
-);
-
-int msdos_dir_rmnod(rtems_filesystem_location_info_t *parent_pathloc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */);
-
int msdos_dir_sync(rtems_libio_t *iop);
int msdos_dir_stat(
- rtems_filesystem_location_info_t *loc, /* IN */
- struct stat *buf /* OUT */
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *buf
);
-int msdos_creat_node(rtems_filesystem_location_info_t *parent_loc,
- msdos_node_type_t type,
- const char *name,
- int name_len,
- mode_t mode,
- const fat_file_fd_t *link_fd);
+int msdos_creat_node(const rtems_filesystem_location_info_t *parent_loc,
+ msdos_node_type_t type,
+ const char *name,
+ int name_len,
+ mode_t mode,
+ const fat_file_fd_t *link_fd);
/* Misc prototypes */
-msdos_token_types_t msdos_get_token(const char *path,
- int pathlen,
- const char **token,
- int *token_len);
int msdos_find_name(
rtems_filesystem_location_info_t *parent_loc,
@@ -384,13 +351,13 @@ int msdos_find_name(
);
int msdos_get_name_node(
- rtems_filesystem_location_info_t *parent_loc,
- bool create_node,
- const char *name,
- int name_len,
- msdos_name_type_t name_type,
- fat_dir_pos_t *dir_pos,
- char *name_dir_entry
+ const rtems_filesystem_location_info_t *parent_loc,
+ bool create_node,
+ const char *name,
+ int name_len,
+ msdos_name_type_t name_type,
+ fat_dir_pos_t *dir_pos,
+ char *name_dir_entry
);
int msdos_dir_info_remove(rtems_filesystem_location_info_t *pathloc);
diff --git a/cpukit/libfs/src/dosfs/msdos_create.c b/cpukit/libfs/src/dosfs/msdos_create.c
index ec5862a178..263df36353 100644
--- a/cpukit/libfs/src/dosfs/msdos_create.c
+++ b/cpukit/libfs/src/dosfs/msdos_create.c
@@ -55,12 +55,12 @@
*
*/
int
-msdos_creat_node(rtems_filesystem_location_info_t *parent_loc,
- msdos_node_type_t type,
- const char *name,
- int name_len,
- mode_t mode,
- const fat_file_fd_t *link_fd)
+msdos_creat_node(const rtems_filesystem_location_info_t *parent_loc,
+ msdos_node_type_t type,
+ const char *name,
+ int name_len,
+ mode_t mode,
+ const fat_file_fd_t *link_fd)
{
int rc = RC_OK;
ssize_t ret = 0;
@@ -83,9 +83,16 @@ msdos_creat_node(rtems_filesystem_location_info_t *parent_loc,
memset(short_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
memset(dot_dotdot, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2);
+ if (name_len > MSDOS_NAME_MAX_LFN_WITH_DOT) {
+ rtems_set_errno_and_return_minus_one(ENAMETOOLONG);
+ }
+
name_type = msdos_long_to_short (name, name_len,
MSDOS_DIR_NAME(short_node),
MSDOS_NAME_MAX);
+ if (name_type == MSDOS_NAME_INVALID) {
+ rtems_set_errno_and_return_minus_one(EINVAL);
+ }
/* fill reserved field */
*MSDOS_DIR_NT_RES(short_node) = MSDOS_RES_NT_VALUE;
diff --git a/cpukit/libfs/src/dosfs/msdos_dir.c b/cpukit/libfs/src/dosfs/msdos_dir.c
index 494b9fbae6..725fd254d0 100644
--- a/cpukit/libfs/src/dosfs/msdos_dir.c
+++ b/cpukit/libfs/src/dosfs/msdos_dir.c
@@ -33,20 +33,10 @@
/* msdos_dir_open --
* Open fat-file which correspondes to the directory being opened and
* set offset field of file control block to zero.
- *
- * PARAMETERS:
- * iop - file control block
- * pathname - name
- * flag - flags
- * mode - mode
- *
- * RETURNS:
- * RC_OK, if directory opened successfully, or -1 if error occured (errno
- * set apropriately)
*/
int
-msdos_dir_open(rtems_libio_t *iop, const char *pathname, uint32_t flag,
- uint32_t mode)
+msdos_dir_open(rtems_libio_t *iop, const char *pathname, int oflag,
+ mode_t mode)
{
int rc = RC_OK;
rtems_status_code sc = RTEMS_SUCCESSFUL;
@@ -529,9 +519,9 @@ msdos_dir_lseek(rtems_libio_t *iop, off_t offset, int whence)
*/
int
msdos_dir_stat(
- rtems_filesystem_location_info_t *loc,
- struct stat *buf
- )
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
@@ -594,103 +584,3 @@ msdos_dir_sync(rtems_libio_t *iop)
rtems_semaphore_release(fs_info->vol_sema);
return rc;
}
-
-/* msdos_dir_chmod --
- * Change the attributes of the directory. This currently does
- * nothing and returns no error.
- *
- * PARAMETERS:
- * pathloc - node description
- * mode - the new mode
- *
- * RETURNS:
- * RC_OK always
- */
-int
-msdos_dir_chmod(rtems_filesystem_location_info_t *pathloc,
- mode_t mode)
-{
- return RC_OK;
-}
-
-/* msdos_dir_rmnod --
- * Remove directory node.
- *
- * Check that this directory node is not opened as fat-file, is empty and
- * not filesystem root node. If all this conditions met then delete.
- *
- * PARAMETERS:
- * pathloc - node description
- *
- * RETURNS:
- * RC_OK on success, or -1 if error occured (errno set apropriately).
- */
-int
-msdos_dir_rmnod(rtems_filesystem_location_info_t *parent_pathloc,
- rtems_filesystem_location_info_t *pathloc)
-{
- int rc = RC_OK;
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
- fat_file_fd_t *fat_fd = pathloc->node_access;
- bool is_empty = false;
-
- sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
- MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
- if (sc != RTEMS_SUCCESSFUL)
- rtems_set_errno_and_return_minus_one(EIO);
-
- /*
- * You cannot remove a node that still has children
- */
- rc = msdos_dir_is_empty(pathloc->mt_entry, fat_fd, &is_empty);
- if (rc != RC_OK)
- {
- rtems_semaphore_release(fs_info->vol_sema);
- return rc;
- }
-
- if (!is_empty)
- {
- rtems_semaphore_release(fs_info->vol_sema);
- rtems_set_errno_and_return_minus_one(ENOTEMPTY);
- }
-
- /*
- * We deny attempts to delete open directory (if directory is current
- * directory we assume it is open one)
- */
- if (fat_fd->links_num > 1)
- {
- rtems_semaphore_release(fs_info->vol_sema);
- rtems_set_errno_and_return_minus_one(EBUSY);
- }
-
- /*
- * You cannot remove the file system root node.
- */
- if (rtems_filesystem_is_root_location(pathloc))
- {
- rtems_semaphore_release(fs_info->vol_sema);
- rtems_set_errno_and_return_minus_one(EBUSY);
- }
-
- /*
- * You cannot remove a mountpoint.
- * not used - mount() not implemenetd yet.
- */
-
- /* mark file removed */
- rc = msdos_set_first_char4file_name(pathloc->mt_entry, &fat_fd->dir_pos,
- MSDOS_THIS_DIR_ENTRY_EMPTY);
- if (rc != RC_OK)
- {
- rtems_semaphore_release(fs_info->vol_sema);
- return rc;
- }
-
- fat_file_mark_removed(pathloc->mt_entry, fat_fd);
-
- rtems_semaphore_release(fs_info->vol_sema);
- return rc;
-}
diff --git a/cpukit/libfs/src/dosfs/msdos_eval.c b/cpukit/libfs/src/dosfs/msdos_eval.c
index 9b5e0c835d..0ab5971e62 100644
--- a/cpukit/libfs/src/dosfs/msdos_eval.c
+++ b/cpukit/libfs/src/dosfs/msdos_eval.c
@@ -52,384 +52,58 @@ msdos_set_handlers(rtems_filesystem_location_info_t *loc)
loc->handlers = fs_info->file_handlers;
}
-/* msdos_eval_path --
- *
- * The following routine evaluate path for a node that wishes to be
- * accessed. Structure 'pathloc' is returned with a pointer to the
- * node to be accessed.
- *
- * PARAMETERS:
- * pathname - path for evaluation
- * flags - flags
- * pathloc - node description (IN/OUT)
- *
- * RETURNS:
- * RC_OK and filled pathloc on success, or -1 if error occured
- * (errno set appropriately)
- *
- */
-int
-msdos_eval_path(
- const char *pathname,
- size_t pathnamelen,
- int flags,
- rtems_filesystem_location_info_t *pathloc
- )
+static bool msdos_is_directory(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg
+)
{
- int rc = RC_OK;
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
- fat_file_fd_t *fat_fd = NULL;
- rtems_filesystem_location_info_t newloc;
- int i = 0;
- int token_len = 0;
- msdos_token_types_t type = MSDOS_CURRENT_DIR;
- const char *token;
-
- sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
- MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
- if (sc != RTEMS_SUCCESSFUL)
- rtems_set_errno_and_return_minus_one(EIO);
-
- if (!pathloc->node_access)
- {
- errno = ENOENT;
- rc = -1;
- goto err;
- }
-
- fat_fd = pathloc->node_access;
-
- rc = fat_file_reopen(fat_fd);
- if (rc != RC_OK)
- goto err;
-
- while ((type != MSDOS_NO_MORE_PATH) && (type != MSDOS_INVALID_TOKEN))
- {
- type = msdos_get_token(&pathname[i], pathnamelen, &token, &token_len);
- pathnamelen -= token_len;
- i += token_len;
-
- fat_fd = pathloc->node_access;
-
- switch (type)
- {
- case MSDOS_UP_DIR:
- /*
- * Only a directory can be decended into.
- */
- if (fat_fd->fat_file_type != FAT_DIRECTORY)
- {
- errno = ENOTSUP;
- rc = -1;
- goto error;
- }
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc( ctx );
+ fat_file_fd_t *fat_fd = currentloc->node_access;
- /*
- * Am I at the root of this mounted filesystem?
- */
- if (rtems_filesystem_is_root_location(pathloc))
- {
- /*
- * Am I at the root of all filesystems?
- * XXX: MSDOS is not supposed to be base fs.
- */
- if (pathloc->node_access ==
- rtems_filesystem_root.node_access)
- {
- break; /* Throw out the .. in this case */
- }
- else
- {
- newloc = pathloc->mt_entry->mt_point_node;
- *pathloc = newloc;
-
- rc = fat_file_close(pathloc->mt_entry, fat_fd);
- if (rc != RC_OK)
- goto err;
-
- rtems_semaphore_release(fs_info->vol_sema);
- return (*pathloc->ops->evalpath_h)(&(pathname[i-token_len]),
- pathnamelen + token_len,
- flags, pathloc);
- }
- }
- else
- {
- rc = msdos_find_name(pathloc, token, token_len);
- if (rc != RC_OK)
- {
- if (rc == MSDOS_NAME_NOT_FOUND_ERR)
- {
- errno = ENOENT;
- rc = -1;
- }
- goto error;
- }
- }
- break;
-
- case MSDOS_NAME:
- /*
- * Only a directory can be decended into.
- */
- if (fat_fd->fat_file_type != FAT_DIRECTORY)
- {
- errno = ENOTSUP;
- rc = -1;
- goto error;
- }
-
- /*
- * Otherwise find the token name in the present location and
- * set the node access to the point we have found.
- */
- rc = msdos_find_name(pathloc, token, token_len);
- if (rc != RC_OK)
- {
- if (rc == MSDOS_NAME_NOT_FOUND_ERR)
- {
- errno = ENOENT;
- rc = -1;
- }
- goto error;
- }
- break;
-
- case MSDOS_NO_MORE_PATH:
- case MSDOS_CURRENT_DIR:
- break;
-
- case MSDOS_INVALID_TOKEN:
- errno = ENAMETOOLONG;
- rc = -1;
- goto error;
- break;
-
- }
- }
-
- /*
- * Always return the root node.
- *
- * If we are at a node that is a mount point. Set loc to the
- * new fs root node and let let the mounted filesystem set the handlers.
- *
- * NOTE: The behavior of stat() on a mount point appears to be
- * questionable.
- * NOTE: MSDOS filesystem currently doesn't support mount functionality ->
- * action not implemented
- */
- fat_fd = pathloc->node_access;
-
- msdos_set_handlers(pathloc);
-
- rtems_semaphore_release(fs_info->vol_sema);
- return RC_OK;
-
-error:
- fat_file_close(pathloc->mt_entry, fat_fd);
-
-err:
- rtems_semaphore_release(fs_info->vol_sema);
- return rc;
+ return fat_fd->fat_file_type == MSDOS_DIRECTORY;
}
-/* msdos_eval4make --
- * The following routine evaluate path for a new node to be created.
- * 'pathloc' is returned with a pointer to the parent of the new node.
- * 'name' is returned with a pointer to the first character in the
- * new node name. The parent node is verified to be a directory.
- *
- * PARAMETERS:
- * path - path for evaluation
- * pathloc - IN/OUT (start point for evaluation/parent directory for
- * creation)
- * name - new node name
- *
- * RETURNS:
- * RC_OK, filled pathloc for parent directory and name of new node on
- * success, or -1 if error occured (errno set appropriately)
- */
-int
-msdos_eval4make(
- const char *path,
- rtems_filesystem_location_info_t *pathloc,
- const char **name
- )
+static rtems_filesystem_eval_path_generic_status msdos_eval_token(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg,
+ const char *token,
+ size_t tokenlen
+)
{
- int rc = RC_OK;
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
- fat_file_fd_t *fat_fd = NULL;
- rtems_filesystem_location_info_t newloc;
- msdos_token_types_t type;
- int i = 0;
- int token_len;
- const char *token;
- bool done = false;
-
- sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
- MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
- if (sc != RTEMS_SUCCESSFUL)
- rtems_set_errno_and_return_minus_one(EIO);
-
- if (!pathloc->node_access)
- {
- errno = ENOENT;
- rc = -1;
- goto err;
+ rtems_filesystem_eval_path_generic_status status =
+ RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
+
+ if (rtems_filesystem_is_current_directory(token, tokenlen)) {
+ rtems_filesystem_eval_path_clear_token(ctx);
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
+ } else {
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc(ctx);
+ int rc = msdos_find_name(currentloc, token, tokenlen);
+
+ if (rc == RC_OK) {
+ rtems_filesystem_eval_path_clear_token(ctx);
+ msdos_set_handlers(currentloc);
+ if (rtems_filesystem_eval_path_has_path(ctx)) {
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
+ }
+ } else if (rc == MSDOS_NAME_NOT_FOUND_ERR) {
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
+ } else {
+ rtems_filesystem_eval_path_error(ctx, 0);
}
+ }
- fat_fd = pathloc->node_access;
-
- rc = fat_file_reopen(fat_fd);
- if (rc != RC_OK)
- goto err;
-
- while (!done)
- {
- type = msdos_get_token(&path[i], strlen(&path[i]), &token, &token_len);
- i += token_len;
- fat_fd = pathloc->node_access;
-
- switch (type)
- {
- case MSDOS_UP_DIR:
- /*
- * Only a directory can be decended into.
- */
- if (fat_fd->fat_file_type != FAT_DIRECTORY)
- {
- errno = ENOTDIR;
- rc = -1;
- goto error;
- }
-
- /*
- * Am I at the root of this mounted filesystem?
- */
- if (rtems_filesystem_is_root_location(pathloc))
- {
- /*
- * Am I at the root of all filesystems?
- * XXX: MSDOS is not supposed to be base fs.
- */
- if (pathloc->node_access ==
- rtems_filesystem_root.node_access)
- {
- break; /* Throw out the .. in this case */
- }
- else
- {
- newloc = pathloc->mt_entry->mt_point_node;
- *pathloc = newloc;
-
- rc = fat_file_close(pathloc->mt_entry, fat_fd);
- if (rc != RC_OK)
- goto err;
-
- rtems_semaphore_release(fs_info->vol_sema);
- return (*pathloc->ops->evalformake_h)(&path[i-token_len],
- pathloc, name);
- }
- }
- else
- {
- rc = msdos_find_name(pathloc, token, token_len);
- if (rc != RC_OK)
- {
- if (rc == MSDOS_NAME_NOT_FOUND_ERR)
- {
- errno = ENOENT;
- rc = -1;
- }
- goto error;
- }
- }
- break;
-
- case MSDOS_NAME:
- /*
- * Only a directory can be decended into.
- */
- if (fat_fd->fat_file_type != FAT_DIRECTORY)
- {
- errno = ENOTDIR;
- rc = -1;
- goto error;
- }
-
- /*
- * Otherwise find the token name in the present location and
- * set the node access to the point we have found.
- */
- rc = msdos_find_name(pathloc, token, token_len);
- if (rc)
- {
- if (rc != MSDOS_NAME_NOT_FOUND_ERR)
- {
- errno = ENOENT;
- rc = -1;
- goto error;
- }
- else
- done = true;
- }
- break;
-
- case MSDOS_NO_MORE_PATH:
- errno = EEXIST;
- rc = -1;
- goto error;
- break;
-
- case MSDOS_CURRENT_DIR:
- break;
-
- case MSDOS_INVALID_TOKEN:
- errno = ENAMETOOLONG;
- rc = -1;
- goto error;
- break;
-
- }
- }
-
- *name = &path[i - token_len];
-
- /*
- * We have evaluated the path as far as we can.
- * Verify there is not any invalid stuff at the end of the name.
- */
- for( ; path[i] != '\0'; i++)
- {
- if (!msdos_is_separator(path[i]))
- {
- errno = ENOENT;
- rc = -1;
- goto error;
- }
- }
-
- fat_fd = pathloc->node_access;
-
- if (fat_fd->fat_file_type != FAT_DIRECTORY)
- {
- errno = ENOTDIR;
- rc = -1;
- goto error;
- }
-
- msdos_set_handlers(pathloc);
-
- rtems_semaphore_release(fs_info->vol_sema);
- return RC_OK;
+ return status;
+}
-error:
- fat_file_close(pathloc->mt_entry, fat_fd);
+static const rtems_filesystem_eval_path_generic_config msdos_eval_config = {
+ .is_directory = msdos_is_directory,
+ .eval_token = msdos_eval_token
+};
-err:
- rtems_semaphore_release(fs_info->vol_sema);
- return rc;
+void msdos_eval_path(rtems_filesystem_eval_path_context_t *ctx)
+{
+ rtems_filesystem_eval_path_generic(ctx, NULL, &msdos_eval_config);
}
diff --git a/cpukit/libfs/src/dosfs/msdos_file.c b/cpukit/libfs/src/dosfs/msdos_file.c
index 5378a25914..b2f98b890d 100644
--- a/cpukit/libfs/src/dosfs/msdos_file.c
+++ b/cpukit/libfs/src/dosfs/msdos_file.c
@@ -41,8 +41,8 @@
* and errno set appropriately
*/
int
-msdos_file_open(rtems_libio_t *iop, const char *pathname, uint32_t flag,
- uint32_t mode)
+msdos_file_open(rtems_libio_t *iop, const char *pathname, int oflag,
+ mode_t mode)
{
int rc = RC_OK;
rtems_status_code sc = RTEMS_SUCCESSFUL;
@@ -268,9 +268,9 @@ msdos_file_lseek(rtems_libio_t *iop, off_t offset, int whence)
*/
int
msdos_file_stat(
- rtems_filesystem_location_info_t *loc,
- struct stat *buf
- )
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
@@ -426,81 +426,3 @@ msdos_file_datasync(rtems_libio_t *iop)
rtems_semaphore_release(fs_info->vol_sema);
return RC_OK;
}
-
-
-/* msdos_file_ioctl --
- *
- *
- * PARAMETERS:
- * iop - file control block
- * ...
- *
- * RETURNS:
- *
- */
-int
-msdos_file_ioctl(rtems_libio_t *iop,uint32_t command, void *buffer)
-{
- int rc = RC_OK;
-
- return rc;
-}
-
-/* msdos_file_chmod --
- * Change the attributes of the file. This currently does
- * nothing and returns no error.
- *
- * PARAMETERS:
- * pathloc - node description
- * mode - the new mode
- *
- * RETURNS:
- * RC_OK always
- */
-int
-msdos_file_chmod(rtems_filesystem_location_info_t *pathloc,
- mode_t mode)
-{
- return RC_OK;
-}
-
-/* msdos_file_rmnod --
- * Remove node associated with a file - set up first name character to
- * predefined value(and write it to the disk), and mark fat-file which
- * correspondes to the file as "removed"
- *
- * PARAMETERS:
- * pathloc - node description
- *
- * RETURNS:
- * RC_OK on success, or -1 if error occured (errno set appropriately)
- */
-int
-msdos_file_rmnod(rtems_filesystem_location_info_t *parent_pathloc,
- rtems_filesystem_location_info_t *pathloc)
-{
- int rc = RC_OK;
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
- fat_file_fd_t *fat_fd = pathloc->node_access;
-
- sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
- MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
- if (sc != RTEMS_SUCCESSFUL)
- rtems_set_errno_and_return_minus_one(EIO);
-
- /* mark file removed */
- rc = msdos_set_first_char4file_name(pathloc->mt_entry,
- &fat_fd->dir_pos,
- MSDOS_THIS_DIR_ENTRY_EMPTY);
- if (rc != RC_OK)
- {
- rtems_semaphore_release(fs_info->vol_sema);
- return rc;
- }
-
- fat_file_mark_removed(pathloc->mt_entry, fat_fd);
-
- rtems_semaphore_release(fs_info->vol_sema);
- return RC_OK;
-}
diff --git a/cpukit/libfs/src/dosfs/msdos_free.c b/cpukit/libfs/src/dosfs/msdos_free.c
index 90fc586a10..da99dc5d36 100644
--- a/cpukit/libfs/src/dosfs/msdos_free.c
+++ b/cpukit/libfs/src/dosfs/msdos_free.c
@@ -29,28 +29,9 @@
/* msdos_free_node_info --
* Call fat-file close routine.
- *
- * PARAMETERS:
- * pathloc - node description
- *
- * RETURNS:
- * RC_OK on success, or -1 code if error occured
- *
*/
-int
-msdos_free_node_info(rtems_filesystem_location_info_t *pathloc)
+void
+msdos_free_node_info(const rtems_filesystem_location_info_t *pathloc)
{
- int rc = RC_OK;
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
-
- sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
- MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
- if (sc != RTEMS_SUCCESSFUL)
- rtems_set_errno_and_return_minus_one(EIO);
-
- rc = fat_file_close(pathloc->mt_entry, pathloc->node_access);
-
- rtems_semaphore_release(fs_info->vol_sema);
- return rc;
+ fat_file_close(pathloc->mt_entry, pathloc->node_access);
}
diff --git a/cpukit/libfs/src/dosfs/msdos_fsunmount.c b/cpukit/libfs/src/dosfs/msdos_fsunmount.c
index 310da9c8ff..37b7730525 100644
--- a/cpukit/libfs/src/dosfs/msdos_fsunmount.c
+++ b/cpukit/libfs/src/dosfs/msdos_fsunmount.c
@@ -38,33 +38,19 @@
* PARAMETERS:
* temp_mt_entry - mount table entry
*
- * RETURNS:
- * RC_OK on success, or -1 if error occured (errno set apropriately).
- *
*/
-int
+void
msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry)
{
- int rc = RC_OK;
msdos_fs_info_t *fs_info = temp_mt_entry->fs_info;
- fat_file_fd_t *fat_fd = temp_mt_entry->mt_fs_root.node_access;
+ fat_file_fd_t *fat_fd = temp_mt_entry->mt_fs_root->location.node_access;
/* close fat-file which correspondes to root directory */
- if (fat_file_close(temp_mt_entry, fat_fd) != RC_OK)
- {
- /* no return - try to free as much as possible */
- rc = -1;
- }
+ fat_file_close(temp_mt_entry, fat_fd);
- if (fat_shutdown_drive(temp_mt_entry) != RC_OK)
- {
- /* no return - try to free as much as possible */
- rc = -1;
- }
+ fat_shutdown_drive(temp_mt_entry);
rtems_semaphore_delete(fs_info->vol_sema);
free(fs_info->cl_buf);
free(temp_mt_entry->fs_info);
-
- return rc;
}
diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_dir.c b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
index 933960a3e2..193d796dd9 100644
--- a/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
+++ b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
@@ -26,10 +26,8 @@ const rtems_filesystem_file_handlers_r msdos_dir_handlers = {
rtems_filesystem_default_ioctl,
msdos_dir_lseek,
msdos_dir_stat,
- msdos_dir_chmod,
- rtems_filesystem_default_ftruncate,
+ rtems_filesystem_default_ftruncate_directory,
msdos_dir_sync,
msdos_dir_sync,
- rtems_filesystem_default_fcntl,
- msdos_dir_rmnod
+ rtems_filesystem_default_fcntl
};
diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_file.c b/cpukit/libfs/src/dosfs/msdos_handlers_file.c
index 8990236303..fefb6795d9 100644
--- a/cpukit/libfs/src/dosfs/msdos_handlers_file.c
+++ b/cpukit/libfs/src/dosfs/msdos_handlers_file.c
@@ -23,13 +23,11 @@ const rtems_filesystem_file_handlers_r msdos_file_handlers = {
msdos_file_close,
msdos_file_read,
msdos_file_write,
- msdos_file_ioctl,
+ rtems_filesystem_default_ioctl,
msdos_file_lseek,
msdos_file_stat,
- msdos_file_chmod,
msdos_file_ftruncate,
msdos_file_sync,
msdos_file_datasync,
- rtems_filesystem_default_fcntl,
- msdos_file_rmnod
+ rtems_filesystem_default_fcntl
};
diff --git a/cpukit/libfs/src/dosfs/msdos_init.c b/cpukit/libfs/src/dosfs/msdos_init.c
index 217e0c1f3a..8941ec45dc 100644
--- a/cpukit/libfs/src/dosfs/msdos_init.c
+++ b/cpukit/libfs/src/dosfs/msdos_init.c
@@ -4,6 +4,9 @@
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -19,27 +22,59 @@
#include "dosfs.h"
#include "msdos.h"
+static int msdos_clone_node_info(rtems_filesystem_location_info_t *loc)
+{
+ fat_file_fd_t *fat_fd = loc->node_access;
+
+ return fat_file_reopen(fat_fd);
+}
+
const rtems_filesystem_operations_table msdos_ops = {
- .evalpath_h = msdos_eval_path,
- .evalformake_h = msdos_eval4make,
+ .lock_h = msdos_lock,
+ .unlock_h = msdos_unlock,
+ .eval_path_h = msdos_eval_path,
.link_h = rtems_filesystem_default_link,
- .unlink_h = msdos_file_rmnod,
+ .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
.node_type_h = msdos_node_type,
.mknod_h = msdos_mknod,
+ .rmnod_h = msdos_rmnod,
+ .fchmod_h = rtems_filesystem_default_fchmod,
.chown_h = rtems_filesystem_default_chown,
+ .clonenod_h = msdos_clone_node_info,
.freenod_h = msdos_free_node_info,
.mount_h = rtems_filesystem_default_mount,
.fsmount_me_h = rtems_dosfs_initialize,
.unmount_h = rtems_filesystem_default_unmount,
.fsunmount_me_h = msdos_shut_down,
.utime_h = rtems_filesystem_default_utime,
- .eval_link_h = rtems_filesystem_default_evaluate_link,
.symlink_h = rtems_filesystem_default_symlink,
.readlink_h = rtems_filesystem_default_readlink,
.rename_h = msdos_rename,
.statvfs_h = rtems_filesystem_default_statvfs
};
+void msdos_lock(rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ msdos_fs_info_t *fs_info = mt_entry->fs_info;
+ rtems_status_code sc = rtems_semaphore_obtain(
+ fs_info->vol_sema,
+ RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred(0xdeadbeef);
+ }
+}
+
+void msdos_unlock(rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ msdos_fs_info_t *fs_info = mt_entry->fs_info;
+ rtems_status_code sc = rtems_semaphore_release(fs_info->vol_sema);
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred(0xdeadbeef);
+ }
+}
+
/* msdos_initialize --
* MSDOS filesystem initialization. Called when mounting an
* MSDOS filesystem.
diff --git a/cpukit/libfs/src/dosfs/msdos_initsupp.c b/cpukit/libfs/src/dosfs/msdos_initsupp.c
index fc10fda71a..27905d08ca 100644
--- a/cpukit/libfs/src/dosfs/msdos_initsupp.c
+++ b/cpukit/libfs/src/dosfs/msdos_initsupp.c
@@ -141,9 +141,9 @@ msdos_initialize_support(
rtems_set_errno_and_return_minus_one( EIO );
}
- temp_mt_entry->mt_fs_root.node_access = fat_fd;
- temp_mt_entry->mt_fs_root.handlers = directory_handlers;
- temp_mt_entry->mt_fs_root.ops = op_table;
+ temp_mt_entry->mt_fs_root->location.node_access = fat_fd;
+ temp_mt_entry->mt_fs_root->location.handlers = directory_handlers;
+ temp_mt_entry->mt_fs_root->location.ops = op_table;
return rc;
}
diff --git a/cpukit/libfs/src/dosfs/msdos_misc.c b/cpukit/libfs/src/dosfs/msdos_misc.c
index f272d842a2..f27b4aea9c 100644
--- a/cpukit/libfs/src/dosfs/msdos_misc.c
+++ b/cpukit/libfs/src/dosfs/msdos_misc.c
@@ -257,89 +257,6 @@ msdos_long_to_short(const char *lfn, int lfn_len, char* sfn, int sfn_len)
return type;
}
-/* msdos_get_token --
- * Routine to get a token (name or separator) from the path.
- *
- * PARAMETERS:
- * path - path to get token from
- * ret_token - returned token
- * token_len - length of returned token
- *
- * RETURNS:
- * token type, token and token length
- *
- */
-msdos_token_types_t
-msdos_get_token(const char *path,
- int pathlen,
- const char **ret_token,
- int *ret_token_len)
-{
- msdos_token_types_t type = MSDOS_NAME;
- int i = 0;
-
- *ret_token = NULL;
- *ret_token_len = 0;
-
- if (pathlen == 0)
- return MSDOS_NO_MORE_PATH;
-
- /*
- * Check for a separator.
- */
- while (!msdos_is_separator(path[i]) && (i < pathlen))
- {
- if ( !msdos_is_valid_name_char(path[i]) )
- return MSDOS_INVALID_TOKEN;
- ++i;
- if ( i == MSDOS_NAME_MAX_LFN_WITH_DOT )
- return MSDOS_INVALID_TOKEN;
- }
-
- *ret_token = path;
-
- /*
- * If it is just a separator then it is the current dir.
- */
- if ( i == 0 )
- {
- if ( (*path != '\0') && pathlen )
- {
- i++;
- type = MSDOS_CURRENT_DIR;
- }
- else
- type = MSDOS_NO_MORE_PATH;
- }
-
- /*
- * Set the token and token_len to the token start and length.
- */
- *ret_token_len = i;
-
- /*
- * If we copied something that was not a seperator see if
- * it was a special name.
- */
- if ( type == MSDOS_NAME )
- {
- if ((i == 2) && ((*ret_token)[0] == '.') && ((*ret_token)[1] == '.'))
- {
- type = MSDOS_UP_DIR;
- return type;
- }
-
- if ((i == 1) && ((*ret_token)[0] == '.'))
- {
- type = MSDOS_CURRENT_DIR;
- return type;
- }
- }
-
- return type;
-}
-
-
/* msdos_find_name --
* Find the node which correspondes to the name, open fat-file which
* correspondes to the found node and close fat-file which correspondes
@@ -491,13 +408,13 @@ msdos_find_name(
*/
int
msdos_get_name_node(
- rtems_filesystem_location_info_t *parent_loc,
- bool create_node,
- const char *name,
- int name_len,
- msdos_name_type_t name_type,
- fat_dir_pos_t *dir_pos,
- char *name_dir_entry
+ const rtems_filesystem_location_info_t *parent_loc,
+ bool create_node,
+ const char *name,
+ int name_len,
+ msdos_name_type_t name_type,
+ fat_dir_pos_t *dir_pos,
+ char *name_dir_entry
)
{
int rc = RC_OK;
diff --git a/cpukit/libfs/src/dosfs/msdos_mknod.c b/cpukit/libfs/src/dosfs/msdos_mknod.c
index ad4ad50d00..195addaf9f 100644
--- a/cpukit/libfs/src/dosfs/msdos_mknod.c
+++ b/cpukit/libfs/src/dosfs/msdos_mknod.c
@@ -31,31 +31,16 @@
#include "msdos.h"
-/* msdos_mknod --
- * The following function checks spelling and formats name for a new node,
- * determines type of the node to be created and creates it.
- *
- * PARAMETERS:
- * name - file name to create
- * mode - node type
- * dev - dev
- * pathloc - parent directory description
- *
- * RETURNS:
- * RC_OK on succes, or -1 if error occured and set errno
- *
- */
int msdos_mknod(
- const char *name,
- mode_t mode,
- dev_t dev,
- rtems_filesystem_location_info_t *pathloc
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
)
{
int rc = RC_OK;
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
- msdos_token_types_t type = 0;
+ msdos_node_type_t type = 0;
/*
* Figure out what type of msdos node this is.
@@ -71,14 +56,8 @@ int msdos_mknod(
else
rtems_set_errno_and_return_minus_one(EINVAL);
- sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
- MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
- if (sc != RTEMS_SUCCESSFUL)
- rtems_set_errno_and_return_minus_one(EIO);
-
/* Create an MSDOS node */
- rc = msdos_creat_node(pathloc, type, name, strlen(name), mode, NULL);
+ rc = msdos_creat_node(parentloc, type, name, namelen, mode, NULL);
- rtems_semaphore_release(fs_info->vol_sema);
return rc;
}
diff --git a/cpukit/libfs/src/dosfs/msdos_node_type.c b/cpukit/libfs/src/dosfs/msdos_node_type.c
index 877cf60492..be6fb9f57e 100644
--- a/cpukit/libfs/src/dosfs/msdos_node_type.c
+++ b/cpukit/libfs/src/dosfs/msdos_node_type.c
@@ -32,17 +32,17 @@
#include "msdos.h"
/* msdos_node_type --
- * Determine type of the node that the pathloc refers to.
+ * Determine type of the node that the loc refers to.
*
* PARAMETERS:
- * pathloc - node description
+ * loc - node description
*
* RETURNS:
* node type
*
*/
rtems_filesystem_node_types_t
-msdos_node_type(rtems_filesystem_location_info_t *pathloc)
+msdos_node_type(const rtems_filesystem_location_info_t *loc)
{
fat_file_fd_t *fat_fd;
@@ -52,7 +52,7 @@ msdos_node_type(rtems_filesystem_location_info_t *pathloc)
* hence node_access memory can't be freed during processing node_type_h
* call
*/
- fat_fd = pathloc->node_access;
+ fat_fd = loc->node_access;
return fat_fd->fat_file_type;
}
diff --git a/cpukit/libfs/src/dosfs/msdos_rename.c b/cpukit/libfs/src/dosfs/msdos_rename.c
index 1d285bd01d..8490d58370 100644
--- a/cpukit/libfs/src/dosfs/msdos_rename.c
+++ b/cpukit/libfs/src/dosfs/msdos_rename.c
@@ -30,53 +30,28 @@
/* msdos_rename --
* Rename the node by removing the exitsing directory entry and creating a
* new one.
- *
- * PARAMETERS:
- * old_parent_loc - node description for the "old parent" node
- * old_loc - node description for the "old" node
- * new_parent_loc - node description for the "parent" node
- * name - name of new node
- *
- * RETURNS:
- * RC_OK on success, or -1 if error occured (errno set appropriately)
*/
int
-msdos_rename(rtems_filesystem_location_info_t *old_parent_loc,
- rtems_filesystem_location_info_t *old_loc,
- rtems_filesystem_location_info_t *new_parent_loc,
- const char *new_name)
+msdos_rename(
+ const rtems_filesystem_location_info_t *old_parent_loc,
+ const rtems_filesystem_location_info_t *old_loc,
+ const rtems_filesystem_location_info_t *new_parent_loc,
+ const char *new_name,
+ size_t new_namelen
+)
{
int rc = RC_OK;
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- msdos_fs_info_t *fs_info = new_parent_loc->mt_entry->fs_info;
fat_file_fd_t *old_fat_fd = old_loc->node_access;
- const char *token;
- int len;
-
- /*
- * check spelling and format new node name
- */
- if (MSDOS_NAME != msdos_get_token(new_name, strlen(new_name), &token, &len)) {
- rtems_set_errno_and_return_minus_one(ENAMETOOLONG);
- }
- /*
- * lock volume
- */
- sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
- MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
- if (sc != RTEMS_SUCCESSFUL)
- rtems_set_errno_and_return_minus_one(EIO);
/*
* create new directory entry as "hard link", copying relevant info from
* existing file
*/
rc = msdos_creat_node(new_parent_loc,
- MSDOS_HARD_LINK,new_name,len,S_IFREG,
+ MSDOS_HARD_LINK,new_name,new_namelen,S_IFREG,
old_fat_fd);
if (rc != RC_OK)
{
- rtems_semaphore_release(fs_info->vol_sema);
return rc;
}
@@ -87,6 +62,5 @@ msdos_rename(rtems_filesystem_location_info_t *old_parent_loc,
&old_fat_fd->dir_pos,
MSDOS_THIS_DIR_ENTRY_EMPTY);
- rtems_semaphore_release(fs_info->vol_sema);
return rc;
}
diff --git a/cpukit/libfs/src/dosfs/msdos_rmnod.c b/cpukit/libfs/src/dosfs/msdos_rmnod.c
new file mode 100644
index 0000000000..56431b2133
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_rmnod.c
@@ -0,0 +1,79 @@
+/*
+ * MSDOS directory handlers implementation
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "msdos.h"
+
+int
+msdos_rmnod(const rtems_filesystem_location_info_t *parent_pathloc,
+ const rtems_filesystem_location_info_t *pathloc)
+{
+ int rc = RC_OK;
+ fat_file_fd_t *fat_fd = pathloc->node_access;
+
+ if (fat_fd->fat_file_type == MSDOS_DIRECTORY)
+ {
+ bool is_empty = false;
+
+ /*
+ * You cannot remove a node that still has children
+ */
+ rc = msdos_dir_is_empty(pathloc->mt_entry, fat_fd, &is_empty);
+ if (rc != RC_OK)
+ {
+ return rc;
+ }
+
+ if (!is_empty)
+ {
+ rtems_set_errno_and_return_minus_one(ENOTEMPTY);
+ }
+
+ /*
+ * We deny attempts to delete open directory (if directory is current
+ * directory we assume it is open one)
+ */
+ if (fat_fd->links_num > 1)
+ {
+ rtems_set_errno_and_return_minus_one(EBUSY);
+ }
+
+ /*
+ * You cannot remove the file system root node.
+ */
+ if (rtems_filesystem_location_is_root(pathloc))
+ {
+ rtems_set_errno_and_return_minus_one(EBUSY);
+ }
+
+ /*
+ * You cannot remove a mountpoint.
+ * not used - mount() not implemenetd yet.
+ */
+ }
+
+ /* mark file removed */
+ rc = msdos_set_first_char4file_name(pathloc->mt_entry, &fat_fd->dir_pos,
+ MSDOS_THIS_DIR_ENTRY_EMPTY);
+ if (rc != RC_OK)
+ {
+ return rc;
+ }
+
+ fat_file_mark_removed(pathloc->mt_entry, fat_fd);
+
+ return rc;
+}
diff --git a/cpukit/libfs/src/imfs/deviceio.c b/cpukit/libfs/src/imfs/deviceio.c
index bb66703be9..69f409e472 100644
--- a/cpukit/libfs/src/imfs/deviceio.c
+++ b/cpukit/libfs/src/imfs/deviceio.c
@@ -15,15 +15,13 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <rtems.h>
-#include <rtems/libio.h>
-#include <rtems/devfs.h>
-
#include "imfs.h"
+#include <rtems/devfs.h>
+
/*
* device_open
*
@@ -33,8 +31,8 @@
int device_open(
rtems_libio_t *iop,
const char *pathname,
- uint32_t flag,
- uint32_t mode
+ int oflag,
+ mode_t mode
)
{
rtems_libio_open_close_args_t args;
diff --git a/cpukit/libfs/src/imfs/fifoimfs_init.c b/cpukit/libfs/src/imfs/fifoimfs_init.c
index 13dc373eec..d2af7af8e5 100644
--- a/cpukit/libfs/src/imfs/fifoimfs_init.c
+++ b/cpukit/libfs/src/imfs/fifoimfs_init.c
@@ -20,26 +20,29 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
#include "imfs.h"
const rtems_filesystem_operations_table fifoIMFS_ops = {
- .evalpath_h = IMFS_eval_path,
- .evalformake_h = IMFS_evaluate_for_make,
+ .lock_h = rtems_filesystem_default_lock,
+ .unlock_h = rtems_filesystem_default_unlock,
+ .eval_path_h = IMFS_eval_path,
.link_h = IMFS_link,
- .unlink_h = IMFS_unlink,
+ .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
.node_type_h = IMFS_node_type,
.mknod_h = IMFS_mknod,
+ .rmnod_h = IMFS_rmnod,
+ .fchmod_h = IMFS_fchmod,
.chown_h = IMFS_chown,
+ .clonenod_h = rtems_filesystem_default_clonenode,
.freenod_h = rtems_filesystem_default_freenode,
.mount_h = IMFS_mount,
.fsmount_me_h = fifoIMFS_initialize,
.unmount_h = IMFS_unmount,
.fsunmount_me_h = IMFS_fsunmount,
.utime_h = IMFS_utime,
- .eval_link_h = IMFS_evaluate_link,
.symlink_h = IMFS_symlink,
.readlink_h = IMFS_readlink,
.rename_h = IMFS_rename,
@@ -54,8 +57,7 @@ int fifoIMFS_initialize(
return IMFS_initialize_support(
mt_entry,
&fifoIMFS_ops,
- &IMFS_memfile_handlers,
- &IMFS_directory_handlers,
+ &IMFS_link_handlers,
&IMFS_fifo_handlers
);
}
diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h
index b412c2a1fe..2a851acae4 100644
--- a/cpukit/libfs/src/imfs/imfs.h
+++ b/cpukit/libfs/src/imfs/imfs.h
@@ -18,13 +18,9 @@
#ifndef _RTEMS_IMFS_H
#define _RTEMS_IMFS_H
-#include <rtems.h>
-#include <rtems/chain.h>
-
-#include <sys/types.h>
#include <limits.h>
-#include <rtems/libio.h>
+#include <rtems/libio_.h>
#include <rtems/pipe.h>
#ifdef __cplusplus
@@ -32,15 +28,6 @@ extern "C" {
#endif
/*
- * File name macros
- */
-
-#define IMFS_is_valid_name_char( _ch ) ( 1 )
-
-#define IMFS_is_separator( _ch ) \
- rtems_filesystem_is_separator( _ch )
-
-/*
* Data types
*/
@@ -226,22 +213,11 @@ typedef struct {
ino_t ino_count;
const rtems_filesystem_file_handlers_r *memfile_handlers;
const rtems_filesystem_file_handlers_r *directory_handlers;
+ const rtems_filesystem_file_handlers_r *link_handlers;
const rtems_filesystem_file_handlers_r *fifo_handlers;
} IMFS_fs_info_t;
/*
- * Type defination for tokens returned from IMFS_get_token
- */
-
-typedef enum {
- IMFS_NO_MORE_PATH,
- IMFS_CURRENT_DIR,
- IMFS_UP_DIR,
- IMFS_NAME,
- IMFS_INVALID_TOKEN
-} IMFS_token_types;
-
-/*
* Shared Data
*/
@@ -276,29 +252,18 @@ extern int miniIMFS_initialize(
extern int IMFS_initialize_support(
rtems_filesystem_mount_table_entry_t *mt_entry,
const rtems_filesystem_operations_table *op_table,
- const rtems_filesystem_file_handlers_r *memfile_handlers,
- const rtems_filesystem_file_handlers_r *directory_handlers,
+ const rtems_filesystem_file_handlers_r *link_handlers,
const rtems_filesystem_file_handlers_r *fifo_handlers
);
-extern int IMFS_fsunmount(
+extern void IMFS_fsunmount(
rtems_filesystem_mount_table_entry_t *mt_entry
);
extern int rtems_tarfs_load(
- char *mountpoint,
- uint8_t *tar_image,
- size_t tar_size
-);
-
-/*
- * Returns the number of characters copied from path to token.
- */
-extern IMFS_token_types IMFS_get_token(
- const char *path,
- int pathlen,
- char *token,
- int *token_len
+ const char *mountpoint,
+ uint8_t *tar_image,
+ size_t tar_size
);
extern void IMFS_dump( void );
@@ -309,88 +274,59 @@ extern void IMFS_dump( void );
*/
extern int IMFS_memfile_maximum_size( void );
-extern void IMFS_initialize_jnode(
- IMFS_jnode_t *the_jnode,
- IMFS_jnode_types_t type,
- IMFS_jnode_t *the_parent,
- char *name,
- mode_t mode
-);
-
-extern IMFS_jnode_t *IMFS_find_match_in_dir(
- IMFS_jnode_t *directory, /* IN */
- char *name /* IN */
-);
extern rtems_filesystem_node_types_t IMFS_node_type(
- rtems_filesystem_location_info_t *pathloc /* IN */
+ const rtems_filesystem_location_info_t *loc
);
extern int IMFS_stat(
- rtems_filesystem_location_info_t *loc, /* IN */
- struct stat *buf /* OUT */
-);
-
-extern int IMFS_Set_handlers(
- rtems_filesystem_location_info_t *loc
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *buf
);
-extern int IMFS_evaluate_link(
- rtems_filesystem_location_info_t *node, /* IN/OUT */
- int flags /* IN */
-);
+extern void IMFS_Set_handlers( rtems_filesystem_location_info_t *loc );
-extern int IMFS_eval_path(
- const char *pathname, /* IN */
- size_t pathnamelen, /* IN */
- int flags, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+extern void IMFS_eval_path(
+ rtems_filesystem_eval_path_context_t *ctx
);
extern int IMFS_link(
- rtems_filesystem_location_info_t *to_loc, /* IN */
- rtems_filesystem_location_info_t *parent_loc, /* IN */
- const char *token /* IN */
-);
-
-extern int IMFS_unlink(
- rtems_filesystem_location_info_t *parent_pathloc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *targetloc,
+ const char *name,
+ size_t namelen
);
extern int IMFS_chown(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- uid_t owner, /* IN */
- gid_t group /* IN */
+ const rtems_filesystem_location_info_t *loc,
+ uid_t owner,
+ gid_t group
);
extern int IMFS_mknod(
- const char *path, /* IN */
- mode_t mode, /* IN */
- dev_t dev, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
);
extern IMFS_jnode_t *IMFS_allocate_node(
IMFS_jnode_types_t type, /* IN */
const char *name, /* IN */
+ size_t namelen, /* IN */
mode_t mode /* IN */
);
extern IMFS_jnode_t *IMFS_create_root_node(void);
extern IMFS_jnode_t *IMFS_create_node(
- rtems_filesystem_location_info_t *parent_loc, /* IN */
- IMFS_jnode_types_t type, /* IN */
- const char *name, /* IN */
- mode_t mode, /* IN */
- const IMFS_types_union *info /* IN */
-);
-
-extern int IMFS_evaluate_for_make(
- const char *path, /* IN */
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- const char **name /* OUT */
+ const rtems_filesystem_location_info_t *pathloc, /* IN */
+ IMFS_jnode_types_t type, /* IN */
+ const char *name, /* IN */
+ size_t namelen, /* IN */
+ mode_t mode, /* IN */
+ const IMFS_types_union *info /* IN */
);
extern int IMFS_mount(
@@ -413,8 +349,8 @@ extern int memfile_ftruncate(
extern int imfs_dir_open(
rtems_libio_t *iop, /* IN */
const char *pathname, /* IN */
- uint32_t flag, /* IN */
- uint32_t mode /* IN */
+ int oflag, /* IN */
+ mode_t mode /* IN */
);
extern int imfs_dir_close(
@@ -433,21 +369,11 @@ extern off_t imfs_dir_lseek(
int whence /* IN */
);
-extern int imfs_dir_fstat(
- rtems_filesystem_location_info_t *loc, /* IN */
- struct stat *buf /* OUT */
-);
-
-extern int imfs_dir_rmnod(
- rtems_filesystem_location_info_t *parent_pathloc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */
-);
-
extern int memfile_open(
rtems_libio_t *iop, /* IN */
const char *pathname, /* IN */
- uint32_t flag, /* IN */
- uint32_t mode /* IN */
+ int oflag, /* IN */
+ mode_t mode /* IN */
);
extern int memfile_close(
@@ -481,8 +407,8 @@ extern off_t memfile_lseek(
extern int device_open(
rtems_libio_t *iop, /* IN */
const char *pathname, /* IN */
- uint32_t flag, /* IN */
- uint32_t mode /* IN */
+ int oflag, /* IN */
+ mode_t mode /* IN */
);
extern int device_close(
@@ -519,33 +445,35 @@ extern int device_ftruncate(
);
extern int IMFS_utime(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- time_t actime, /* IN */
- time_t modtime /* IN */
+ const rtems_filesystem_location_info_t *loc,
+ time_t actime,
+ time_t modtime
);
extern int IMFS_fchmod(
- rtems_filesystem_location_info_t *loc,
- mode_t mode
+ const rtems_filesystem_location_info_t *loc,
+ mode_t mode
);
extern int IMFS_symlink(
- rtems_filesystem_location_info_t *parent_loc, /* IN */
- const char *link_name,
- const char *node_name
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ const char *target
);
extern ssize_t IMFS_readlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- char *buf, /* OUT */
- size_t bufsize
+ const rtems_filesystem_location_info_t *loc,
+ char *buf,
+ size_t bufsize
);
extern int IMFS_rename(
- rtems_filesystem_location_info_t *old_loc, /* IN */
- rtems_filesystem_location_info_t *old_parent_loc, /* IN */
- rtems_filesystem_location_info_t *new_parent_loc, /* IN */
- const char *new_name /* IN */
+ const rtems_filesystem_location_info_t *oldparentloc,
+ const rtems_filesystem_location_info_t *oldloc,
+ const rtems_filesystem_location_info_t *newparentloc,
+ const char *name,
+ size_t namelen
);
extern int IMFS_fdatasync(
@@ -561,8 +489,8 @@ extern void IMFS_check_node_remove(
);
extern int IMFS_rmnod(
- rtems_filesystem_location_info_t *parent_pathloc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *loc
);
/*
diff --git a/cpukit/libfs/src/imfs/imfs_chown.c b/cpukit/libfs/src/imfs/imfs_chown.c
index 7f0c7b5688..e31b89e0b0 100644
--- a/cpukit/libfs/src/imfs/imfs_chown.c
+++ b/cpukit/libfs/src/imfs/imfs_chown.c
@@ -15,18 +15,19 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
#include "imfs.h"
+#include <unistd.h>
+
+#include <rtems/libio_.h>
+
int IMFS_chown(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- uid_t owner, /* IN */
- gid_t group /* IN */
+ const rtems_filesystem_location_info_t *loc,
+ uid_t owner,
+ gid_t group
)
{
IMFS_jnode_t *jnode;
@@ -34,7 +35,7 @@ int IMFS_chown(
uid_t st_uid;
#endif
- jnode = (IMFS_jnode_t *) pathloc->node_access;
+ jnode = (IMFS_jnode_t *) loc->node_access;
/*
* Verify I am the owner of the node or the super user.
diff --git a/cpukit/libfs/src/imfs/imfs_creat.c b/cpukit/libfs/src/imfs/imfs_creat.c
index 3b602d0c14..37e3ac0578 100644
--- a/cpukit/libfs/src/imfs/imfs_creat.c
+++ b/cpukit/libfs/src/imfs/imfs_creat.c
@@ -14,35 +14,32 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
+#include "imfs.h"
+
#include <stdlib.h>
#include <string.h>
-#include "imfs.h"
-#include <rtems/libio_.h>
/*
* Create an IMFS filesystem node of an arbitrary type that is NOT
* the root directory node.
*/
IMFS_jnode_t *IMFS_create_node(
- rtems_filesystem_location_info_t *parent_loc,
- IMFS_jnode_types_t type,
- const char *name,
- mode_t mode,
- const IMFS_types_union *info
+ const rtems_filesystem_location_info_t *parent_loc,
+ IMFS_jnode_types_t type,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ const IMFS_types_union *info
)
{
IMFS_jnode_t *node;
IMFS_jnode_t *parent;
IMFS_fs_info_t *fs_info;
- /*
- * MUST have a parent node to call this routine.
- */
- if ( parent_loc == NULL )
- return NULL;
+ IMFS_assert( parent_loc != NULL );
parent = parent_loc->node_access;
fs_info = parent_loc->mt_entry->fs_info;
@@ -51,13 +48,16 @@ IMFS_jnode_t *IMFS_create_node(
* Reject creation of FIFOs if support is disabled.
*/
if ( type == IMFS_FIFO &&
- fs_info->fifo_handlers == &rtems_filesystem_handlers_default )
+ fs_info->fifo_handlers == &rtems_filesystem_handlers_default ) {
+ errno = ENOTSUP;
+
return NULL;
+ }
/*
* Allocate filesystem node and fill in basic information
*/
- node = IMFS_allocate_node( type, name, mode & ~rtems_filesystem_umask );
+ node = IMFS_allocate_node( type, name, namelen, mode );
if ( !node )
return NULL;
@@ -104,25 +104,36 @@ IMFS_jnode_t *IMFS_create_node(
IMFS_jnode_t *IMFS_allocate_node(
IMFS_jnode_types_t type,
const char *name,
+ size_t namelen,
mode_t mode
)
{
IMFS_jnode_t *node;
struct timeval tv;
+ if ( namelen > IMFS_NAME_MAX ) {
+ errno = ENAMETOOLONG;
+
+ return NULL;
+ }
+
/*
* Allocate an IMFS jnode
*/
node = calloc( 1, sizeof( IMFS_jnode_t ) );
- if ( !node )
+ if ( !node ) {
+ errno = ENOMEM;
+
return NULL;
+ }
/*
* Fill in the basic information
*/
node->st_nlink = 1;
node->type = type;
- strncpy( node->name, name, IMFS_NAME_MAX );
+ memcpy( node->name, name, namelen );
+ node->name [namelen] = '\0';
/*
* Fill in the mode and permission information for the jnode structure.
@@ -155,7 +166,7 @@ IMFS_jnode_t *IMFS_create_root_node(void)
/*
* Allocate filesystem node and fill in basic information
*/
- node = IMFS_allocate_node( IMFS_DIRECTORY, "", (S_IFDIR | 0755) );
+ node = IMFS_allocate_node( IMFS_DIRECTORY, "", 0, (S_IFDIR | 0755) );
if ( !node )
return NULL;
diff --git a/cpukit/libfs/src/imfs/imfs_debug.c b/cpukit/libfs/src/imfs/imfs_debug.c
index f8bdf1ce41..091237275d 100644
--- a/cpukit/libfs/src/imfs/imfs_debug.c
+++ b/cpukit/libfs/src/imfs/imfs_debug.c
@@ -12,21 +12,14 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h> /* for close */
-#include <inttypes.h>
+#include "imfs.h"
+#include <inttypes.h>
+#include <unistd.h>
#include <stdio.h>
-#include <sys/stat.h>
-
-#include "imfs.h"
-#include <rtems/libio_.h>
/*
* IMFS_print_jnode
@@ -142,7 +135,7 @@ void IMFS_dump( void )
{
fprintf(stdout, "*************** Dump of Entire IMFS ***************\n" );
fprintf(stdout, "/\n" );
- IMFS_dump_directory( rtems_filesystem_root.node_access, 0 );
+ IMFS_dump_directory( rtems_filesystem_root->location.node_access, 0 );
fprintf(stdout, "*************** End of Dump ***************\n" );
}
diff --git a/cpukit/libfs/src/imfs/imfs_directory.c b/cpukit/libfs/src/imfs/imfs_directory.c
index 7e0c125104..8ef05b4d1d 100644
--- a/cpukit/libfs/src/imfs/imfs_directory.c
+++ b/cpukit/libfs/src/imfs/imfs_directory.c
@@ -12,23 +12,14 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <rtems/chain.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
+#include "imfs.h"
+
#include <string.h>
#include <dirent.h>
-#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-
/*
* imfs_dir_open
*
@@ -40,8 +31,8 @@
int imfs_dir_open(
rtems_libio_t *iop,
const char *pathname,
- uint32_t flag,
- uint32_t mode
+ int oflag,
+ mode_t mode
)
{
IMFS_jnode_t *the_jnode;
@@ -203,115 +194,3 @@ off_t imfs_dir_lseek(
return 0;
}
-
-
-
-/*
- * imfs_dir_fstat
- *
- * This routine will obtain the following information concerning the current
- * directory:
- * st_dev 0ll
- * st_ino 1
- * st_mode mode extracted from the jnode
- * st_nlink number of links to this node
- * st_uid uid extracted from the jnode
- * st_gid gid extracted from the jnode
- * st_rdev 0ll
- * st_size the number of bytes in the directory
- * This is calculated by taking the number of entries
- * in the directory and multiplying by the size of a
- * dirent structure
- * st_blksize 0
- * st_blocks 0
- * stat_atime time of last access
- * stat_mtime time of last modification
- * stat_ctime time of the last change
- *
- * This information will be returned to the calling function in a -stat- struct
- *
- */
-
-int imfs_dir_fstat(
- rtems_filesystem_location_info_t *loc,
- struct stat *buf
-)
-{
- rtems_chain_node *the_node;
- rtems_chain_control *the_chain;
- IMFS_jnode_t *the_jnode;
-
-
- the_jnode = (IMFS_jnode_t *) loc->node_access;
-
- buf->st_dev = 0ll;
- buf->st_ino = the_jnode->st_ino;
- buf->st_mode = the_jnode->st_mode;
- buf->st_nlink = the_jnode->st_nlink;
- buf->st_uid = the_jnode->st_uid;
- buf->st_gid = the_jnode->st_gid;
- buf->st_rdev = 0ll;
- buf->st_blksize = 0;
- buf->st_blocks = 0;
- buf->st_atime = the_jnode->stat_atime;
- buf->st_mtime = the_jnode->stat_mtime;
- buf->st_ctime = the_jnode->stat_ctime;
-
- buf->st_size = 0;
-
- the_chain = &the_jnode->info.directory.Entries;
-
- /* Run through the chain and count the number of directory entries */
- /* that are subordinate to this directory node */
- for ( the_node = rtems_chain_first( the_chain );
- !rtems_chain_is_tail( the_chain, the_node ) ;
- the_node = the_node->next ) {
-
- buf->st_size = buf->st_size + sizeof( struct dirent );
- }
-
- return 0;
-}
-
-/*
- * IMFS_dir_rmnod
- *
- * This routine is available from the optable to remove a node
- * from the IMFS file system.
- */
-
-int imfs_dir_rmnod(
- rtems_filesystem_location_info_t *parent_pathloc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */
-)
-{
- IMFS_jnode_t *the_jnode;
-
- the_jnode = (IMFS_jnode_t *) pathloc->node_access;
-
- /*
- * You cannot remove a node that still has children
- */
-
- if ( ! rtems_chain_is_empty( &the_jnode->info.directory.Entries ) )
- rtems_set_errno_and_return_minus_one( ENOTEMPTY );
-
- /*
- * You cannot remove the file system root node.
- */
-
- if ( rtems_filesystem_is_root_location(pathloc) )
- rtems_set_errno_and_return_minus_one( EBUSY );
-
- /*
- * You cannot remove a mountpoint.
- */
-
- if ( the_jnode->info.directory.mt_fs != NULL )
- rtems_set_errno_and_return_minus_one( EBUSY );
-
- IMFS_create_orphan( the_jnode );
- IMFS_check_node_remove( the_jnode );
-
- return 0;
-}
diff --git a/cpukit/libfs/src/imfs/imfs_eval.c b/cpukit/libfs/src/imfs/imfs_eval.c
index 78fafca536..43f2ee40e0 100644
--- a/cpukit/libfs/src/imfs/imfs_eval.c
+++ b/cpukit/libfs/src/imfs/imfs_eval.c
@@ -4,684 +4,189 @@
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
- *
- * $Id$
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-
#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
-#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
-
-#define MAXSYMLINK 5
-
-int IMFS_Set_handlers(
- rtems_filesystem_location_info_t *loc
-)
+void IMFS_Set_handlers( rtems_filesystem_location_info_t *loc )
{
- IMFS_jnode_t *node = loc->node_access;
- IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *node = loc->node_access;
+ IMFS_fs_info_t *fs_info = loc->mt_entry->fs_info;
+ const rtems_filesystem_file_handlers_r *handlers;
- fs_info = loc->mt_entry->fs_info;
- switch( node->type ) {
+ switch ( node->type ) {
case IMFS_DIRECTORY:
- loc->handlers = fs_info->directory_handlers;
+ handlers = &IMFS_directory_handlers;
break;
case IMFS_DEVICE:
- loc->handlers = &IMFS_device_handlers;
+ handlers = &IMFS_device_handlers;
break;
- case IMFS_SYM_LINK:
case IMFS_HARD_LINK:
- loc->handlers = &IMFS_link_handlers;
- break;
- case IMFS_LINEAR_FILE:
- loc->handlers = fs_info->memfile_handlers;
+ case IMFS_SYM_LINK:
+ handlers = fs_info->link_handlers;
break;
case IMFS_MEMORY_FILE:
- loc->handlers = fs_info->memfile_handlers;
+ case IMFS_LINEAR_FILE:
+ handlers = &IMFS_memfile_handlers;
break;
case IMFS_FIFO:
- loc->handlers = fs_info->fifo_handlers;
+ handlers = fs_info->fifo_handlers;
+ break;
+ default:
+ IMFS_assert( 0 );
break;
}
- return 0;
-}
-
-/*
- * IMFS_evaluate_permission
- *
- * The following routine evaluates that we have permission
- * to do flags on the node.
- */
-static int IMFS_evaluate_permission(
- rtems_filesystem_location_info_t *node,
- int flags
-)
-{
- uid_t st_uid;
- gid_t st_gid;
- IMFS_jnode_t *jnode;
- int flags_to_test;
-
- if ( !rtems_libio_is_valid_perms( flags ) )
- rtems_set_errno_and_return_minus_one( EPERM );
-
- jnode = node->node_access;
-
-#if defined(RTEMS_POSIX_API)
- st_uid = geteuid();
- st_gid = getegid();
-#else
- st_uid = jnode->st_uid;
- st_gid = jnode->st_gid;
-#endif
-
- /*
- * Check if I am owner or a group member or someone else.
- */
-
- flags_to_test = flags;
-
- if ( st_uid == jnode->st_uid )
- flags_to_test <<= 6;
- else if ( st_gid == jnode->st_gid )
- flags_to_test <<= 3;
- else {
- /* must be other - do nothing */;
- }
-
- /*
- * If all of the flags are set we have permission
- * to do this.
- */
- if ( ( flags_to_test & jnode->st_mode) == flags_to_test )
- return 1;
-
- return 0;
+ loc->handlers = handlers;
}
-/*
- * IMFS_evaluate_hard_link
- *
- * The following routine evaluates a hardlink to the actual node.
- */
-
-static int IMFS_evaluate_hard_link(
- rtems_filesystem_location_info_t *node, /* IN/OUT */
- int flags /* IN */
+static bool IMFS_is_directory(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg
)
{
- IMFS_jnode_t *jnode = node->node_access;
- int result = 0;
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc( ctx );
+ IMFS_jnode_t *node = currentloc->node_access;
- /*
- * Check for things that should never happen.
- */
- IMFS_assert( jnode->type == IMFS_HARD_LINK );
-
- /*
- * Set the hard link value and the handlers.
- */
- node->node_access = jnode->info.hard_link.link_node;
-
- IMFS_Set_handlers( node );
-
- /*
- * Verify we have the correct permissions for this node.
- */
-
- if ( !IMFS_evaluate_permission( node, flags ) )
- rtems_set_errno_and_return_minus_one( EACCES );
-
- return result;
+ return node->type == IMFS_DIRECTORY;
}
-
-/*
- * IMFS_evaluate_sym_link
- *
- * The following routine evaluates a symbolic link to the actual node.
- */
-
-static int IMFS_evaluate_sym_link(
- rtems_filesystem_location_info_t *node, /* IN/OUT */
- int flags /* IN */
+static IMFS_jnode_t *IMFS_search_in_directory(
+ IMFS_jnode_t *dir,
+ const char *token,
+ size_t tokenlen
)
{
- IMFS_jnode_t *jnode = node->node_access;
- int result = 0;
- int i;
-
- /*
- * Check for things that should never happen.
- */
- IMFS_assert( jnode->type == IMFS_SYM_LINK );
- IMFS_assert( jnode->Parent );
-
- /*
- * Move the node_access to either the symbolic links parent or
- * root depending on the symbolic links path.
- */
- node->node_access = jnode->Parent;
-
- rtems_filesystem_get_sym_start_loc(
- jnode->info.sym_link.name,
- &i,
- node
- );
-
- /*
- * Use eval path to evaluate the path of the symbolic link.
- */
- result = IMFS_eval_path(
- &jnode->info.sym_link.name[i],
- strlen( &jnode->info.sym_link.name[i] ),
- flags,
- node
- );
-
- IMFS_Set_handlers( node );
-
- /*
- * Verify we have the correct permissions for this node.
- */
- if ( !IMFS_evaluate_permission( node, flags ) )
- rtems_set_errno_and_return_minus_one( EACCES );
-
- return result;
-}
+ if ( rtems_filesystem_is_current_directory( token, tokenlen ) ) {
+ return dir;
+ } else {
+ if ( rtems_filesystem_is_parent_directory( token, tokenlen ) ) {
+ return dir->Parent;
+ } else {
+ rtems_chain_control *entries = &dir->info.directory.Entries;
+ rtems_chain_node *current = rtems_chain_first( entries );
+ rtems_chain_node *tail = rtems_chain_tail( entries );
-/*
- * IMFS_evaluate_link
- *
- * The following routine returns the real node pointed to by a link.
- */
-int IMFS_evaluate_link(
- rtems_filesystem_location_info_t *node, /* IN/OUT */
- int flags /* IN */
-)
-{
- IMFS_jnode_t *jnode;
- int result = 0;
+ while ( current != tail ) {
+ IMFS_jnode_t *entry = (IMFS_jnode_t *) current;
+ bool match = strncmp( entry->name, token, tokenlen ) == 0
+ && entry->name [tokenlen] == '\0';
- do {
- jnode = node->node_access;
+ if ( match ) {
+ return entry;
+ }
- /*
- * Increment and check the link counter.
- */
+ current = rtems_chain_next( current );
+ }
- rtems_filesystem_link_counts ++;
- if ( rtems_filesystem_link_counts > MAXSYMLINK ) {
- rtems_filesystem_link_counts = 0;
- rtems_set_errno_and_return_minus_one( ELOOP );
+ return NULL;
}
-
- /*
- * Follow the Link node.
- */
-
- if ( jnode->type == IMFS_HARD_LINK )
- result = IMFS_evaluate_hard_link( node, flags );
-
- else if (jnode->type == IMFS_SYM_LINK )
- result = IMFS_evaluate_sym_link( node, flags );
-
- } while ( ( result == 0 ) && ( ( jnode->type == IMFS_SYM_LINK ) ||
- ( jnode->type == IMFS_HARD_LINK ) ) );
-
- /*
- * Clear link counter.
- */
-
- rtems_filesystem_link_counts = 0;
-
- return result;
-}
-
-/*
- * IMFS_skip_separator
- *
- * Skip the separator in the path.
- */
-static void IMFS_skip_separator (
- const char *path, /* IN */
- size_t *len, /* IN/OUT */
- int *index /* IN/OUT */
-)
-{
- while ( IMFS_is_separator( path[*index] ) && path[*index] && *len ) {
- ++(*index);
- --(*len);
}
}
-/*
- * IMFS_evaluate_for_make
- *
- * The following routine evaluate path for a new node to be created.
- * pathloc is returned with a pointer to the parent of the new node.
- * name is returned with a pointer to the first character in the
- * new node name. The parent node is verified to be a directory.
- */
-
-int IMFS_evaluate_for_make(
- const char *path, /* IN */
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- const char **name /* OUT */
- )
+static rtems_filesystem_global_location_t **IMFS_is_mount_point(
+ IMFS_jnode_t *node
+)
{
- int i = 0;
- int len;
- IMFS_token_types type;
- char token[ IMFS_NAME_MAX + 1 ];
- IMFS_jnode_t *node;
- bool done = false;
- size_t pathlen;
- int result;
-
- /*
- * This was filled in by the caller and is valid in the
- * mount table.
- */
- node = pathloc->node_access;
-
- /*
- * Get the path length.
- */
- pathlen = strlen( path );
- /*
- * Evaluate all tokens until we are done or an error occurs.
- */
-
- while( !done ) {
-
- type = IMFS_get_token( &path[i], pathlen, token, &len );
- pathlen -= len;
- i += len;
-
- if ( !pathloc->node_access )
- rtems_set_errno_and_return_minus_one( ENOENT );
-
- /*
- * I cannot move out of this directory without execute permission.
- */
+ rtems_filesystem_global_location_t **fs_root_ptr = NULL;
- if ( type != IMFS_NO_MORE_PATH )
- if ( node->type == IMFS_DIRECTORY )
- if ( !IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
- rtems_set_errno_and_return_minus_one( EACCES );
-
- node = pathloc->node_access;
-
- switch( type ) {
-
- case IMFS_UP_DIR:
- /*
- * Am I at the root of all filesystems? (chroot'ed?)
- */
-
- if ( pathloc->node_access == rtems_filesystem_root.node_access )
- break; /* Throw out the .. in this case */
-
-
- /*
- * Am I at the root of this mounted filesystem?
- */
-
- if ( rtems_filesystem_is_root_location( pathloc ) ) {
-
- /*
- * Am I at the root of all filesystems?
- */
-
- if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
- break;
-
- } else {
- *pathloc = pathloc->mt_entry->mt_point_node;
- return (*pathloc->ops->evalformake_h)( &path[i-len], pathloc, name );
- }
- } else {
-
- if ( !node->Parent )
- rtems_set_errno_and_return_minus_one( ENOENT );
-
- node = node->Parent;
- }
-
- pathloc->node_access = node;
- break;
-
- case IMFS_NAME:
-
- if ( node->type == IMFS_HARD_LINK ) {
-
- result = IMFS_evaluate_link( pathloc, 0 );
- if ( result == -1 )
- return -1;
-
- } else if ( node->type == IMFS_SYM_LINK ) {
-
- result = IMFS_evaluate_link( pathloc, 0 );
-
- if ( result == -1 )
- return -1;
- }
-
- node = pathloc->node_access;
- if ( !node )
- rtems_set_errno_and_return_minus_one( ENOTDIR );
-
- /*
- * Only a directory can be decended into.
- */
-
- if ( node->type != IMFS_DIRECTORY )
- rtems_set_errno_and_return_minus_one( ENOTDIR );
-
- /*
- * Find the token name in the present location.
- */
-
- node = IMFS_find_match_in_dir( node, token );
-
- /*
- * If there is no node we have found the name of the node we
- * wish to create.
- */
-
- if ( ! node )
- done = true;
- else {
- if (( node->type == IMFS_DIRECTORY ) && ( node->info.directory.mt_fs != NULL )) {
- IMFS_skip_separator( path, &pathlen, &i);
- if ((path[i] != '.') || (path[i + 1] != '.')) {
- *pathloc = node->info.directory.mt_fs->mt_fs_root;
- return (*pathloc->ops->evalformake_h)( &path[i],
- pathloc,
- name );
- }
- i += 2;
- pathlen -= 2;
- node = node->Parent;
- }
- pathloc->node_access = node;
- }
- break;
-
- case IMFS_NO_MORE_PATH:
- rtems_set_errno_and_return_minus_one( EEXIST );
- break;
-
- case IMFS_INVALID_TOKEN:
- rtems_set_errno_and_return_minus_one( ENAMETOOLONG );
- break;
-
- case IMFS_CURRENT_DIR:
- break;
+ if ( node->type == IMFS_DIRECTORY ) {
+ if ( node->info.directory.mt_fs != NULL ) {
+ fs_root_ptr = &node->info.directory.mt_fs->mt_fs_root;
}
}
- *name = &path[ i - len ];
-
- /*
- * We have evaluated the path as far as we can.
- * Verify there is not any invalid stuff at the end of the name.
- */
-
- for( ; path[i] != '\0'; i++) {
- if ( !IMFS_is_separator( path[ i ] ) )
- rtems_set_errno_and_return_minus_one( ENOENT );
- }
-
- /*
- * Verify we can execute and write to this directory.
- */
-
- result = IMFS_Set_handlers( pathloc );
-
- /*
- * The returned node must be a directory
- */
- node = pathloc->node_access;
- if ( node->type != IMFS_DIRECTORY )
- rtems_set_errno_and_return_minus_one( ENOTDIR );
-
- /*
- * We must have Write and execute permission on the returned node.
- */
-
- if ( !IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_WX ) )
- rtems_set_errno_and_return_minus_one( EACCES );
-
- return result;
+ return fs_root_ptr;
}
-/*
- * IMFS_eval_path
- *
- * The following routine evaluate path for a node that wishes to be
- * accessed with mode. pathloc is returned with a pointer to the
- * node to be accessed.
- */
-
-int IMFS_eval_path(
- const char *pathname, /* IN */
- size_t pathnamelen, /* IN */
- int flags, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
- )
+static rtems_filesystem_eval_path_generic_status IMFS_eval_token(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg,
+ const char *token,
+ size_t tokenlen
+)
{
- int i = 0;
- int len;
- IMFS_token_types type = IMFS_CURRENT_DIR;
- char token[ IMFS_NAME_MAX + 1 ];
- IMFS_jnode_t *node;
- int result;
-
- if ( !rtems_libio_is_valid_perms( flags ) ) {
- rtems_set_errno_and_return_minus_one( EIO );
- }
-
- /*
- * This was filled in by the caller and is valid in the
- * mount table.
- */
-
- node = pathloc->node_access;
-
- /*
- * Evaluate all tokens until we are done or an error occurs.
- */
-
- while( (type != IMFS_NO_MORE_PATH) && (type != IMFS_INVALID_TOKEN) ) {
-
- type = IMFS_get_token( &pathname[i], pathnamelen, token, &len );
- pathnamelen -= len;
- i += len;
-
- if ( !pathloc->node_access )
- rtems_set_errno_and_return_minus_one( ENOENT );
+ rtems_filesystem_eval_path_generic_status status =
+ RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc( ctx );
+ IMFS_jnode_t *dir = currentloc->node_access;
+ bool access_ok = rtems_filesystem_eval_path_check_access(
+ ctx,
+ RTEMS_LIBIO_PERMS_SEARCH,
+ dir->st_mode,
+ dir->st_uid,
+ dir->st_gid
+ );
- /*
- * I cannot move out of this directory without execute permission.
- */
- if ( type != IMFS_NO_MORE_PATH )
- if ( node->type == IMFS_DIRECTORY )
- if ( !IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
- rtems_set_errno_and_return_minus_one( EACCES );
+ if ( access_ok ) {
+ IMFS_jnode_t *entry = IMFS_search_in_directory( dir, token, tokenlen );
- node = pathloc->node_access;
+ if ( entry != NULL ) {
+ bool terminal = !rtems_filesystem_eval_path_has_path( ctx );
+ int eval_flags = rtems_filesystem_eval_path_get_flags( ctx );
+ bool follow_hard_link = (eval_flags & RTEMS_LIBIO_FOLLOW_HARD_LINK) != 0;
+ bool follow_sym_link = (eval_flags & RTEMS_LIBIO_FOLLOW_SYM_LINK) != 0;
- switch( type ) {
- case IMFS_UP_DIR:
- /*
- * Am I at the root of all filesystems? (chroot'ed?)
- */
+ rtems_filesystem_eval_path_clear_token( ctx );
- if ( pathloc->node_access == rtems_filesystem_root.node_access )
- break; /* Throw out the .. in this case */
+ if ( entry->type == IMFS_HARD_LINK && (follow_hard_link || !terminal)) {
+ entry = entry->info.hard_link.link_node;
+ }
- /*
- * Am I at the root of this mounted filesystem?
- */
+ if ( entry->type == IMFS_SYM_LINK && (follow_sym_link || !terminal)) {
+ const char *target = entry->info.sym_link.name;
- if ( rtems_filesystem_is_root_location( pathloc ) ) {
+ rtems_filesystem_eval_path_recursive( ctx, target, strlen( target ) );
+ } else {
+ rtems_filesystem_global_location_t **fs_root_ptr =
+ IMFS_is_mount_point( entry );
- /*
- * Am I at the root of all filesystems?
- */
+ if ( fs_root_ptr == NULL ) {
+ currentloc->node_access = entry;
+ IMFS_Set_handlers( currentloc );
- if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
- break; /* Throw out the .. in this case */
- } else {
- *pathloc = pathloc->mt_entry->mt_point_node;
- return (*pathloc->ops->evalpath_h)(&(pathname[i-len]),
- pathnamelen+len,
- flags,pathloc);
+ if ( !terminal ) {
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
}
} else {
-
- if ( !node->Parent )
- rtems_set_errno_and_return_minus_one( ENOENT );
-
- node = node->Parent;
- pathloc->node_access = node;
-
- }
-
- pathloc->node_access = node;
- break;
-
- case IMFS_NAME:
- /*
- * If we are at a link follow it.
- */
- if ( node->type == IMFS_HARD_LINK ) {
- IMFS_evaluate_hard_link( pathloc, 0 );
- node = pathloc->node_access;
-
- /*
- * It would be a design error if we evaluated the link and
- * was broken.
- */
- IMFS_assert( node );
-
- } else if ( node->type == IMFS_SYM_LINK ) {
- result = IMFS_evaluate_sym_link( pathloc, 0 );
-
- /*
- * In contrast to a hard link, it is possible to have a broken
- * symbolic link.
- */
- node = pathloc->node_access;
- if ( result == -1 )
- return -1;
- }
-
- /*
- * Only a directory can be decended into.
- */
- if ( node->type != IMFS_DIRECTORY )
- rtems_set_errno_and_return_minus_one( ENOTDIR );
-
- /*
- * Find the token name in the current node.
- */
- node = IMFS_find_match_in_dir( node, token );
- if ( !node )
- rtems_set_errno_and_return_minus_one( ENOENT );
-
- /*
- * If we are at a node that is a mount point so current directory
- * actually exists on the mounted file system and not in the node that
- * contains the mount point node. For example a stat of the mount
- * point should return the details of the root of the mounted file
- * system not the mount point node of parent file system.
- *
- * If the node we have just moved to is a mount point do not loop and
- * get the token because the token may be suitable for the mounted
- * file system and not the IMFS. For example the IMFS length is
- * limited. If the token is a parent directory move back up otherwise
- * set loc to the new fs root node and let them finish evaluating the
- * path.
- */
- if (( node->type == IMFS_DIRECTORY ) && ( node->info.directory.mt_fs != NULL )) {
- IMFS_skip_separator( pathname, &pathnamelen, &i);
- if ((pathname[i] != '.') || (pathname[i + 1] != '.')) {
- *pathloc = node->info.directory.mt_fs->mt_fs_root;
- return (*pathloc->ops->evalpath_h)( &pathname[i],
- pathnamelen,
- flags, pathloc );
+ access_ok = rtems_filesystem_eval_path_check_access(
+ ctx,
+ RTEMS_LIBIO_PERMS_EXEC,
+ entry->st_mode,
+ entry->st_uid,
+ entry->st_gid
+ );
+ if ( access_ok ) {
+ rtems_filesystem_eval_path_restart( ctx, fs_root_ptr );
}
- i += 2;
- pathnamelen -= 2;
- node = node->Parent;
}
-
- /*
- * Set the node access to the point we have found.
- */
- pathloc->node_access = node;
- break;
-
- case IMFS_NO_MORE_PATH:
- case IMFS_CURRENT_DIR:
- break;
-
- case IMFS_INVALID_TOKEN:
- rtems_set_errno_and_return_minus_one( ENAMETOOLONG );
- break;
-
- }
- }
-
- /*
- * Always return the root node.
- *
- * If we are at a node that is a mount point. Set loc to the
- * new fs root node and let let the mounted filesystem set the handlers.
- *
- * NOTE: The behavior of stat() on a mount point appears to be questionable.
- */
-
- if ( node->type == IMFS_DIRECTORY ) {
- if ( node->info.directory.mt_fs != NULL ) {
- *pathloc = node->info.directory.mt_fs->mt_fs_root;
- return (*pathloc->ops->evalpath_h)( &pathname[i-len],
- pathnamelen+len,
- flags, pathloc );
+ }
} else {
- result = IMFS_Set_handlers( pathloc );
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
}
- } else {
- result = IMFS_Set_handlers( pathloc );
}
- /*
- * Verify we have the correct permissions for this node.
- */
+ return status;
+}
- if ( !IMFS_evaluate_permission( pathloc, flags ) )
- rtems_set_errno_and_return_minus_one( EACCES );
+static const rtems_filesystem_eval_path_generic_config IMFS_eval_config = {
+ .is_directory = IMFS_is_directory,
+ .eval_token = IMFS_eval_token
+};
- return result;
+void IMFS_eval_path( rtems_filesystem_eval_path_context_t *ctx )
+{
+ rtems_filesystem_eval_path_generic( ctx, NULL, &IMFS_eval_config );
}
diff --git a/cpukit/libfs/src/imfs/imfs_fchmod.c b/cpukit/libfs/src/imfs/imfs_fchmod.c
index 54a093de2f..4236a2901b 100644
--- a/cpukit/libfs/src/imfs/imfs_fchmod.c
+++ b/cpukit/libfs/src/imfs/imfs_fchmod.c
@@ -12,18 +12,14 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
-
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
#include "imfs.h"
int IMFS_fchmod(
- rtems_filesystem_location_info_t *loc,
- mode_t mode
+ const rtems_filesystem_location_info_t *loc,
+ mode_t mode
)
{
IMFS_jnode_t *jnode;
diff --git a/cpukit/libfs/src/imfs/imfs_fifo.c b/cpukit/libfs/src/imfs/imfs_fifo.c
index e447b26a70..790471e472 100644
--- a/cpukit/libfs/src/imfs/imfs_fifo.c
+++ b/cpukit/libfs/src/imfs/imfs_fifo.c
@@ -11,13 +11,9 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <stdlib.h>
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-
#include "imfs.h"
#define JNODE2PIPE(_jnode) ( (_jnode)->info.fifo.pipe )
@@ -35,8 +31,8 @@ do { \
static int IMFS_fifo_open(
rtems_libio_t *iop,
const char *pathname,
- uint32_t flag,
- uint32_t mode
+ int oflag,
+ mode_t mode
)
{
IMFS_jnode_t *jnode = iop->pathinfo.node_access;
@@ -138,10 +134,8 @@ const rtems_filesystem_file_handlers_r IMFS_fifo_handlers = {
IMFS_fifo_ioctl,
IMFS_fifo_lseek,
IMFS_stat,
- IMFS_fchmod,
rtems_filesystem_default_ftruncate,
rtems_filesystem_default_fsync,
rtems_filesystem_default_fdatasync,
- rtems_filesystem_default_fcntl,
- IMFS_rmnod,
+ rtems_filesystem_default_fcntl
};
diff --git a/cpukit/libfs/src/imfs/imfs_fsunmount.c b/cpukit/libfs/src/imfs/imfs_fsunmount.c
index b65c20e60d..49ade1bab9 100644
--- a/cpukit/libfs/src/imfs/imfs_fsunmount.c
+++ b/cpukit/libfs/src/imfs/imfs_fsunmount.c
@@ -12,20 +12,10 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <sys/types.h> /* for mkdir */
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-
#include "imfs.h"
-#include <rtems/libio_.h>
-
-#if defined(IMFS_DEBUG)
-#include <stdio.h>
-#endif
/*
* IMFS_fsunmount
@@ -43,7 +33,7 @@
#define jnode_get_first_child( jnode ) \
((IMFS_jnode_t *)( rtems_chain_head( jnode_get_control( jnode ) )->next))
-int IMFS_fsunmount(
+void IMFS_fsunmount(
rtems_filesystem_mount_table_entry_t *temp_mt_entry
)
{
@@ -57,29 +47,24 @@ int IMFS_fsunmount(
* associated memory space
*/
- jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
- loc = temp_mt_entry->mt_fs_root;
+ loc = temp_mt_entry->mt_fs_root->location;
+ jnode = (IMFS_jnode_t *)loc.node_access;
/*
* Set this to null to indicate that it is being unmounted.
*/
- temp_mt_entry->mt_fs_root.node_access = NULL;
+ temp_mt_entry->mt_fs_root->location.node_access = NULL;
do {
next = jnode->Parent;
loc.node_access = (void *)jnode;
IMFS_Set_handlers( &loc );
- if ( jnode->type != IMFS_DIRECTORY ) {
- result = IMFS_unlink( NULL, &loc );
+ if ( jnode->type != IMFS_DIRECTORY || jnode_has_no_children( jnode ) ) {
+ result = IMFS_rmnod( NULL, &loc );
if (result != 0)
- return -1;
- jnode = next;
- } else if ( jnode_has_no_children( jnode ) ) {
- result = IMFS_unlink( NULL, &loc );
- if (result != 0)
- return -1;
+ rtems_fatal_error_occurred(0xdeadbeef);
jnode = next;
}
if ( jnode != NULL ) {
@@ -89,6 +74,4 @@ int IMFS_fsunmount(
}
}
} while (jnode != NULL);
-
- return 0;
}
diff --git a/cpukit/libfs/src/imfs/imfs_getchild.c b/cpukit/libfs/src/imfs/imfs_getchild.c
deleted file mode 100644
index 1cfeb2a537..0000000000
--- a/cpukit/libfs/src/imfs/imfs_getchild.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * IMFS_find_match_in_dir()
- *
- * This routine returns the child name in the given directory.
- *
- * COPYRIGHT (c) 1989-1999.
- * On-Line Applications Research Corporation (OAR).
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
- *
- * $Id$
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <errno.h>
-#include <string.h>
-#include "imfs.h"
-
-static const char dotname[2] = ".";
-static const char dotdotname[3] = "..";
-
-IMFS_jnode_t *IMFS_find_match_in_dir(
- IMFS_jnode_t *directory,
- char *name
-)
-{
- rtems_chain_node *the_node;
- rtems_chain_control *the_chain;
- IMFS_jnode_t *the_jnode;
-
- /*
- * Check for fatal errors. A NULL directory show a problem in the
- * the IMFS code.
- */
- IMFS_assert( directory );
- IMFS_assert( name );
-
- /*
- * Check for "." and ".."
- */
-
- if ( !strcmp( name, dotname ) )
- return directory;
-
- if ( !strcmp( name, dotdotname ) )
- return directory->Parent;
-
- the_chain = &directory->info.directory.Entries;
-
- for ( the_node = rtems_chain_first( the_chain );
- !rtems_chain_is_tail( the_chain, the_node );
- the_node = the_node->next ) {
-
- the_jnode = (IMFS_jnode_t *) the_node;
-
- if ( !strcmp( name, the_jnode->name ) )
- return the_jnode;
- }
-
- return 0;
-}
diff --git a/cpukit/libfs/src/imfs/imfs_gtkn.c b/cpukit/libfs/src/imfs/imfs_gtkn.c
deleted file mode 100644
index b15b2f1136..0000000000
--- a/cpukit/libfs/src/imfs/imfs_gtkn.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * IMFS_get_token
- *
- * Routine to get a token (name or separator) from the path
- * the length of the token is returned in token_len.
- *
- * COPYRIGHT (c) 1989-1999.
- * On-Line Applications Research Corporation (OAR).
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
- *
- * $Id$
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "imfs.h"
-#include <rtems/libio_.h>
-
-IMFS_token_types IMFS_get_token(
- const char *path,
- int pathlen,
- char *token,
- int *token_len
-)
-{
- register int i = 0;
- IMFS_token_types type = IMFS_NAME;
- register char c;
-
- /*
- * Copy a name into token. (Remember NULL is a token.)
- */
- c = path[i];
- while ( (!IMFS_is_separator(c)) && (i < pathlen) && (i <= IMFS_NAME_MAX) ) {
-
- token[i] = c;
-
- if ( i == IMFS_NAME_MAX )
- return IMFS_INVALID_TOKEN;
-
- if ( !IMFS_is_valid_name_char(c) )
- type = IMFS_INVALID_TOKEN;
-
- c = path [++i];
- }
-
- /*
- * Copy a seperator into token.
- */
-
- if ( i == 0 ) {
- token[i] = c;
-
- if ( (token[i] != '\0') && pathlen ) {
- i++;
- type = IMFS_CURRENT_DIR;
- } else {
- type = IMFS_NO_MORE_PATH;
- }
- } else if (token[ i-1 ] != '\0') {
- token[i] = '\0';
- }
-
- /*
- * Set token_len to the number of characters copied.
- */
-
- *token_len = i;
-
- /*
- * If we copied something that was not a seperator see if
- * it was a special name.
- */
-
- if ( type == IMFS_NAME ) {
- if ( strcmp( token, "..") == 0 )
- type = IMFS_UP_DIR;
- else if ( strcmp( token, "." ) == 0 )
- type = IMFS_CURRENT_DIR;
- }
-
- return type;
-}
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_device.c b/cpukit/libfs/src/imfs/imfs_handlers_device.c
index 8e249bda33..a6edfb1f77 100644
--- a/cpukit/libfs/src/imfs/imfs_handlers_device.c
+++ b/cpukit/libfs/src/imfs/imfs_handlers_device.c
@@ -12,11 +12,9 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
-
#include "imfs.h"
/*
@@ -31,10 +29,8 @@ const rtems_filesystem_file_handlers_r IMFS_device_handlers = {
device_ioctl,
device_lseek,
IMFS_stat,
- IMFS_fchmod,
device_ftruncate,
rtems_filesystem_default_fsync,
rtems_filesystem_default_fdatasync,
- rtems_filesystem_default_fcntl,
- IMFS_rmnod
+ rtems_filesystem_default_fcntl
};
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_directory.c b/cpukit/libfs/src/imfs/imfs_handlers_directory.c
index 5ca715825e..4778f45599 100644
--- a/cpukit/libfs/src/imfs/imfs_handlers_directory.c
+++ b/cpukit/libfs/src/imfs/imfs_handlers_directory.c
@@ -12,11 +12,9 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
-
#include "imfs.h"
/*
@@ -30,11 +28,9 @@ const rtems_filesystem_file_handlers_r IMFS_directory_handlers = {
rtems_filesystem_default_write,
rtems_filesystem_default_ioctl,
imfs_dir_lseek,
- imfs_dir_fstat,
- IMFS_fchmod,
- rtems_filesystem_default_ftruncate,
+ IMFS_stat,
+ rtems_filesystem_default_ftruncate_directory,
rtems_filesystem_default_fsync,
IMFS_fdatasync,
- rtems_filesystem_default_fcntl,
- imfs_dir_rmnod
+ rtems_filesystem_default_fcntl
};
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_link.c b/cpukit/libfs/src/imfs/imfs_handlers_link.c
index d8bbec82d4..967aa1410f 100644
--- a/cpukit/libfs/src/imfs/imfs_handlers_link.c
+++ b/cpukit/libfs/src/imfs/imfs_handlers_link.c
@@ -12,11 +12,9 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
-
#include "imfs.h"
/*
@@ -31,10 +29,8 @@ const rtems_filesystem_file_handlers_r IMFS_link_handlers = {
rtems_filesystem_default_ioctl,
rtems_filesystem_default_lseek,
IMFS_stat, /* stat */
- rtems_filesystem_default_fchmod,
rtems_filesystem_default_ftruncate,
rtems_filesystem_default_fsync,
rtems_filesystem_default_fdatasync,
- rtems_filesystem_default_fcntl,
- IMFS_rmnod
+ rtems_filesystem_default_fcntl
};
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
index ee859ee98d..10e47fd0f8 100644
--- a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
+++ b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
@@ -12,11 +12,9 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
-
#include "imfs.h"
/*
@@ -31,10 +29,8 @@ const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = {
memfile_ioctl,
memfile_lseek,
IMFS_stat,
- IMFS_fchmod,
memfile_ftruncate,
IMFS_fdatasync, /* fsync */
IMFS_fdatasync,
- rtems_filesystem_default_fcntl,
- IMFS_rmnod
+ rtems_filesystem_default_fcntl
};
diff --git a/cpukit/libfs/src/imfs/imfs_init.c b/cpukit/libfs/src/imfs/imfs_init.c
index c74d493b40..2a7d890a09 100644
--- a/cpukit/libfs/src/imfs/imfs_init.c
+++ b/cpukit/libfs/src/imfs/imfs_init.c
@@ -18,28 +18,29 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <rtems/libio_.h>
-
#include "imfs.h"
const rtems_filesystem_operations_table IMFS_ops = {
- .evalpath_h = IMFS_eval_path,
- .evalformake_h = IMFS_evaluate_for_make,
+ .lock_h = rtems_filesystem_default_lock,
+ .unlock_h = rtems_filesystem_default_unlock,
+ .eval_path_h = IMFS_eval_path,
.link_h = IMFS_link,
- .unlink_h = IMFS_unlink,
+ .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
.node_type_h = IMFS_node_type,
.mknod_h = IMFS_mknod,
+ .rmnod_h = IMFS_rmnod,
+ .fchmod_h = IMFS_fchmod,
.chown_h = IMFS_chown,
+ .clonenod_h = rtems_filesystem_default_clonenode,
.freenod_h = rtems_filesystem_default_freenode,
.mount_h = IMFS_mount,
.fsmount_me_h = IMFS_initialize,
.unmount_h = IMFS_unmount,
.fsunmount_me_h = IMFS_fsunmount,
.utime_h = IMFS_utime,
- .eval_link_h = IMFS_evaluate_link,
.symlink_h = IMFS_symlink,
.readlink_h = IMFS_readlink,
.rename_h = IMFS_rename,
@@ -54,8 +55,7 @@ int IMFS_initialize(
return IMFS_initialize_support(
mt_entry,
&IMFS_ops,
- &IMFS_memfile_handlers,
- &IMFS_directory_handlers,
- &rtems_filesystem_handlers_default /* for fifos */
+ &IMFS_link_handlers,
+ &rtems_filesystem_handlers_default /* for fifos */
);
}
diff --git a/cpukit/libfs/src/imfs/imfs_initsupp.c b/cpukit/libfs/src/imfs/imfs_initsupp.c
index 47e1d392e8..61ad6a70f2 100644
--- a/cpukit/libfs/src/imfs/imfs_initsupp.c
+++ b/cpukit/libfs/src/imfs/imfs_initsupp.c
@@ -12,21 +12,12 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <sys/types.h> /* for mkdir */
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-
#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-#if defined(IMFS_DEBUG)
-#include <stdio.h>
-#endif
+#include <stdlib.h>
/*
* IMFS_determine_bytes_per_block
@@ -66,8 +57,7 @@ static int IMFS_determine_bytes_per_block(
int IMFS_initialize_support(
rtems_filesystem_mount_table_entry_t *temp_mt_entry,
const rtems_filesystem_operations_table *op_table,
- const rtems_filesystem_file_handlers_r *memfile_handlers,
- const rtems_filesystem_file_handlers_r *directory_handlers,
+ const rtems_filesystem_file_handlers_r *link_handlers,
const rtems_filesystem_file_handlers_r *fifo_handlers
)
{
@@ -87,9 +77,9 @@ int IMFS_initialize_support(
*
* NOTE: UNIX root is 755 and owned by root/root (0/0).
*/
- temp_mt_entry->mt_fs_root.node_access = IMFS_create_root_node();
- temp_mt_entry->mt_fs_root.handlers = directory_handlers;
- temp_mt_entry->mt_fs_root.ops = op_table;
+ temp_mt_entry->mt_fs_root->location.node_access = IMFS_create_root_node();
+ temp_mt_entry->mt_fs_root->location.handlers = &IMFS_directory_handlers;
+ temp_mt_entry->mt_fs_root->location.ops = op_table;
temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
/*
@@ -97,7 +87,7 @@ int IMFS_initialize_support(
*/
fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
if ( !fs_info ) {
- free(temp_mt_entry->mt_fs_root.node_access);
+ free(temp_mt_entry->mt_fs_root->location.node_access);
rtems_set_errno_and_return_minus_one(ENOMEM);
}
temp_mt_entry->fs_info = fs_info;
@@ -108,11 +98,10 @@ int IMFS_initialize_support(
fs_info->instance = imfs_instance++;
fs_info->ino_count = 1;
- fs_info->memfile_handlers = memfile_handlers;
- fs_info->directory_handlers = directory_handlers;
+ fs_info->link_handlers = link_handlers;
fs_info->fifo_handlers = fifo_handlers;
- jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode = temp_mt_entry->mt_fs_root->location.node_access;
jnode->st_ino = fs_info->ino_count;
return 0;
diff --git a/cpukit/libfs/src/imfs/imfs_link.c b/cpukit/libfs/src/imfs/imfs_link.c
index c7dc6475f9..130c529d75 100644
--- a/cpukit/libfs/src/imfs/imfs_link.c
+++ b/cpukit/libfs/src/imfs/imfs_link.c
@@ -16,51 +16,36 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
int IMFS_link(
- rtems_filesystem_location_info_t *to_loc, /* IN */
- rtems_filesystem_location_info_t *parent_loc, /* IN */
- const char *token /* IN */
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *targetloc,
+ const char *name,
+ size_t namelen
)
{
IMFS_types_union info;
IMFS_jnode_t *new_node;
- char new_name[ IMFS_NAME_MAX + 1 ];
- int i;
/*
* Verify this node can be linked to.
*/
- info.hard_link.link_node = to_loc->node_access;
+ info.hard_link.link_node = targetloc->node_access;
if ( info.hard_link.link_node->st_nlink >= LINK_MAX )
rtems_set_errno_and_return_minus_one( EMLINK );
/*
- * Remove any separators at the end of the string.
- */
- IMFS_get_token( token, strlen( token ), new_name, &i );
-
- /*
* Create a new link node.
- *
- * NOTE: Coverity Id 19 reports this as a leak
- * While technically not a leak, it indicated that IMFS_create_node
- * was ONLY passed a NULL when we created the root node. We
- * added a new IMFS_create_root_node() so this path no longer
- * existed. The result was simpler code which should not have
- * this path.
*/
new_node = IMFS_create_node(
- parent_loc,
+ parentloc,
IMFS_HARD_LINK,
- new_name,
+ name,
+ namelen,
( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
&info
);
diff --git a/cpukit/libfs/src/imfs/imfs_load_tar.c b/cpukit/libfs/src/imfs/imfs_load_tar.c
index 69c69c3e6d..0ae0f7cf88 100644
--- a/cpukit/libfs/src/imfs/imfs_load_tar.c
+++ b/cpukit/libfs/src/imfs/imfs_load_tar.c
@@ -21,16 +21,12 @@
* pointing to addresses in the TAR image.
*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <tar.h>
+#include "imfs.h"
+#include <sys/stat.h>
#include <string.h>
+#include <tar.h>
-#include <rtems.h>
-#include <rtems/libio_.h>
-#include <rtems/imfs.h>
#include <rtems/untar.h>
/*
@@ -80,13 +76,11 @@
* create_node.
*/
int rtems_tarfs_load(
- char *mountpoint,
+ const char *mountpoint,
uint8_t *tar_image,
- size_t tar_size
+ size_t tar_size
)
{
- rtems_filesystem_location_info_t root_loc;
- rtems_filesystem_location_info_t loc;
const char *hdr_ptr;
char filename[100];
char full_filename[256];
@@ -97,26 +91,27 @@ int rtems_tarfs_load(
int offset;
unsigned long nblocks;
IMFS_jnode_t *node;
- int status;
-
- status = rtems_filesystem_evaluate_path(
- mountpoint,
- strlen(mountpoint),
- 0,
- &root_loc,
- 0
+ int rv = 0;
+ int eval_flags = RTEMS_LIBIO_FOLLOW_LINK;
+ rtems_filesystem_eval_path_context_t ctx;
+ rtems_filesystem_location_info_t rootloc;
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_start( &ctx, mountpoint, eval_flags );
+
+ rtems_filesystem_eval_path_extract_currentloc( &ctx, &rootloc );
+ rtems_filesystem_eval_path_set_flags(
+ &ctx,
+ RTEMS_LIBIO_MAKE | RTEMS_LIBIO_EXCLUSIVE
);
- if (status != 0)
- return -1;
-
- if (root_loc.ops != &IMFS_ops && root_loc.ops != &fifoIMFS_ops)
- return -1;
+ if (rootloc.ops != &IMFS_ops && rootloc.ops != &fifoIMFS_ops) {
+ rv = -1;
+ }
/*
* Create an IMFS node structure pointing to tar image memory.
*/
offset = 0;
- while (1) {
+ while ( rv == 0 ) {
if (offset + 512 > tar_size)
break;
@@ -154,22 +149,23 @@ int rtems_tarfs_load(
}
/*
* Create a LINEAR_FILE node
- *
- * NOTE: Coverity Id 20 reports this as a leak.
- * While technically not a leak, it indicated that
- * IMFS_create_node was ONLY passed a NULL when we created the
- * root node. We added a new IMFS_create_root_node() so this
- * path no longer existed. The result was simpler code which
- * should not have this path.
*/
else if (linkflag == REGTYPE) {
- const char *name;
-
- loc = root_loc;
- if (IMFS_evaluate_for_make(filename, &loc, &name) == 0) {
+ rtems_filesystem_location_free( currentloc );
+ rtems_filesystem_location_clone( currentloc, &rootloc );
+ rtems_filesystem_eval_path_set_path(
+ &ctx,
+ filename,
+ strlen( filename )
+ );
+ rtems_filesystem_eval_path_continue( &ctx );
+
+ if ( !rtems_filesystem_location_is_null( currentloc ) ) {
node = IMFS_create_node(
- &loc,
- IMFS_LINEAR_FILE, (char *)name,
+ currentloc,
+ IMFS_LINEAR_FILE,
+ rtems_filesystem_eval_path_get_token( &ctx ),
+ rtems_filesystem_eval_path_get_tokenlen( &ctx ),
(file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG,
NULL
);
@@ -181,6 +177,10 @@ int rtems_tarfs_load(
offset += 512 * nblocks;
}
}
- return status;
+
+ rtems_filesystem_location_free( &rootloc );
+ rtems_filesystem_eval_path_cleanup( &ctx );
+
+ return rv;
}
diff --git a/cpukit/libfs/src/imfs/imfs_mknod.c b/cpukit/libfs/src/imfs/imfs_mknod.c
index 747391e9fd..47f7dca0e8 100644
--- a/cpukit/libfs/src/imfs/imfs_mknod.c
+++ b/cpukit/libfs/src/imfs/imfs_mknod.c
@@ -6,6 +6,9 @@
* COPYRIGHT (c) 1989-2010.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -14,65 +17,60 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-
#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
+
+static void get_type_and_info_by_mode_and_dev(
+ mode_t mode,
+ dev_t dev,
+ IMFS_jnode_types_t *type,
+ IMFS_types_union *info
+)
+{
+ if ( S_ISDIR( mode ) ) {
+ *type = IMFS_DIRECTORY;
+ } else if ( S_ISREG( mode ) ) {
+ *type = IMFS_MEMORY_FILE;
+ } else if ( S_ISBLK( mode ) || S_ISCHR( mode ) ) {
+ *type = IMFS_DEVICE;
+ rtems_filesystem_split_dev_t(
+ dev,
+ info->device.major,
+ info->device.minor
+ );
+ } else if (S_ISFIFO( mode )) {
+ *type = IMFS_FIFO;
+ } else {
+ IMFS_assert( 0 );
+ }
+}
int IMFS_mknod(
- const char *token, /* IN */
- mode_t mode, /* IN */
- dev_t dev, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
)
{
- IMFS_token_types type = 0;
- IMFS_jnode_t *new_node;
- int result;
- char new_name[ IMFS_NAME_MAX + 1 ];
- IMFS_types_union info;
+ int rv = 0;
+ IMFS_jnode_types_t type;
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
- IMFS_get_token( token, strlen( token ), new_name, &result );
+ get_type_and_info_by_mode_and_dev( mode, dev, &type, &info );
- /*
- * Figure out what type of IMFS node this is.
- */
- if ( S_ISDIR(mode) )
- type = IMFS_DIRECTORY;
- else if ( S_ISREG(mode) )
- type = IMFS_MEMORY_FILE;
- else if ( S_ISBLK(mode) || S_ISCHR(mode) ) {
- type = IMFS_DEVICE;
- rtems_filesystem_split_dev_t( dev, info.device.major, info.device.minor );
- } else if (S_ISFIFO(mode))
- type = IMFS_FIFO;
- else
- IMFS_assert( 0 );
+ new_node = IMFS_create_node( parentloc, type, name, namelen, mode, &info );
+ if ( new_node != NULL ) {
+ IMFS_jnode_t *parent = parentloc->node_access;
- /*
- * Allocate and fill in an IMFS jnode
- *
- * NOTE: Coverity Id 21 reports this as a leak.
- * While technically not a leak, it indicated that IMFS_create_node
- * was ONLY passed a NULL when we created the root node. We
- * added a new IMFS_create_root_node() so this path no longer
- * existed. The result was simpler code which should not have
- * this path.
- */
- new_node = IMFS_create_node( pathloc, type, new_name, mode, &info );
- if ( !new_node )
- rtems_set_errno_and_return_minus_one( ENOMEM );
+ IMFS_update_ctime( parent );
+ IMFS_update_mtime( parent );
+ } else {
+ rv = -1;
+ }
- IMFS_update_ctime(new_node->Parent);
- IMFS_update_mtime(new_node->Parent);
- return 0;
+ return rv;
}
diff --git a/cpukit/libfs/src/imfs/imfs_mount.c b/cpukit/libfs/src/imfs/imfs_mount.c
index 3ec16da3f7..243e5a0e30 100644
--- a/cpukit/libfs/src/imfs/imfs_mount.c
+++ b/cpukit/libfs/src/imfs/imfs_mount.c
@@ -1,16 +1,12 @@
/*
* IMFS_mount
*
- * This routine will look at a mount table entry that we are going to
- * add to the mount table. If the mount point rtems_filesystem
- * location_info_t struct refers to a node that is a directory,
- * the node will be marked as a mount point by setting its directory.mt_fs
- * pointer to point to the mount table entry that we are about to add
- * to the mount table chain.
- *
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -19,35 +15,27 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
-
#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-int IMFS_mount(
- rtems_filesystem_mount_table_entry_t *mt_entry
-)
+int IMFS_mount( rtems_filesystem_mount_table_entry_t *mt_entry )
{
- IMFS_jnode_t *node;
-
- node = mt_entry->mt_point_node.node_access;
-
- /*
- * Is the node that we are mounting onto a directory node ?
- */
-
- if ( node->type != IMFS_DIRECTORY )
- rtems_set_errno_and_return_minus_one( ENOTDIR );
-
- /*
- * Set mt_fs pointer to point to the mount table entry for
- * the mounted file system.
- */
-
- node->info.directory.mt_fs = mt_entry;
- return 0;
+ int rv = 0;
+ IMFS_jnode_t *node = mt_entry->mt_point_node->location.node_access;
+
+ if ( node->type == IMFS_DIRECTORY ) {
+ if ( node->info.directory.mt_fs == NULL ) {
+ node->info.directory.mt_fs = mt_entry;
+ } else {
+ errno = EBUSY;
+ rv = -1;
+ }
+ } else {
+ errno = ENOTDIR;
+ rv = -1;
+ }
+
+ return rv;
}
diff --git a/cpukit/libfs/src/imfs/imfs_ntype.c b/cpukit/libfs/src/imfs/imfs_ntype.c
index f80182b144..f399707c0c 100644
--- a/cpukit/libfs/src/imfs/imfs_ntype.c
+++ b/cpukit/libfs/src/imfs/imfs_ntype.c
@@ -7,6 +7,9 @@
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -15,18 +18,30 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
#include "imfs.h"
rtems_filesystem_node_types_t IMFS_node_type(
- rtems_filesystem_location_info_t *pathloc /* IN */
+ const rtems_filesystem_location_info_t *loc
)
{
- IMFS_jnode_t *node;
+ const IMFS_jnode_t *node = loc->node_access;
+ IMFS_jnode_types_t imfs_type = node->type;
+ rtems_filesystem_node_types_t type;
+
+ switch ( imfs_type ) {
+ case IMFS_HARD_LINK:
+ type = node->info.hard_link.link_node->type;
+ break;
+ case IMFS_LINEAR_FILE:
+ type = RTEMS_FILESYSTEM_MEMORY_FILE;
+ break;
+ default:
+ type = imfs_type;
+ break;
+ }
- node = pathloc->node_access;
- return node->type;
+ return type;
}
diff --git a/cpukit/libfs/src/imfs/imfs_readlink.c b/cpukit/libfs/src/imfs/imfs_readlink.c
index b598fcf2c1..6786806abd 100644
--- a/cpukit/libfs/src/imfs/imfs_readlink.c
+++ b/cpukit/libfs/src/imfs/imfs_readlink.c
@@ -15,18 +15,15 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
ssize_t IMFS_readlink(
- rtems_filesystem_location_info_t *loc,
- char *buf, /* OUT */
- size_t bufsize
+ const rtems_filesystem_location_info_t *loc,
+ char *buf,
+ size_t bufsize
)
{
IMFS_jnode_t *node;
diff --git a/cpukit/libfs/src/imfs/imfs_rename.c b/cpukit/libfs/src/imfs/imfs_rename.c
index 95c27fa9fd..855d026c36 100644
--- a/cpukit/libfs/src/imfs/imfs_rename.c
+++ b/cpukit/libfs/src/imfs/imfs_rename.c
@@ -15,40 +15,50 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
int IMFS_rename(
- rtems_filesystem_location_info_t *old_parent_loc, /* IN */
- rtems_filesystem_location_info_t *old_loc, /* IN */
- rtems_filesystem_location_info_t *new_parent_loc, /* IN */
- const char *new_name /* IN */
+ const rtems_filesystem_location_info_t *oldparentloc,
+ const rtems_filesystem_location_info_t *oldloc,
+ const rtems_filesystem_location_info_t *newparentloc,
+ const char *name,
+ size_t namelen
)
{
- IMFS_jnode_t *the_jnode;
- IMFS_jnode_t *new_parent;
+ int rv = 0;
+ IMFS_jnode_t *node = oldloc->node_access;
+ IMFS_jnode_t *new_parent = newparentloc->node_access;
- the_jnode = old_loc->node_access;
-
- strncpy( the_jnode->name, new_name, IMFS_NAME_MAX );
+ /*
+ * FIXME: Due to insufficient checks we can create inaccessible nodes with
+ * this operation.
+ */
- if ( the_jnode->Parent != NULL )
- rtems_chain_extract( (rtems_chain_node *) the_jnode );
+ if ( node->Parent != NULL ) {
+ if ( namelen < IMFS_NAME_MAX ) {
+ memcpy( node->name, name, namelen );
+ node->name [namelen] = '\0';
- new_parent = new_parent_loc->node_access;
- the_jnode->Parent = new_parent;
+ rtems_chain_extract( &node->Node );
- rtems_chain_append( &new_parent->info.directory.Entries, &the_jnode->Node );
+ node->Parent = new_parent;
+ rtems_chain_append(
+ &new_parent->info.directory.Entries,
+ &node->Node
+ );
- /*
- * Update the time.
- */
- IMFS_update_ctime( the_jnode );
+ IMFS_update_ctime( node );
+ } else {
+ errno = ENAMETOOLONG;
+ rv = -1;
+ }
+ } else {
+ errno = EINVAL;
+ rv = -1;
+ }
- return 0;
+ return rv;
}
diff --git a/cpukit/libfs/src/imfs/imfs_rmnod.c b/cpukit/libfs/src/imfs/imfs_rmnod.c
index 25c7cde084..c50041942f 100644
--- a/cpukit/libfs/src/imfs/imfs_rmnod.c
+++ b/cpukit/libfs/src/imfs/imfs_rmnod.c
@@ -7,6 +7,9 @@
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -15,17 +18,13 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <stdlib.h>
-
-#include <rtems.h>
-#include <rtems/libio.h>
-#include <rtems/libio_.h>
-
#include "imfs.h"
+#include <stdlib.h>
+
void IMFS_create_orphan( IMFS_jnode_t *jnode )
{
if ( jnode->Parent != NULL ) {
@@ -40,10 +39,7 @@ void IMFS_create_orphan( IMFS_jnode_t *jnode )
void IMFS_check_node_remove( IMFS_jnode_t *jnode )
{
- if ( !rtems_libio_is_file_open( jnode ) && jnode->st_nlink < 1 ) {
- if ( rtems_filesystem_current.node_access == jnode )
- rtems_filesystem_current.node_access = NULL;
-
+ if ( jnode->st_nlink < 1 ) {
switch ( jnode->type ) {
case IMFS_MEMORY_FILE:
IMFS_memfile_remove( jnode );
@@ -59,19 +55,75 @@ void IMFS_check_node_remove( IMFS_jnode_t *jnode )
}
}
-/*
- * IMFS_rmnod
- */
+static int IMFS_rmnod_directory(
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *loc
+)
+{
+ IMFS_jnode_t *node = loc->node_access;
+ int rv = 0;
+
+ if ( !rtems_chain_is_empty( &node->info.directory.Entries ) ) {
+ errno = ENOTEMPTY;
+ rv = -1;
+ } else if (
+ rtems_filesystem_location_is_root( loc )
+ || node->info.directory.mt_fs != NULL
+ ) {
+ errno = EBUSY;
+ rv = -1;
+ }
+
+ return rv;
+}
+
+static int IMFS_rmnod_hard_link(
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *loc
+)
+{
+ int rv = 0;
+ IMFS_jnode_t *node = loc->node_access;
+ IMFS_jnode_t *target = node->info.hard_link.link_node;
+
+ if ( target->st_nlink == 1) {
+ rtems_filesystem_location_info_t target_loc = *loc;
+
+ target_loc.node_access = target;
+ IMFS_Set_handlers( &target_loc );
+
+ rv = (*target_loc.ops->rmnod_h)( parentloc, &target_loc );
+ } else {
+ --target->st_nlink;
+ IMFS_update_ctime( target );
+ }
+
+ return rv;
+}
int IMFS_rmnod(
- rtems_filesystem_location_info_t *parent_pathloc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *loc
)
{
- IMFS_jnode_t *jnode = (IMFS_jnode_t *) pathloc->node_access;
+ int rv = 0;
+ IMFS_jnode_t *node = loc->node_access;
- IMFS_create_orphan( jnode );
- IMFS_check_node_remove( jnode );
+ switch ( node->type ) {
+ case IMFS_DIRECTORY:
+ rv = IMFS_rmnod_directory( parentloc, loc );
+ break;
+ case IMFS_HARD_LINK:
+ rv = IMFS_rmnod_hard_link( parentloc, loc );
+ break;
+ default:
+ break;
+ }
+
+ if ( rv == 0 ) {
+ IMFS_create_orphan( node );
+ IMFS_check_node_remove( node );
+ }
- return 0;
+ return rv;
}
diff --git a/cpukit/libfs/src/imfs/imfs_stat.c b/cpukit/libfs/src/imfs/imfs_stat.c
index 5bc1eae579..66d1ca2ba9 100644
--- a/cpukit/libfs/src/imfs/imfs_stat.c
+++ b/cpukit/libfs/src/imfs/imfs_stat.c
@@ -6,6 +6,9 @@
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -14,31 +17,45 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
-#include <string.h>
#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
+
+#include <dirent.h>
+#include <string.h>
+
+static size_t IMFS_directory_size( const IMFS_jnode_t *the_jnode )
+{
+ size_t size = 0;
+ const rtems_chain_control *chain = &the_jnode->info.directory.Entries;
+ const rtems_chain_node *current = rtems_chain_immutable_first( chain );
+ const rtems_chain_node *tail = rtems_chain_immutable_tail( chain );
+
+ while ( current != tail ) {
+ size += sizeof(struct dirent);
+ current = rtems_chain_immutable_next( current );
+ }
+
+ return size;
+}
int IMFS_stat(
- rtems_filesystem_location_info_t *loc,
- struct stat *buf
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *buf
)
{
- IMFS_fs_info_t *fs_info;
- IMFS_jnode_t *the_jnode;
- IMFS_device_t *io;
-
- the_jnode = loc->node_access;
+ IMFS_fs_info_t *fs_info = loc->mt_entry->fs_info;
+ IMFS_jnode_t *the_jnode = loc->node_access;
+ IMFS_device_t *io = &the_jnode->info.device;
+ if ( the_jnode->type == IMFS_HARD_LINK ) {
+ the_jnode = the_jnode->info.hard_link.link_node;
+ }
switch ( the_jnode->type ) {
case IMFS_DEVICE:
- io = &the_jnode->info.device;
buf->st_rdev = rtems_filesystem_make_dev_t( io->major, io->minor );
break;
@@ -47,12 +64,15 @@ int IMFS_stat(
buf->st_size = the_jnode->info.file.size;
break;
+ case IMFS_DIRECTORY:
+ buf->st_size = IMFS_directory_size( the_jnode );
+ break;
+
case IMFS_SYM_LINK:
buf->st_size = strlen( the_jnode->info.sym_link.name );
break;
case IMFS_FIFO:
- buf->st_size = 0;
break;
default:
@@ -64,7 +84,6 @@ int IMFS_stat(
* The device number of the IMFS is the major number and the minor is the
* instance.
*/
- fs_info = loc->mt_entry->fs_info;
buf->st_dev =
rtems_filesystem_make_dev_t( IMFS_DEVICE_MAJOR_NUMBER, fs_info->instance );
@@ -78,7 +97,9 @@ int IMFS_stat(
buf->st_mtime = the_jnode->stat_mtime;
buf->st_ctime = the_jnode->stat_ctime;
- buf->st_blksize = imfs_rq_memfile_bytes_per_block;
+ if ( the_jnode->type != IMFS_DIRECTORY ) {
+ buf->st_blksize = imfs_rq_memfile_bytes_per_block;
+ }
return 0;
}
diff --git a/cpukit/libfs/src/imfs/imfs_symlink.c b/cpukit/libfs/src/imfs/imfs_symlink.c
index 863ad23510..5a1d06ad19 100644
--- a/cpukit/libfs/src/imfs/imfs_symlink.c
+++ b/cpukit/libfs/src/imfs/imfs_symlink.c
@@ -16,54 +16,39 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
+
+#include <stdlib.h>
int IMFS_symlink(
- rtems_filesystem_location_info_t *parent_loc,
- const char *link_name,
- const char *node_name
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ const char *target
)
{
IMFS_types_union info;
IMFS_jnode_t *new_node;
- char new_name[ IMFS_NAME_MAX + 1 ];
- int i;
-
- /*
- * Remove any separators at the end of the string.
- */
- IMFS_get_token( node_name, strlen( node_name ), new_name, &i );
/*
* Duplicate link name
*/
- info.sym_link.name = strdup(link_name);
+ info.sym_link.name = strdup(target);
if (info.sym_link.name == NULL) {
rtems_set_errno_and_return_minus_one(ENOMEM);
}
/*
* Create a new link node.
- *
- * NOTE: Coverity CID 22 notes this as a resource leak.
- * While technically not a leak, it indicated that IMFS_create_node
- * was ONLY passed a NULL when we created the root node. We
- * added a new IMFS_create_root_node() so this path no longer
- * existed. The result was simpler code which should not have
- * this path.
*/
new_node = IMFS_create_node(
- parent_loc,
+ parentloc,
IMFS_SYM_LINK,
- new_name,
+ name,
+ namelen,
( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
&info
);
diff --git a/cpukit/libfs/src/imfs/imfs_unlink.c b/cpukit/libfs/src/imfs/imfs_unlink.c
deleted file mode 100644
index 0ec176ed03..0000000000
--- a/cpukit/libfs/src/imfs/imfs_unlink.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * IMFS_unlink
- *
- * Routine to remove a link node from the tree.
- *
- * COPYRIGHT (c) 1989-1999.
- * On-Line Applications Research Corporation (OAR).
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
- *
- * $Id$
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-
-#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-
-int IMFS_unlink(
- rtems_filesystem_location_info_t *parentloc, /* IN */
- rtems_filesystem_location_info_t *loc /* IN */
-)
-{
- IMFS_jnode_t *node;
- rtems_filesystem_location_info_t the_link;
- int result = 0;
-
- node = loc->node_access;
-
- /*
- * Decrement the link counter of node pointed to and free the
- * space.
- */
-
- /*
- * If this is the last last pointer to the node
- * free the node.
- */
-
- if ( node->type == IMFS_HARD_LINK ) {
-
- if ( !node->info.hard_link.link_node )
- rtems_set_errno_and_return_minus_one( EINVAL );
-
- the_link = *loc;
- the_link.node_access = node->info.hard_link.link_node;
- IMFS_Set_handlers( &the_link );
-
- /*
- * If removing the last hard link to a node, then we need
- * to remove the node that is a link and the node itself.
- */
-
- if ( node->info.hard_link.link_node->st_nlink == 1)
- {
- result = (*the_link.handlers->rmnod_h)( parentloc, &the_link );
- if ( result != 0 )
- return -1;
- }
- else
- {
- node->info.hard_link.link_node->st_nlink --;
- IMFS_update_ctime( node->info.hard_link.link_node );
- }
- }
-
- /*
- * Now actually free the node we were asked to free.
- */
-
- result = (*loc->handlers->rmnod_h)( parentloc, loc );
-
- return result;
-}
diff --git a/cpukit/libfs/src/imfs/imfs_unmount.c b/cpukit/libfs/src/imfs/imfs_unmount.c
index ee1482bfa5..47acec9320 100644
--- a/cpukit/libfs/src/imfs/imfs_unmount.c
+++ b/cpukit/libfs/src/imfs/imfs_unmount.c
@@ -1,17 +1,12 @@
/*
* IMFS_unmount
*
- * This routine will look at a mount table entry that we are going to
- * add to the mount table. If the mount point
- * rtems_filesystem_location_info_t struct refers to a node that is a
- * directory that has a file system mounted on it, the node will be
- * marked as a mount point by * setting its directory.mt_fs pointer
- * to NULL. This indicates that a directory is no longer mounted on
- * this node.
- *
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -20,43 +15,27 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
-
#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-int IMFS_unmount(
- rtems_filesystem_mount_table_entry_t *mt_entry
-)
+int IMFS_unmount( rtems_filesystem_mount_table_entry_t *mt_entry )
{
- IMFS_jnode_t *node;
-
- node = mt_entry->mt_point_node.node_access;
-
- /*
- * Is the node that we are mounting onto a directory node ?
- */
-
- if ( node->type != IMFS_DIRECTORY )
- rtems_set_errno_and_return_minus_one( ENOTDIR );
-
- /*
- * Did the node indicate that there was a directory mounted here?
- */
-
- if ( node->info.directory.mt_fs == NULL )
- rtems_set_errno_and_return_minus_one( EINVAL ); /* XXX */
-
- /*
- * Set the mt_fs pointer to indicate that there is no longer
- * a file system mounted to this point.
- */
-
- node->info.directory.mt_fs = NULL;
-
- return 0;
+ int rv = 0;
+ IMFS_jnode_t *node = mt_entry->mt_point_node->location.node_access;
+
+ if ( node->type == IMFS_DIRECTORY ) {
+ if ( node->info.directory.mt_fs == mt_entry ) {
+ node->info.directory.mt_fs = NULL;
+ } else {
+ errno = EINVAL;
+ rv = -1;
+ }
+ } else {
+ errno = ENOTDIR;
+ rv = -1;
+ }
+
+ return rv;
}
diff --git a/cpukit/libfs/src/imfs/imfs_utime.c b/cpukit/libfs/src/imfs/imfs_utime.c
index 2867e13ed6..b16af11b30 100644
--- a/cpukit/libfs/src/imfs/imfs_utime.c
+++ b/cpukit/libfs/src/imfs/imfs_utime.c
@@ -15,24 +15,22 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <errno.h>
-#include <sys/time.h>
-
-#include <rtems/libio_.h>
#include "imfs.h"
+#include <sys/time.h>
+
int IMFS_utime(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- time_t actime, /* IN */
- time_t modtime /* IN */
+ const rtems_filesystem_location_info_t *loc,
+ time_t actime,
+ time_t modtime
)
{
IMFS_jnode_t *the_jnode;
- the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+ the_jnode = (IMFS_jnode_t *) loc->node_access;
the_jnode->stat_atime = actime;
the_jnode->stat_mtime = modtime;
diff --git a/cpukit/libfs/src/imfs/ioman.c b/cpukit/libfs/src/imfs/ioman.c
index 0dce7e7239..c0dbee5d05 100644
--- a/cpukit/libfs/src/imfs/ioman.c
+++ b/cpukit/libfs/src/imfs/ioman.c
@@ -5,6 +5,9 @@
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -13,19 +16,13 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
#include <string.h>
-#include <rtems.h>
#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-#include "imfs.h"
/*
* rtems_io_register_name
@@ -52,42 +49,23 @@ rtems_status_code rtems_io_register_name(
return RTEMS_SUCCESSFUL;
}
-/*
- * rtems_io_lookup_name
- *
- * This version is reentrant.
- *
- * XXX - This is dependent upon IMFS and should not be.
- * Suggest adding a filesystem routine to fill in the device_info.
- */
-
rtems_status_code rtems_io_lookup_name(
const char *name,
rtems_driver_name_t *device_info
)
{
- IMFS_jnode_t *the_jnode;
- rtems_filesystem_location_info_t loc;
- int result;
- rtems_filesystem_node_types_t node_type;
-
- result = rtems_filesystem_evaluate_path(
- name, strlen( name ), 0x00, &loc, true );
- the_jnode = loc.node_access;
-
- node_type = (*loc.ops->node_type_h)( &loc );
-
- if ( (result != 0) || node_type != RTEMS_FILESYSTEM_DEVICE ) {
- rtems_filesystem_freenode( &loc );
- return RTEMS_UNSATISFIED;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ struct stat st;
+ int rv = stat( name, &st );
+
+ if ( rv == 0 && S_ISCHR( st.st_mode ) ) {
+ device_info->device_name = name;
+ device_info->device_name_length = strlen( name );
+ device_info->major = rtems_filesystem_dev_major_t( st.st_rdev );
+ device_info->minor = rtems_filesystem_dev_minor_t( st.st_rdev );
+ } else {
+ sc = RTEMS_UNSATISFIED;
}
- device_info->device_name = name;
- device_info->device_name_length = strlen( name );
- device_info->major = the_jnode->info.device.major;
- device_info->minor = the_jnode->info.device.minor;
-
- rtems_filesystem_freenode( &loc );
-
- return RTEMS_SUCCESSFUL;
+ return sc;
}
diff --git a/cpukit/libfs/src/imfs/memfile.c b/cpukit/libfs/src/imfs/memfile.c
index 35c1eee0ec..65810c0bca 100644
--- a/cpukit/libfs/src/imfs/memfile.c
+++ b/cpukit/libfs/src/imfs/memfile.c
@@ -18,18 +18,13 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
+#include "imfs.h"
+
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
-
-#include <rtems.h>
-#include <rtems/libio.h>
-#include "imfs.h"
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
#define MEMFILE_STATIC
@@ -86,8 +81,8 @@ void memfile_free_block(
int memfile_open(
rtems_libio_t *iop,
const char *pathname,
- uint32_t flag,
- uint32_t mode
+ int oflag,
+ mode_t mode
)
{
IMFS_jnode_t *the_jnode;
diff --git a/cpukit/libfs/src/imfs/miniimfs_init.c b/cpukit/libfs/src/imfs/miniimfs_init.c
index b43a5318e8..a4db968e3c 100644
--- a/cpukit/libfs/src/imfs/miniimfs_init.c
+++ b/cpukit/libfs/src/imfs/miniimfs_init.c
@@ -18,28 +18,29 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <rtems/libio_.h>
-
#include "imfs.h"
static const rtems_filesystem_operations_table miniIMFS_ops = {
- .evalpath_h = IMFS_eval_path,
- .evalformake_h = IMFS_evaluate_for_make,
+ .lock_h = rtems_filesystem_default_lock,
+ .unlock_h = rtems_filesystem_default_unlock,
+ .eval_path_h = IMFS_eval_path,
.link_h = rtems_filesystem_default_link,
- .unlink_h = rtems_filesystem_default_unlink,
+ .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
.node_type_h = IMFS_node_type,
.mknod_h = IMFS_mknod,
+ .rmnod_h = IMFS_rmnod,
+ .fchmod_h = rtems_filesystem_default_fchmod,
.chown_h = rtems_filesystem_default_chown,
+ .clonenod_h = rtems_filesystem_default_clonenode,
.freenod_h = rtems_filesystem_default_freenode,
.mount_h = IMFS_mount,
.fsmount_me_h = miniIMFS_initialize,
.unmount_h = rtems_filesystem_default_unmount,
- .fsunmount_me_h = rtems_filesystem_default_unmount,
+ .fsunmount_me_h = rtems_filesystem_default_fsunmount,
.utime_h = rtems_filesystem_default_utime,
- .eval_link_h = rtems_filesystem_default_evaluate_link,
.symlink_h = rtems_filesystem_default_symlink,
.readlink_h = rtems_filesystem_default_readlink,
.rename_h = rtems_filesystem_default_rename,
@@ -54,8 +55,7 @@ int miniIMFS_initialize(
return IMFS_initialize_support(
mt_entry,
&miniIMFS_ops,
- &rtems_filesystem_handlers_default, /* for memfiles */
- &rtems_filesystem_handlers_default, /* for directories */
+ &rtems_filesystem_handlers_default, /* for links */
&rtems_filesystem_handlers_default /* for fifos */
);
}
diff --git a/cpukit/libfs/src/nfsclient/src/librtemsNfs.h b/cpukit/libfs/src/nfsclient/src/librtemsNfs.h
index fc17d1de7f..4e8247ced0 100644
--- a/cpukit/libfs/src/nfsclient/src/librtemsNfs.h
+++ b/cpukit/libfs/src/nfsclient/src/librtemsNfs.h
@@ -123,7 +123,7 @@ rpcUdpCleanup(void);
* Supply zero values to have the
* driver chose reasonable defaults.
*/
-int
+void
nfsInit(int smallPoolDepth, int bigPoolDepth);
/* Driver cleanup code
diff --git a/cpukit/libfs/src/nfsclient/src/nfs.c b/cpukit/libfs/src/nfsclient/src/nfs.c
index 80e757cbdf..ee1185367f 100644
--- a/cpukit/libfs/src/nfsclient/src/nfs.c
+++ b/cpukit/libfs/src/nfsclient/src/nfs.c
@@ -4,7 +4,12 @@
/* Author: Till Straumann <strauman@slac.stanford.edu> 2002 */
-/* Hacked on by others. */
+/*
+ * Hacked on by others.
+ *
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ */
/*
* Authorship
@@ -74,6 +79,7 @@
#include <mount_prot.h>
#include "rpcio.h"
+#include "librtemsNfs.h"
/* Configurable parameters */
@@ -201,6 +207,21 @@ static struct timeval _nfscalltimeout = { 10, 0 }; /* {secs, us } */
#define UNLOCK(s) do { rtems_semaphore_release((s)); \
} while (0)
+static inline char *
+nfs_dupname(const char *name, size_t namelen)
+{
+ char *dupname = malloc(namelen + 1);
+
+ if (dupname != NULL) {
+ memcpy(dupname, name, namelen);
+ dupname [namelen] = '\0';
+ } else {
+ errno = ENOMEM;
+ }
+
+ return dupname;
+}
+
/*****************************************
Types with Associated XDR Routines
*****************************************/
@@ -214,12 +235,6 @@ typedef struct strbuf {
u_int max;
} strbuf;
-static bool_t
-xdr_strbuf(XDR *xdrs, strbuf *obj)
-{
- return xdr_string(xdrs, &obj->buf, obj->max);
-}
-
/* Read 'readlink' results into a 'strbuf'.
* This is convenient as it avoids
* one extra step of copying / lenght
@@ -562,9 +577,9 @@ typedef struct NfsNodeRec_ {
*****************************************/
static ssize_t nfs_readlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- char *buf, /* OUT */
- size_t len
+ const rtems_filesystem_location_info_t *loc,
+ char *buf,
+ size_t len
);
static int updateAttr(NfsNode node, int force);
@@ -591,10 +606,10 @@ static int updateAttr(NfsNode node, int force);
static int
nfs_sattr(NfsNode node, sattr *arg, u_long mask);
-extern struct _rtems_filesystem_operations_table nfs_fs_ops;
-static struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers;
-static struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers;
-static struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers;
+extern const struct _rtems_filesystem_operations_table nfs_fs_ops;
+static const struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers;
+static const struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers;
+static const struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers;
static rtems_driver_address_table drvNfs;
int
@@ -603,64 +618,6 @@ nfsMountsShow(FILE*);
rtems_status_code
rtems_filesystem_resolve_location(char *buf, int len, rtems_filesystem_location_info_t *loc);
-
-/*****************************************
- Inline Routines
- *****************************************/
-
-
-/* * * * * * * * * * * * * * * * * *
- Trivial Operations on a NfsNode
- * * * * * * * * * * * * * * * * * */
-
-/* determine if a location 'l' is an NFS root node */
-static inline int
-locIsRoot(rtems_filesystem_location_info_t *l)
-{
-NfsNode me = (NfsNode) l->node_access;
-NfsNode r;
- r = (NfsNode)l->mt_entry->mt_fs_root.node_access;
- return SERP_ATTR(r).fileid == SERP_ATTR(me).fileid &&
- SERP_ATTR(r).fsid == SERP_ATTR(me).fsid;
-}
-
-/* determine if a location 'l' is an NFS node */
-static inline int
-locIsNfs(rtems_filesystem_location_info_t *l)
-{
- return l->ops == &nfs_fs_ops;
-}
-
-/* determine if two locations refer to the
- * same entity. We know that 'nfsloc' is a
- * location inside nfs. However, we needn't
- * know anything about 'anyloc'.
- */
-static inline int
-locAreEqual(
- rtems_filesystem_location_info_t *nfsloc,
- rtems_filesystem_location_info_t *anyloc
-)
-{
-NfsNode na = (NfsNode) nfsloc->node_access;
-NfsNode nb;
-
- if (!locIsNfs(anyloc))
- return 0;
-
- nb = (NfsNode) anyloc->node_access;
-
- if (na->nfs != nb->nfs)
- return 0;
-
- updateAttr(nb, 0);
-
- return SERP_ATTR(na).fileid == SERP_ATTR(nb).fileid &&
- SERP_ATTR(na).fsid == SERP_ATTR(nb).fsid;
-}
-
-
-
/*****************************************
Global Variables
*****************************************/
@@ -1326,409 +1283,229 @@ enum clnt_stat stat = RPC_FAILED;
RTEMS File System Operations for NFS
*****************************************/
-#if 0 /* for reference */
-
-struct rtems_filesystem_location_info_tt
-{
- void *node_access;
- rtems_filesystem_file_handlers_r *handlers;
- rtems_filesystem_operations_table *ops;
- rtems_filesystem_mount_table_entry_t *mt_entry;
-};
-
-#endif
-
-/*
- * Evaluate a path letting 'pathloc' travel along.
- *
- * The important semantics of this operation are:
- *
- * If this routine returns -1, the caller assumes
- * pathloc to be _invalid_ and hence it will not
- * invoke rtems_filesystem_freenode() on it.
- *
- * OTOH, if evalpath returns 0,
- * rtems_filesystem_freenode() will eventually be
- * called which results in our freeing the associated
- * NfsNode attached to node_access.
- *
- * Therefore, this routine will _always_ allocate
- * a NfsNode and pass it out to *pathloc (provided
- * that the evaluation succeeds).
- *
- * However, if the evaluation finds that it has to
- * step across FS boundaries (mount point or a symlink
- * pointing outside), the NfsNode is destroyed
- * before passing control to the new FS' evalpath_h()
- *
- */
-
-union nfs_evalpath_arg {
- int i;
- const char **c;
- };
-
-STATIC int nfs_do_evalpath(
- const char *pathname, /* IN */
- int pathnamelen, /* IN */
- union nfs_evalpath_arg *arg,
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- int forMake
+static bool nfs_is_directory(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg
)
{
-char *del = 0, *part;
-int e = 0;
-NfsNode node = pathloc->node_access;
-char *p = malloc(MAXPATHLEN+1);
-Nfs nfs = (Nfs)pathloc->mt_entry->fs_info;
-RpcUdpServer server = nfs->server;
-unsigned long flags;
-#if DEBUG & DEBUG_COUNT_NODES
-unsigned long niu,siu;
-#endif
+ bool is_dir = false;
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc(ctx);
+ NfsNode node = currentloc->node_access;
+ int force_update = 0;
- if ( !p ) {
- e = ENOMEM;
- goto cleanup;
+ if (updateAttr(node, force_update) == 0) {
+ is_dir = SERP_ATTR(node).type == NFDIR;
}
- memset(p, 0, MAXPATHLEN+1);
- memcpy(p, pathname, pathnamelen);
- LOCK(nfsGlob.lock);
- node = nfsNodeClone(node);
- UNLOCK(nfsGlob.lock);
-
- /* from here on, the NFS is protected from being unmounted
- * since the node refcount is > 1
- */
-
- /* clone the node */
- if ( !node ) {
- /* nodeClone sets errno */
- pathloc->node_access = 0;
- if ( ! (e = errno) ) {
- /* if we have no node, e must not be zero! */
- e = ENOMEM;
- }
- goto cleanup;
- }
-
- pathloc->node_access = node;
-
- /* Special case: the RTEMS filesystem code
- * may emit '..' on a regular file node to
- * find the parent directory :-(.
- * (eval.c: rtems_filesystem_evaluate_parent())
- * Try to catch this case here:
- */
- if ( NFDIR != SERP_ATTR(node).type && '.'==*p && '.'==*(p+1) ) {
- for ( part = p+2; '/'==*part; part++ )
- /* skip trailing '/' */;
- if ( !*part ) {
- /* this is it; back out dir and let them look up the dir itself... */
- memcpy( &SERP_FILE(node),
- &node->args.dir,
- sizeof(node->args.dir));
- *(p+1)=0;
- }
- }
-
- for (part=p; part && *part; part=del) {
-
- if ( NFLNK == SERP_ATTR(node).type ) {
- /* follow midpath link */
- char *b = malloc(NFS_MAXPATHLEN+1);
- int l;
-
- if (!b) {
- e = ENOMEM;
- goto cleanup;
- }
- if (nfs_readlink(pathloc, b, NFS_MAXPATHLEN+1)) {
- free(b);
- e = errno;
- goto cleanup;
- }
-
- /* prepend the link value to the rest of the path */
- if ( (l=strlen(b)) + strlen(part) + 1 > NFS_MAXPATHLEN ) {
- free(b);
- e = EINVAL;
- goto cleanup;
- }
- /* swap string buffers and reset delimiter */
- b[l++] = DELIM;
- strcpy(b+l,part);
- part = b;
- b = p;
- p = del = part;
-
- free(b);
-
- /* back up the directory filehandle (only necessary
- * if we don't back out to the root
- */
- if (! (DELIM == *part) ) {
- memcpy( &SERP_FILE(node),
- &node->args.dir,
- sizeof(node->args.dir));
-
- if (updateAttr(node, 1 /* force */)) {
- e = errno;
- goto cleanup;
- }
- }
- }
+ return is_dir;
+}
- /* find delimiter and eat /// sequences
- * (only if we don't restart at the root)
- */
- if ( DELIM != *part && (del = strchr(part, DELIM))) {
- do {
- *del++=0;
- } while (DELIM==*del);
- }
+static NfsNode nfs_search_in_directory(
+ Nfs nfs,
+ NfsNode node,
+ char *part
+)
+{
+ int rv;
- /* refuse to backup over the root */
- if ( 0==strcmp(part,UPDIR)
- && locAreEqual(pathloc, &rtems_filesystem_root) ) {
- part++;
- }
+ /* lookup one element */
+ SERP_ARGS(node).diroparg.name = part;
- /* cross mountpoint upwards */
- if ( (0==strcmp(part,UPDIR) && locIsRoot(pathloc)) /* cross mountpoint up */
- || DELIM == *part /* link starts at root */
- ) {
- int rval;
+ /* remember args / directory fh */
+ memcpy( &node->args, &SERP_FILE(node), sizeof(node->args));
#if DEBUG & DEBUG_EVALPATH
- fprintf(stderr,
- "Crossing mountpoint upwards\n");
+ fprintf(stderr,"Looking up '%s'\n",part);
#endif
- if (DELIM == *part) {
- *pathloc = rtems_filesystem_root;
- } else {
- *pathloc = pathloc->mt_entry->mt_point_node;
- /* re-append the rest of the path */
- if (del)
- while ( 0 == *--del )
- *del = DELIM;
- }
-
- nfsNodeDestroy(node);
-
-#if DEBUG & DEBUG_EVALPATH
- fprintf(stderr,
- "Re-evaluating '%s'\n",
- part);
-#endif
+ rv = nfscall(
+ nfs->server,
+ NFSPROC_LOOKUP,
+ (xdrproc_t) xdr_diropargs, &SERP_FILE(node),
+ (xdrproc_t) xdr_serporid, &node->serporid
+ );
- if (forMake)
- rval = pathloc->ops->evalformake_h(part, pathloc, arg->c);
- else
- rval = pathloc->ops->evalpath_h(part, strlen(part), arg->i, pathloc);
+ if (rv == 0 && node->serporid.status == NFS_OK) {
+ int force_update = 1;
- free(p);
- return rval;
+ rv = updateAttr(node, force_update);
+ if (rv != 0) {
+ node = NULL;
}
+ } else {
+ node = NULL;
+ }
- /* lookup one element */
- SERP_ARGS(node).diroparg.name = part;
-
- /* remember args / directory fh */
- memcpy( &node->args, &SERP_FILE(node), sizeof(node->args));
-
- /* don't lookup the item we want to create */
- if ( forMake && (!del || !*del) )
- break;
+ return node;
+}
-#if DEBUG & DEBUG_EVALPATH
- fprintf(stderr,"Looking up '%s'\n",part);
-#endif
+static void nfs_follow_link(rtems_filesystem_eval_path_context_t *ctx)
+{
+ const size_t len = NFS_MAXPATHLEN + 1;
+ char *link = malloc(len);
- if ( nfscall(server,
- NFSPROC_LOOKUP,
- (xdrproc_t)xdr_diropargs, &SERP_FILE(node),
- (xdrproc_t)xdr_serporid, &node->serporid) ||
- NFS_OK != (errno=node->serporid.status) ) {
- e = errno;
- goto cleanup;
- }
- node->age = nowSeconds();
+ if (link != NULL) {
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc(ctx);
+ ssize_t rv = nfs_readlink(currentloc, link, len);
-#if DEBUG & DEBUG_EVALPATH
- if (NFLNK == SERP_ATTR(node).type && del) {
- fprintf(stderr,
- "Following midpath link '%s'\n",
- part);
+ if (rv >= 0) {
+ rtems_filesystem_eval_path_recursive(ctx, link, (size_t) rv);
+ } else {
+ rtems_filesystem_eval_path_error(ctx, 0);
}
-#endif
+ free(link);
+ } else {
+ rtems_filesystem_eval_path_error(ctx, ENOMEM);
}
+}
- if (forMake) {
- /* remember the name - do this _before_ copying
- * the name to local storage; the caller expects a
- * pointer into pathloc
- */
- assert( node->args.name );
-
- *(arg->c) = pathname + (node->args.name - p);
-
-#if 0
- /* restore the directory node */
+static bool nfs_update_currentloc(
+ rtems_filesystem_eval_path_context_t *ctx,
+ Nfs nfs,
+ NfsNode node
+)
+{
+ bool ok = true;
+ rtems_filesystem_location_info_t *pathloc =
+ rtems_filesystem_eval_path_get_currentloc(ctx);
- memcpy( &SERP_FILE(node),
- &node->args.dir,
- sizeof(node->args.dir));
+ pathloc->node_access = node;
- if ( (nfscall(nfs->server,
- NFSPROC_GETATTR,
- (xdrproc_t)xdr_nfs_fh, &SERP_FILE(node),
- (xdrproc_t)xdr_attrstat, &node->serporid) && !errno && (errno = EIO)) ||
- (NFS_OK != (errno=node->serporid.status) ) ) {
- goto cleanup;
- }
-#endif
+ switch (SERP_ATTR(node).type) {
+ case NFDIR: pathloc->handlers = &nfs_dir_file_handlers; break;
+ case NFREG: pathloc->handlers = &nfs_file_file_handlers; break;
+ case NFLNK: pathloc->handlers = &nfs_link_file_handlers; break;
+ default: pathloc->handlers = &rtems_filesystem_handlers_default; break;
}
- if (locIsRoot(pathloc)) {
-
- /* stupid filesystem code has no 'op' for comparing nodes
- * but just compares the 'node_access' pointers.
- * Luckily, this is only done for comparing the root nodes.
- * Hence, we never give them a copy of the root but always
- * the root itself.
- */
- pathloc->node_access = pathloc->mt_entry->mt_fs_root.node_access;
- /* increment the 'in use' counter since we return one more
- * reference to the root node
- */
- rtems_interrupt_disable(flags);
- nfs->nodesInUse++;
- rtems_interrupt_enable(flags);
- nfsNodeDestroy(node);
-
-
- } else {
- switch (SERP_ATTR(node).type) {
- case NFDIR: pathloc->handlers = &nfs_dir_file_handlers; break;
- case NFREG: pathloc->handlers = &nfs_file_file_handlers; break;
- case NFLNK: pathloc->handlers = &nfs_link_file_handlers; break;
- default: pathloc->handlers = &rtems_filesystem_handlers_default; break;
- }
- pathloc->node_access = node;
-
- /* remember the name of this directory entry */
+ /* remember the name of this directory entry */
- if (node->args.name) {
- if (node->str) {
+ if (node->args.name) {
+ if (node->str) {
#if DEBUG & DEBUG_COUNT_NODES
- rtems_interrupt_disable(flags);
- nfs->stringsInUse--;
- rtems_interrupt_enable(flags);
+ rtems_interrupt_level flags;
+ rtems_interrupt_disable(flags);
+ nfs->stringsInUse--;
+ rtems_interrupt_enable(flags);
#endif
- free(node->str);
- }
- node->args.name = node->str = strdup(node->args.name);
- if (!node->str) {
- e = ENOMEM;
- goto cleanup;
- }
-
+ free(node->str);
+ }
+ node->args.name = node->str = strdup(node->args.name);
+ if (node->str != NULL) {
#if DEBUG & DEBUG_COUNT_NODES
+ rtems_interrupt_level flags;
rtems_interrupt_disable(flags);
nfs->stringsInUse++;
rtems_interrupt_enable(flags);
#endif
+ } else {
+ rtems_filesystem_eval_path_error(ctx, ENOMEM);
+ ok = false;
}
-
}
- node = 0;
- e = 0;
+ return ok;
+}
-cleanup:
- free(p);
-#if DEBUG & DEBUG_COUNT_NODES
- /* cache counters; nfs may be unmounted by other thread after the last
- * node is destroyed
- */
- niu = nfs->nodesInUse;
- siu = nfs->stringsInUse;
-#endif
- if (node) {
- nfsNodeDestroy(node);
- pathloc->node_access = 0;
- }
-#if DEBUG & DEBUG_COUNT_NODES
- fprintf(stderr,
- "leaving evalpath, in use count is %i nodes, %i strings\n",
- niu,siu);
-#endif
- if (e) {
-#if DEBUG & DEBUG_EVALPATH
- perror("Evalpath");
-#endif
- rtems_set_errno_and_return_minus_one(e);
+static rtems_filesystem_eval_path_generic_status nfs_eval_part(
+ rtems_filesystem_eval_path_context_t *ctx,
+ char *part
+)
+{
+ rtems_filesystem_eval_path_generic_status status =
+ RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc(ctx);
+ Nfs nfs = currentloc->mt_entry->fs_info;
+ NfsNode dir = currentloc->node_access;
+ NfsNode entry = nfs_search_in_directory(nfs, dir, part);
+
+ if (entry != NULL) {
+ rtems_filesystem_eval_path_clear_token(ctx);
+
+ if (nfs_update_currentloc(ctx, nfs, entry)) {
+ int eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
+ bool follow_sym_link = (eval_flags & RTEMS_LIBIO_FOLLOW_SYM_LINK) != 0;
+ bool terminal = !rtems_filesystem_eval_path_has_path( ctx );
+
+ if (SERP_ATTR(entry).type == NFLNK && (follow_sym_link || !terminal)) {
+ nfs_follow_link(ctx);
+ } else if (!terminal) {
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
+ }
+ }
} else {
- return 0;
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
}
+
+ return status;
}
-/* MANDATORY; may set errno=ENOSYS and return -1 */
-static int nfs_evalformake(
- const char *path, /* IN */
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- const char **pname /* OUT */
+static rtems_filesystem_eval_path_generic_status nfs_eval_token(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg,
+ const char *token,
+ size_t tokenlen
)
{
- union nfs_evalpath_arg args;
- args.c = pname;
-
- return nfs_do_evalpath(path, strlen(path), &args, pathloc, 1 /*forMake*/);
+ rtems_filesystem_eval_path_generic_status status =
+ RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
+
+ if (rtems_filesystem_is_current_directory(token, tokenlen)) {
+ rtems_filesystem_eval_path_clear_token(ctx);
+ if (rtems_filesystem_eval_path_has_path(ctx)) {
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
+ }
+ } else {
+ char *part = nfs_dupname(token, tokenlen);
+
+ if (part != NULL) {
+ status = nfs_eval_part(ctx, part);
+ free(part);
+ } else {
+ rtems_filesystem_eval_path_error(ctx, ENOMEM);
+ }
+ }
+
+ return status;
}
-static int nfs_evalpath(
- const char *path, /* IN */
- size_t pathlen, /* IN */
- int flags, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
-)
+static const rtems_filesystem_eval_path_generic_config nfs_eval_config = {
+ .is_directory = nfs_is_directory,
+ .eval_token = nfs_eval_token
+};
+
+static void nfs_eval_path(rtems_filesystem_eval_path_context_t *ctx)
{
- union nfs_evalpath_arg args;
- args.i = flags;
- return nfs_do_evalpath(path, pathlen, &args, pathloc, 0 /*not forMake*/);
+ rtems_filesystem_eval_path_generic(ctx, NULL, &nfs_eval_config);
}
-
/* create a hard link */
static int nfs_link(
- rtems_filesystem_location_info_t *to_loc, /* IN */
- rtems_filesystem_location_info_t *parent_loc, /* IN */
- const char *name /* IN */
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *targetloc,
+ const char *name,
+ size_t namelen
)
{
+int rv = 0;
NfsNode pNode;
nfsstat status;
-NfsNode tNode = to_loc->node_access;
+NfsNode tNode = targetloc->node_access;
+char *dupname;
+
+ dupname = nfs_dupname(name, namelen);
+ if (dupname == NULL)
+ return -1;
#if DEBUG & DEBUG_SYSCALLS
- fprintf(stderr,"Creating link '%s'\n",name);
+ fprintf(stderr,"Creating link '%s'\n",dupname);
#endif
- if ( !locIsNfs(parent_loc) ) {
- errno = EXDEV;
- return -1;
- }
-
- pNode = parent_loc->node_access;
- if ( tNode->nfs != pNode->nfs ) {
- errno = EXDEV;
- return -1;
- }
memcpy(&SERP_ARGS(tNode).linkarg.to.dir,
&SERP_FILE(pNode),
sizeof(SERP_FILE(pNode)));
@@ -1744,16 +1521,18 @@ NfsNode tNode = to_loc->node_access;
#if DEBUG & DEBUG_SYSCALLS
perror("nfs_link");
#endif
- return -1;
+ rv = -1;
}
- return 0;
+ free(dupname);
+
+ return rv;
}
static int nfs_do_unlink(
- rtems_filesystem_location_info_t *parent_loc,/* IN */
- rtems_filesystem_location_info_t *loc, /* IN */
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *loc,
int proc
)
{
@@ -1791,18 +1570,10 @@ char *name = NFSPROC_REMOVE == proc ?
return 0;
}
-static int nfs_unlink(
- rtems_filesystem_location_info_t *parent_loc, /* IN */
- rtems_filesystem_location_info_t *loc /* IN */
-)
-{
- return nfs_do_unlink(parent_loc, loc, NFSPROC_REMOVE);
-}
-
static int nfs_chown(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- uid_t owner, /* IN */
- gid_t group /* IN */
+ const rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
)
{
sattr arg;
@@ -1814,14 +1585,27 @@ sattr arg;
}
+static int nfs_clonenode(rtems_filesystem_location_info_t *loc)
+{
+ NfsNode node = loc->node_access;
+
+ LOCK(nfsGlob.lock);
+ node = nfsNodeClone(node);
+ UNLOCK(nfsGlob.lock);
+
+ loc->node_access = node;
+
+ return node != NULL ? 0 : -1;
+}
+
/* Cleanup the FS private info attached to pathloc->node_access */
-static int nfs_freenode(
- rtems_filesystem_location_info_t *pathloc /* IN */
+static void nfs_freenode(
+ const rtems_filesystem_location_info_t *pathloc /* IN */
)
{
+#if DEBUG & DEBUG_COUNT_NODES
Nfs nfs = ((NfsNode)pathloc->node_access)->nfs;
-#if DEBUG & DEBUG_COUNT_NODES
/* print counts at entry where they are > 0 so 'nfs' is safe from being destroyed
* and there's no race condition
*/
@@ -1831,22 +1615,7 @@ Nfs nfs = ((NfsNode)pathloc->node_access)->nfs;
nfs->stringsInUse);
#endif
- /* never destroy the root node; it is released by the unmount
- * code
- */
- if (locIsRoot(pathloc)) {
- unsigned long flags;
- /* just adjust the references to the root node but
- * don't really release it
- */
- rtems_interrupt_disable(flags);
- nfs->nodesInUse--;
- rtems_interrupt_enable(flags);
- } else {
- nfsNodeDestroy(pathloc->node_access);
- pathloc->node_access = 0;
- }
- return 0;
+ nfsNodeDestroy(pathloc->node_access);
}
/* NOTE/TODO: mounting on top of NFS is not currently supported
@@ -1982,12 +1751,12 @@ char *path = mt_entry->dev;
/* looks good so far */
- mt_entry->mt_fs_root.node_access = rootNode;
+ mt_entry->mt_fs_root->location.node_access = rootNode;
rootNode = 0;
- mt_entry->mt_fs_root.ops = &nfs_fs_ops;
- mt_entry->mt_fs_root.handlers = &nfs_dir_file_handlers;
+ mt_entry->mt_fs_root->location.ops = &nfs_fs_ops;
+ mt_entry->mt_fs_root->location.handlers = &nfs_dir_file_handlers;
mt_entry->pathconf_limits_and_options = nfs_limits_and_options;
LOCK(nfsGlob.llock);
@@ -2016,7 +1785,7 @@ cleanup:
}
/* This op is called when they try to unmount THIS fs */
-STATIC int nfs_fsunmount_me(
+STATIC void nfs_fsunmount_me(
rtems_filesystem_mount_table_entry_t *mt_entry /* in */
)
{
@@ -2035,7 +1804,8 @@ LOCK(nfsGlob.llock);
fprintf(stderr,
"Refuse to unmount; there are still %i nodes in use (1 used by us)\n",
nodesInUse);
- rtems_set_errno_and_return_minus_one(EBUSY);
+ rtems_fatal_error_occurred(0xdeadbeef);
+ return;
}
status = buildIpAddr(&uid, &gid, 0, &saddr, &path);
@@ -2052,20 +1822,17 @@ LOCK(nfsGlob.llock);
if (stat) {
UNLOCK(nfsGlob.llock);
fprintf(stderr,"NFS UMOUNT -- %s\n", clnt_sperrno(stat));
- errno = EIO;
- return -1;
+ return;
}
- nfsNodeDestroy(mt_entry->mt_fs_root.node_access);
- mt_entry->mt_fs_root.node_access = 0;
+ nfsNodeDestroy(mt_entry->mt_fs_root->location.node_access);
+ mt_entry->mt_fs_root->location.node_access = 0;
nfsDestroy(mt_entry->fs_info);
mt_entry->fs_info = 0;
nfsGlob.num_mounted_fs--;
UNLOCK(nfsGlob.llock);
-
- return 0;
}
/* OPTIONAL; may be NULL - BUT: CAUTION; mount() doesn't check
@@ -2073,10 +1840,10 @@ UNLOCK(nfsGlob.llock);
* //NOTE: (10/25/2002) patch submitted and probably applied
*/
static rtems_filesystem_node_types_t nfs_node_type(
- rtems_filesystem_location_info_t *pathloc /* in */
+ const rtems_filesystem_location_info_t *loc
)
{
-NfsNode node = pathloc->node_access;
+NfsNode node = loc->node_access;
if (updateAttr(node, 0 /* only if old */))
return -1;
@@ -2104,28 +1871,35 @@ NfsNode node = pathloc->node_access;
}
static int nfs_mknod(
- const char *path, /* IN */
- mode_t mode, /* IN */
- dev_t dev, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
)
{
+int rv = 0;
struct timeval now;
diropres res;
-NfsNode node = pathloc->node_access;
+NfsNode node = parentloc->node_access;
mode_t type = S_IFMT & mode;
+char *dupname;
if (type != S_IFDIR && type != S_IFREG)
rtems_set_errno_and_return_minus_one(ENOTSUP);
+ dupname = nfs_dupname(name, namelen);
+ if (dupname == NULL)
+ return -1;
+
#if DEBUG & DEBUG_SYSCALLS
- fprintf(stderr,"nfs_mknod: creating %s\n", path);
+ fprintf(stderr,"nfs_mknod: creating %s\n", dupname);
#endif
rtems_clock_get_tod_timeval(&now);
- SERP_ARGS(node).createarg.name = (filename)path;
+ SERP_ARGS(node).createarg.name = dupname;
SERP_ARGS(node).createarg.attributes.mode = mode;
/* TODO: either use our uid or use the Nfs credentials */
SERP_ARGS(node).createarg.attributes.uid = 0;
@@ -2144,16 +1918,40 @@ mode_t type = S_IFMT & mode;
#if DEBUG & DEBUG_SYSCALLS
perror("nfs_mknod");
#endif
- return -1;
+ rv = -1;
}
- return 0;
+ free(dupname);
+
+ return rv;
+}
+
+static int nfs_rmnod(
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *loc
+)
+{
+ int rv = 0;
+ NfsNode node = loc->node_access;
+ int force_update = 0;
+
+ if (updateAttr(node, force_update) == 0) {
+ int proc = SERP_ATTR(node).type == NFDIR
+ ? NFSPROC_RMDIR
+ : NFSPROC_REMOVE;
+
+ rv = nfs_do_unlink(parentloc, loc, proc);
+ } else {
+ rv = -1;
+ }
+
+ return rv;
}
static int nfs_utime(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- time_t actime, /* IN */
- time_t modtime /* IN */
+ const rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
)
{
sattr arg;
@@ -2168,24 +1966,30 @@ sattr arg;
}
static int nfs_symlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- const char *link_name, /* IN */
- const char *node_name
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ const char *target
)
{
+int rv = 0;
struct timeval now;
nfsstat status;
-NfsNode node = loc->node_access;
+NfsNode node = parentloc->node_access;
+char *dupname;
+ dupname = nfs_dupname(name, namelen);
+ if (dupname == NULL)
+ return -1;
#if DEBUG & DEBUG_SYSCALLS
- fprintf(stderr,"nfs_symlink: creating %s -> %s\n", link_name, node_name);
+ fprintf(stderr,"nfs_symlink: creating %s -> %s\n", dupname, target);
#endif
rtems_clock_get_tod_timeval(&now);
- SERP_ARGS(node).symlinkarg.name = (filename)link_name;
- SERP_ARGS(node).symlinkarg.to = (nfspath) node_name;
+ SERP_ARGS(node).symlinkarg.name = dupname;
+ SERP_ARGS(node).symlinkarg.to = (nfspath) target;
SERP_ARGS(node).symlinkarg.attributes.mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
/* TODO */
@@ -2205,243 +2009,103 @@ NfsNode node = loc->node_access;
#if DEBUG & DEBUG_SYSCALLS
perror("nfs_symlink");
#endif
- return -1;
+ rv = -1;
}
- return 0;
+ free(dupname);
+
+ return rv;
}
-static int nfs_do_readlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- strbuf *psbuf /* IN/OUT */
+static ssize_t nfs_readlink(
+ const rtems_filesystem_location_info_t *loc,
+ char *buf,
+ size_t len
)
{
-NfsNode node = loc->node_access;
-Nfs nfs = node->nfs;
-readlinkres_strbuf rr;
-int wasAlloced;
-int rval;
-
- rr.strbuf = *psbuf;
+ NfsNode node = loc->node_access;
+ Nfs nfs = node->nfs;
+ readlinkres_strbuf rr;
- wasAlloced = (0 == psbuf->buf);
+ rr.strbuf.buf = buf;
+ rr.strbuf.max = len - 1;
- if ( (rval = nfscall(nfs->server,
+ if ( nfscall(nfs->server,
NFSPROC_READLINK,
(xdrproc_t)xdr_nfs_fh, &SERP_FILE(node),
- (xdrproc_t)xdr_readlinkres_strbuf, &rr)) ) {
- if (wasAlloced)
- xdr_free( (xdrproc_t)xdr_strbuf, (caddr_t)&rr.strbuf );
- }
-
-
- if (NFS_OK != rr.status) {
- if (wasAlloced)
- xdr_free( (xdrproc_t)xdr_strbuf, (caddr_t)&rr.strbuf );
- rtems_set_errno_and_return_minus_one(rr.status);
+ (xdrproc_t)xdr_readlinkres_strbuf, &rr)
+ || (NFS_OK != (errno = rr.status)) ) {
+#if DEBUG & DEBUG_SYSCALLS
+ perror("nfs_readlink");
+#endif
+ return -1;
}
- *psbuf = rr.strbuf;
-
- return 0;
+ return (ssize_t) strlen(rr.strbuf.buf);
}
-static ssize_t nfs_readlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- char *buf, /* OUT */
- size_t len
-)
+static void nfs_lock(rtems_filesystem_mount_table_entry_t *mt_entry)
{
-strbuf sbuf;
- sbuf.buf = buf;
- sbuf.max = len;
-
- return nfs_do_readlink(loc, &sbuf);
}
-/* The semantics of this routine are:
- *
- * The caller submits a valid pathloc, i.e. it has
- * an NfsNode attached to node_access.
- * On return, pathloc points to the target node which
- * may or may not be an NFS node.
- * Hence, the original NFS node is released in either
- * case:
- * - link evaluation fails; pathloc points to no valid node
- * - link evaluation success; pathloc points to a new valid
- * node. If it's an NFS node, a new NfsNode will be attached
- * to node_access...
- */
-
-#define LINKVAL_BUFLEN (MAXPATHLEN+1)
-#define RVAL_ERR_BUT_DONT_FREENODE (-1)
-#define RVAL_ERR_AND_DO_FREENODE ( 1)
-#define RVAL_OK ( 0)
+static void nfs_unlock(rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+}
-static int nfs_eval_link(
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- int flags /* IN */
+static bool nfs_are_nodes_equal(
+ const rtems_filesystem_location_info_t *a,
+ const rtems_filesystem_location_info_t *b
)
{
-rtems_filesystem_node_types_t type;
-char *buf = malloc(LINKVAL_BUFLEN);
-int rval = RVAL_ERR_AND_DO_FREENODE;
+ bool equal = false;
+ NfsNode na = a->node_access;
- if (!buf) {
- errno = ENOMEM;
- goto cleanup;
- }
-
- /* in this loop, we must not use NFS specific ops as we might
- * step out of our FS during the process...
- * This algorithm should actually be performed by the
- * generic's evaluate_path routine :-(
- *
- * Unfortunately, there is no way of finding the
- * directory node who contains 'pathloc', however :-(
- */
- do {
- /* assume the generics have verified 'pathloc' to be
- * a link...
- */
- if ( !pathloc->ops->readlink_h ) {
- errno = ENOTSUP;
- goto cleanup;
- }
-
- if ( pathloc->ops->readlink_h(pathloc, buf, LINKVAL_BUFLEN) ) {
- goto cleanup;
- }
-
-#if DEBUG & DEBUG_EVALPATH
- fprintf(stderr, "link value is '%s'\n", buf);
-#endif
-
- /* is the link value an absolute path ? */
- if ( DELIM != *buf ) {
- /* NO; a relative path */
-
- /* we must backup to the link's directory - we
- * know only how to do that for NFS, however.
- * In this special case, we can avoid recursion.
- * Otherwise (i.e. if the link is on another FS),
- * we must step into its eval_link_h().
- */
- if (locIsNfs(pathloc)) {
- NfsNode node = pathloc->node_access;
- int err;
-
- memcpy( &SERP_FILE(node),
- &node->args.dir,
- sizeof(node->args.dir) );
-
- if (updateAttr(node, 1 /* force */))
- goto cleanup;
-
- if (SERP_ATTR(node).type != NFDIR) {
- errno = ENOTDIR;
- goto cleanup;
- }
-
- pathloc->handlers = &nfs_dir_file_handlers;
-
- err = nfs_evalpath(buf, strlen(buf), flags, pathloc);
-
- /* according to its semantics,
- * nfs_evalpath cloned the node attached
- * to pathloc. Hence we have to
- * release the old one (referring to
- * the link; the new clone has been
- * updated and refers to the link _value_).
- */
- nfsNodeDestroy(node);
-
- if (err) {
- /* nfs_evalpath has set errno;
- * pathloc->node_access has no
- * valid node attached in this case
- */
- rval = RVAL_ERR_BUT_DONT_FREENODE;
- goto cleanup;
- }
-
- } else {
- if ( ! pathloc->ops->eval_link_h ) {
- errno = ENOTSUP;
- goto cleanup;
- }
- if (!pathloc->ops->eval_link_h(pathloc, flags)) {
- /* FS is responsible for freeing its pathloc->node_access
- * if necessary
- */
- rval = RVAL_ERR_BUT_DONT_FREENODE;
- goto cleanup;
- }
- }
- } else {
- /* link points to an absolute path '/xxx' */
-
- /* release this node; filesystem_evaluate_path() will
- * lookup a new one.
- */
- rtems_filesystem_freenode(pathloc);
-
- if (rtems_filesystem_evaluate_path(buf, strlen(buf), flags, pathloc, 1)) {
- /* If evalpath fails then there is no valid node
- * attached to pathloc; hence we must not attempt
- * to free the node
- */
- rval = RVAL_ERR_BUT_DONT_FREENODE;
- goto cleanup;
- }
- }
+ if (updateAttr(na, 0) == 0) {
+ NfsNode nb = b->node_access;
- if ( !pathloc->ops->node_type_h ) {
- errno = ENOTSUP;
- goto cleanup;
+ if (updateAttr(nb, 0) == 0) {
+ equal = SERP_ATTR(na).fileid == SERP_ATTR(nb).fileid
+ && SERP_ATTR(na).fsid == SERP_ATTR(nb).fsid;
}
-
- type = pathloc->ops->node_type_h(pathloc);
-
-
- /* I dont know what to do about hard links */
- } while ( RTEMS_FILESYSTEM_SYM_LINK == type );
-
- rval = RVAL_OK;
-
-cleanup:
-
- free(buf);
-
- if (RVAL_ERR_AND_DO_FREENODE == rval) {
- rtems_filesystem_freenode(pathloc);
- return -1;
}
- return rval;
+ return equal;
}
+static int nfs_fchmod(
+ const rtems_filesystem_location_info_t *loc,
+ mode_t mode
+)
+{
+sattr arg;
+
+ arg.mode = mode;
+ return nfs_sattr(loc->node_access, &arg, SATTR_MODE);
-struct _rtems_filesystem_operations_table nfs_fs_ops = {
- nfs_evalpath, /* MANDATORY */
- nfs_evalformake, /* MANDATORY; may set errno=ENOSYS and return -1 */
- nfs_link, /* OPTIONAL; may be defaulted */
- nfs_unlink, /* OPTIONAL; may be defaulted */
- nfs_node_type, /* OPTIONAL; may be defaulted; BUG in mount - no test!! */
- nfs_mknod, /* OPTIONAL; may be defaulted */
- nfs_chown, /* OPTIONAL; may be defaulted */
- nfs_freenode, /* OPTIONAL; may be defaulted; (release node_access) */
- rtems_filesystem_default_mount,
- rtems_nfs_initialize, /* OPTIONAL; may be defaulted -- not used anymore */
- rtems_filesystem_default_unmount,
- nfs_fsunmount_me, /* OPTIONAL; may be defaulted */
- nfs_utime, /* OPTIONAL; may be defaulted */
- nfs_eval_link, /* OPTIONAL; may be defaulted */
- nfs_symlink, /* OPTIONAL; may be defaulted */
- nfs_readlink, /* OPTIONAL; may be defaulted */
- rtems_filesystem_default_rename, /* OPTIONAL; may be defaulted */
- rtems_filesystem_default_statvfs /* OPTIONAL; may be defaulted */
+}
+const struct _rtems_filesystem_operations_table nfs_fs_ops = {
+ .lock_h = nfs_lock,
+ .unlock_h = nfs_unlock,
+ .eval_path_h = nfs_eval_path,
+ .link_h = nfs_link,
+ .are_nodes_equal_h = nfs_are_nodes_equal,
+ .node_type_h = nfs_node_type,
+ .mknod_h = nfs_mknod,
+ .rmnod_h = nfs_rmnod,
+ .fchmod_h = nfs_fchmod,
+ .chown_h = nfs_chown,
+ .clonenod_h = nfs_clonenode,
+ .freenod_h = nfs_freenode,
+ .mount_h = rtems_filesystem_default_mount,
+ .fsmount_me_h = rtems_nfs_initialize,
+ .unmount_h = rtems_filesystem_default_unmount,
+ .fsunmount_me_h = nfs_fsunmount_me,
+ .utime_h = nfs_utime,
+ .symlink_h = nfs_symlink,
+ .readlink_h = nfs_readlink,
+ .rename_h = rtems_filesystem_default_rename,
+ .statvfs_h = rtems_filesystem_default_statvfs
};
/*****************************************
@@ -2472,8 +2136,8 @@ struct _rtems_filesystem_operations_table nfs_fs_ops = {
static int nfs_file_open(
rtems_libio_t *iop,
const char *pathname,
- uint32_t flag,
- uint32_t mode
+ int oflag,
+ mode_t mode
)
{
return 0;
@@ -2487,8 +2151,8 @@ static int nfs_file_open(
static int nfs_dir_open(
rtems_libio_t *iop,
const char *pathname,
- uint32_t flag,
- uint32_t mode
+ int oflag,
+ mode_t mode
)
{
NfsNode node = iop->pathinfo.node_access;
@@ -2796,8 +2460,8 @@ struct stat
/* common for file/dir/link */
static int nfs_fstat(
- rtems_filesystem_location_info_t *loc,
- struct stat *buf
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *buf
)
{
NfsNode node = loc->node_access;
@@ -2939,20 +2603,6 @@ u_int mode;
return 0;
}
-
-/* common for file/dir/link */
-static int nfs_fchmod(
- rtems_filesystem_location_info_t *loc,
- mode_t mode
-)
-{
-sattr arg;
-
- arg.mode = mode;
- return nfs_sattr(loc->node_access, &arg, SATTR_MODE);
-
-}
-
/* just set the size attribute to 'length'
* the server will take care of the rest :-)
*/
@@ -2973,71 +2623,52 @@ sattr arg;
SATTR_SIZE);
}
-/* files and symlinks are removed
- * by the common nfs_unlink() routine.
- * NFS has a different NFSPROC_RMDIR
- * call, though...
- */
-static int nfs_dir_rmnod(
- rtems_filesystem_location_info_t *parentpathloc, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN */
-)
-{
- return nfs_do_unlink(parentpathloc, pathloc, NFSPROC_RMDIR);
-}
-
/* the file handlers table */
-static
+static const
struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers = {
- nfs_file_open, /* OPTIONAL; may be defaulted */
- nfs_file_close, /* OPTIONAL; may be defaulted */
- nfs_file_read, /* OPTIONAL; may be defaulted */
- nfs_file_write, /* OPTIONAL; may be defaulted */
- rtems_filesystem_default_ioctl,
- nfs_file_lseek, /* OPTIONAL; may be defaulted */
- nfs_fstat, /* OPTIONAL; may be defaulted */
- nfs_fchmod, /* OPTIONAL; may be defaulted */
- nfs_file_ftruncate, /* OPTIONAL; may be defaulted */
- rtems_filesystem_default_fsync,
- rtems_filesystem_default_fdatasync,
- rtems_filesystem_default_fcntl,
- nfs_unlink, /* OPTIONAL; may be defaulted */
+ .open_h = nfs_file_open,
+ .close_h = nfs_file_close,
+ .read_h = nfs_file_read,
+ .write_h = nfs_file_write,
+ .ioctl_h = rtems_filesystem_default_ioctl,
+ .lseek_h = nfs_file_lseek,
+ .fstat_h = nfs_fstat,
+ .ftruncate_h = nfs_file_ftruncate,
+ .fsync_h = rtems_filesystem_default_fsync,
+ .fdatasync_h = rtems_filesystem_default_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl
};
/* the directory handlers table */
-static
+static const
struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers = {
- nfs_dir_open, /* OPTIONAL; may be defaulted */
- nfs_dir_close, /* OPTIONAL; may be defaulted */
- nfs_dir_read, /* OPTIONAL; may be defaulted */
- rtems_filesystem_default_write,
- rtems_filesystem_default_ioctl,
- nfs_dir_lseek, /* OPTIONAL; may be defaulted */
- nfs_fstat, /* OPTIONAL; may be defaulted */
- nfs_fchmod, /* OPTIONAL; may be defaulted */
- rtems_filesystem_default_ftruncate,
- rtems_filesystem_default_fsync,
- rtems_filesystem_default_fdatasync,
- rtems_filesystem_default_fcntl,
- nfs_dir_rmnod, /* OPTIONAL; may be defaulted */
+ .open_h = nfs_dir_open,
+ .close_h = nfs_dir_close,
+ .read_h = nfs_dir_read,
+ .write_h = rtems_filesystem_default_write,
+ .ioctl_h = rtems_filesystem_default_ioctl,
+ .lseek_h = nfs_dir_lseek,
+ .fstat_h = nfs_fstat,
+ .ftruncate_h = rtems_filesystem_default_ftruncate_directory,
+ .fsync_h = rtems_filesystem_default_fsync,
+ .fdatasync_h = rtems_filesystem_default_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl
};
/* the link handlers table */
-static
+static const
struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers = {
- rtems_filesystem_default_open,
- rtems_filesystem_default_close,
- rtems_filesystem_default_read,
- rtems_filesystem_default_write,
- rtems_filesystem_default_ioctl,
- rtems_filesystem_default_lseek,
- nfs_fstat, /* OPTIONAL; may be defaulted */
- nfs_fchmod, /* OPTIONAL; may be defaulted */
- rtems_filesystem_default_ftruncate,
- rtems_filesystem_default_fsync,
- rtems_filesystem_default_fdatasync,
- rtems_filesystem_default_fcntl,
- nfs_unlink, /* OPTIONAL; may be defaulted */
+ .open_h = rtems_filesystem_default_open,
+ .close_h = rtems_filesystem_default_close,
+ .read_h = rtems_filesystem_default_read,
+ .write_h = rtems_filesystem_default_write,
+ .ioctl_h = rtems_filesystem_default_ioctl,
+ .lseek_h = rtems_filesystem_default_lseek,
+ .fstat_h = nfs_fstat,
+ .ftruncate_h = rtems_filesystem_default_ftruncate,
+ .fsync_h = rtems_filesystem_default_fsync,
+ .fdatasync_h = rtems_filesystem_default_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl
};
/* we need a dummy driver entry table to get a
@@ -3096,7 +2727,7 @@ Nfs nfs;
for (nfs = nfsGlob.mounted_fs; nfs; nfs=nfs->next) {
fprintf(f,"%s on ", nfs->mt_entry->dev);
- if (rtems_filesystem_resolve_location(mntpt, MAXPATHLEN, &nfs->mt_entry->mt_fs_root))
+ if (rtems_filesystem_resolve_location(mntpt, MAXPATHLEN, &nfs->mt_entry->mt_fs_root->location))
fprintf(f,"<UNABLE TO LOOKUP MOUNTPOINT>\n");
else
fprintf(f,"%s\n",mntpt);
@@ -3236,15 +2867,15 @@ rtems_filesystem_location_info_t old;
/* IMPORTANT: let the helper task have its own libio environment (i.e. cwd) */
if (RTEMS_SUCCESSFUL == (rpa->status = rtems_libio_set_private_env())) {
- old = rtems_filesystem_current;
+ old = rtems_filesystem_current->location;
- rtems_filesystem_current = *(rpa->loc);
+ rtems_filesystem_current->location = *(rpa->loc);
if ( !getcwd(rpa->buf, rpa->len) )
rpa->status = RTEMS_UNSATISFIED;
/* must restore the cwd because 'freenode' will be called on it */
- rtems_filesystem_current = old;
+ rtems_filesystem_current->location = old;
}
rtems_semaphore_release(rpa->sync);
rtems_task_delete(RTEMS_SELF);
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-dir.h b/cpukit/libfs/src/rfs/rtems-rfs-dir.h
index 6bbe6d6e18..3b8e7c4f06 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-dir.h
+++ b/cpukit/libfs/src/rfs/rtems-rfs-dir.h
@@ -29,47 +29,6 @@
#include <rtems/rfs/rtems-rfs-inode.h>
/**
- * The current directory string as held in directory lists.
- */
-#define RTEMS_RFS_CURRENT_DIR_STR "."
-
-/**
- * The size of the current directory.
- */
-#define RTEMS_RFS_CURRENT_DIR_SIZE (1)
-
-/**
- * Test if the path provided is a current directory.
- *
- * @param _p Pointer to the path string.
- * @return bool True if the path is a current directory.
- */
-#define rtems_rfs_current_dir(_p) \
- ((_p[0] == RTEMS_RFS_CURRENT_DIR_STR[0]) && \
- ((_p[1] == '\0') || rtems_filesystem_is_separator (_p[1])))
-
-/**
- * The parent directory string as held in directory lists.
- */
-#define RTEMS_RFS_PARENT_DIR_STR ".."
-
-/**
- * The size of the parent directory.
- */
-#define RTEMS_RFS_PARENT_DIR_SIZE (2)
-
-/**
- * Test if the path provided is a parent directory.
- *
- * @param _p Pointer to the path string.
- * @return bool True if the path is a parent directory.
- */
-#define rtems_rfs_parent_dir(_p) \
- ((_p[0] == RTEMS_RFS_PARENT_DIR_STR[0]) && \
- (_p[1] == RTEMS_RFS_PARENT_DIR_STR[1]) && \
- ((_p[2] == '\0') || rtems_filesystem_is_separator (_p[2])))
-
-/**
* Define the offsets of the fields of a directory entry.
*/
#define RTEMS_RFS_DIR_ENTRY_INO (0) /**< The ino offset in a directory
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-file.c b/cpukit/libfs/src/rfs/rtems-rfs-file.c
index d8a7335ea4..abd123da1b 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-file.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-file.c
@@ -31,7 +31,7 @@
int
rtems_rfs_file_open (rtems_rfs_file_system* fs,
rtems_rfs_ino ino,
- uint32_t flags,
+ int oflag,
rtems_rfs_file_handle** file)
{
rtems_rfs_file_handle* handle;
@@ -132,7 +132,7 @@ rtems_rfs_file_open (rtems_rfs_file_system* fs,
printf ("rtems-rfs: file-open: ino=%" PRId32 " share created\n", ino);
}
- handle->flags = flags;
+ handle->flags = oflag;
handle->shared = shared;
*file = handle;
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-file.h b/cpukit/libfs/src/rfs/rtems-rfs-file.h
index 284e6273d8..ecadb359bc 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-file.h
+++ b/cpukit/libfs/src/rfs/rtems-rfs-file.h
@@ -180,7 +180,7 @@ typedef struct _rtems_rfs_file_handle
/**
* Special flags that can be controlled by the fctrl call.
*/
- uint32_t flags;
+ int flags;
/**
* The buffer of data at the file's position.
@@ -298,7 +298,7 @@ typedef struct _rtems_rfs_file_handle
*/
int rtems_rfs_file_open (rtems_rfs_file_system* fs,
rtems_rfs_ino ino,
- uint32_t flags,
+ int oflag,
rtems_rfs_file_handle** handle);
/**
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-link.c b/cpukit/libfs/src/rfs/rtems-rfs-link.c
index 392a7520d6..2dcdf8a67a 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-link.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-link.c
@@ -385,8 +385,7 @@ rtems_rfs_symlink_read (rtems_rfs_file_system* fs,
if (size < *length)
{
- rtems_rfs_inode_close (fs, &inode);
- return EINVAL;
+ *length = size;
}
if (rtems_rfs_inode_get_block_count (&inode) == 0)
@@ -450,8 +449,6 @@ rtems_rfs_symlink_read (rtems_rfs_file_system* fs,
}
}
- path[*length] = '\0';
-
rc = rtems_rfs_inode_close (fs, &inode);
return rc;
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c
index d5a5a3fcf7..9ca829e168 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c
@@ -38,8 +38,8 @@
static int
rtems_rfs_rtems_device_open ( rtems_libio_t *iop,
const char *pathname,
- uint32_t flag,
- uint32_t mode)
+ int oflag,
+ mode_t mode)
{
rtems_libio_open_close_args_t args;
rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo);
@@ -257,10 +257,8 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_device_handlers = {
.ioctl_h = rtems_rfs_rtems_device_ioctl,
.lseek_h = rtems_rfs_rtems_device_lseek,
.fstat_h = rtems_rfs_rtems_fstat,
- .fchmod_h = rtems_rfs_rtems_fchmod,
.ftruncate_h = rtems_rfs_rtems_device_ftruncate,
.fsync_h = rtems_filesystem_default_fsync,
.fdatasync_h = rtems_filesystem_default_fdatasync,
- .fcntl_h = rtems_filesystem_default_fcntl,
- .rmnod_h = rtems_rfs_rtems_rmnod
+ .fcntl_h = rtems_filesystem_default_fcntl
};
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c
index 8f9b363336..77eeeba9fa 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c
@@ -36,18 +36,12 @@
* This rountine will verify that the node being opened as a directory is in
* fact a directory node. If it is then the offset into the directory will be
* set to 0 to position to the first directory entry.
- *
- * @param iop
- * @param pathname
- * @param flag
- * @param mode
- * @@return int
*/
static int
rtems_rfs_rtems_dir_open (rtems_libio_t* iop,
const char* pathname,
- uint32_t flag,
- uint32_t mode)
+ int oflag,
+ mode_t mode)
{
rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo);
rtems_rfs_ino ino = rtems_rfs_rtems_get_iop_ino (iop);
@@ -193,36 +187,6 @@ rtems_rfs_rtems_dir_lseek (rtems_libio_t* iop,
return 0;
}
-static int
-rtems_rfs_rtems_dir_rmnod (rtems_filesystem_location_info_t* parent_pathloc,
- rtems_filesystem_location_info_t* pathloc)
-{
- rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
- rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_pathloc);
- rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
- uint32_t doff = rtems_rfs_rtems_get_pathloc_doff (pathloc);
- int rc;
-
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_DIR_RMNOD))
- printf ("rtems-rfs: dir-rmnod: parent:%" PRId32 " doff:%" PRIu32 ", ino:%" PRId32 "\n",
- parent, doff, ino);
-
- if (ino == RTEMS_RFS_ROOT_INO)
- return rtems_rfs_rtems_error ("dir_rmnod: root inode", EBUSY);
-
- rtems_rfs_rtems_lock (fs);
-
- rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_if_empty);
- if (rc)
- {
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("dir_rmnod: unlinking", rc);
- }
-
- rtems_rfs_rtems_unlock (fs);
- return 0;
-}
-
/*
* Set of operations handlers for operations on directories.
*/
@@ -235,10 +199,8 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_dir_handlers = {
.ioctl_h = rtems_filesystem_default_ioctl,
.lseek_h = rtems_rfs_rtems_dir_lseek,
.fstat_h = rtems_rfs_rtems_fstat,
- .fchmod_h = rtems_rfs_rtems_fchmod,
- .ftruncate_h = rtems_filesystem_default_ftruncate,
+ .ftruncate_h = rtems_filesystem_default_ftruncate_directory,
.fsync_h = rtems_filesystem_default_fsync,
.fdatasync_h = rtems_rfs_rtems_fdatasync,
- .fcntl_h = rtems_filesystem_default_fcntl,
- .rmnod_h = rtems_rfs_rtems_dir_rmnod
+ .fcntl_h = rtems_filesystem_default_fcntl
};
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c
index 346ae54ff5..0a15652dfc 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c
@@ -38,30 +38,24 @@
/**
* This routine processes the open() system call. Note that there is nothing
* special to be done at open() time.
- *
- * @param iop
- * @param pathname
- * @param flag
- * @param mode
- * @return int
*/
static int
rtems_rfs_rtems_file_open (rtems_libio_t* iop,
const char* pathname,
- uint32_t flag,
- uint32_t mode)
+ int oflag,
+ mode_t mode)
{
rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo);
rtems_rfs_ino ino;
rtems_rfs_file_handle* file;
- uint32_t flags;
+ int flags;
int rc;
flags = 0;
if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN))
- printf("rtems-rfs: file-open: path:%s ino:%" PRId32 " flags:%04" PRIx32 " mode:%04" PRIx32 "\n",
+ printf("rtems-rfs: file-open: path:%s ino:%" PRId32 " flags:%04i mode:%04" PRIu32 "\n",
pathname, ino, flags, mode);
rtems_rfs_rtems_lock (fs);
@@ -352,10 +346,8 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_file_handlers = {
.ioctl_h = rtems_rfs_rtems_file_ioctl,
.lseek_h = rtems_rfs_rtems_file_lseek,
.fstat_h = rtems_rfs_rtems_fstat,
- .fchmod_h = rtems_rfs_rtems_fchmod,
.ftruncate_h = rtems_rfs_rtems_file_ftruncate,
.fsync_h = rtems_rfs_rtems_fdatasync,
.fdatasync_h = rtems_rfs_rtems_fdatasync,
- .fcntl_h = rtems_filesystem_default_fcntl,
- .rmnod_h = rtems_rfs_rtems_rmnod
+ .fcntl_h = rtems_filesystem_default_fcntl
};
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-utils.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-utils.c
index 44c8885bbe..e77ffddaf8 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-utils.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-utils.c
@@ -25,60 +25,6 @@
#include "rtems-rfs-rtems.h"
-bool
-rtems_rfs_rtems_eval_perms (rtems_rfs_inode_handle* inode, int flags)
-{
- uid_t st_uid;
- gid_t st_gid;
- uint16_t uid;
- uint16_t gid;
- uint16_t mode;
- int flags_to_test;
-
- uid = rtems_rfs_inode_get_uid (inode);
- gid = rtems_rfs_inode_get_gid (inode);
- mode = rtems_rfs_inode_get_mode (inode);
-
-#if defined (RTEMS_POSIX_API)
- st_uid = geteuid ();
- st_gid = getegid ();
-#else
- st_uid = uid;
- st_gid = gid;
-#endif
-
- /*
- * Check if I am owner or a group member or someone else.
- */
- flags_to_test = flags;
-
- if ((st_uid == 0) || (st_uid == uid))
- flags_to_test |= flags << 6;
- if ((st_uid == 0) || (st_gid == gid))
- flags_to_test |= flags << 3;
- else
- /* must be other - already set above */;
-
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PERMS))
- printf ("rtems-rfs: eval-perms: uid=%d gid=%d iuid=%d igid=%d " \
- "flags=%o flags_to_test=%o mode=%o (%o)\n",
- st_uid, st_gid, uid, gid,
- flags, flags_to_test, mode & 0777,
- flags_to_test & (mode & 0777));
-
- /*
- * If all of the flags are set we have permission
- * to do this.
- */
- if ((flags_to_test & (mode & 0777)) != 0)
- return true;
-
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PERMS))
- printf("rtems-rfs: eval-perms: perms failed\n");
-
- return false;
-}
-
/*
* The following sets the handlers based on the type of inode.
*/
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems.c
index 7c92a09a3c..e6006a8970 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-rtems.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems.c
@@ -1,6 +1,9 @@
/*
* COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
@@ -35,522 +38,245 @@
#include <rtems/rfs/rtems-rfs-link.h>
#include "rtems-rfs-rtems.h"
-/**
- * The libio permissions for read/execute.
- */
-#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
-/**
- * The libio permissions for write/execute.
- */
-#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
-
-/**
- * Evaluate the path to a node that wishes to be accessed. The pathloc is
- * returned with the ino to the node to be accessed.
- *
- * The routine starts from the root stripping away any leading path separators
- * breaking the path up into the node names and checking an inode exists for
- * that node name. Permissions are checked to insure access to the node is
- * allowed. A path to a node must be accessable all the way even if the end
- * result is directly accessable. As a user on Linux try "ls /root/../tmp" and
- * you will see if fails.
- *
- * The whole process is complicated by crossmount paths where we head down into
- * this file system only to return to the top and out to a another mounted file
- * system. For example we are mounted on '/e' and the user enters "ls
- * /e/a/b/../../dev". We need to head down then back up.
- *
- * @param path
- * @param pathlen
- * @param flags
- * @param pathloc
- */
-static int
-rtems_rfs_rtems_eval_path (const char* path,
- size_t pathlen,
- int flags,
- rtems_filesystem_location_info_t* pathloc)
+static bool
+rtems_rfs_rtems_eval_perms (rtems_filesystem_eval_path_context_t *ctx,
+ int eval_flags,
+ rtems_rfs_inode_handle* inode)
{
- rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
- rtems_rfs_inode_handle inode;
- rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
- uint32_t doff = 0;
- const char* node;
- size_t node_len;
- int stripped;
- int rc;
-
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
- printf ("rtems-rfs-rtems: eval-path: in: path:%s pathlen:%zi ino:%" PRId32 "\n",
- path, pathlen, ino);
+ return rtems_filesystem_eval_path_check_access(
+ ctx,
+ eval_flags,
+ rtems_rfs_inode_get_mode (inode),
+ rtems_rfs_inode_get_uid (inode),
+ rtems_rfs_inode_get_gid (inode)
+ );
+}
+static rtems_filesystem_node_types_t
+rtems_rfs_rtems_node_type_by_inode (rtems_rfs_inode_handle* inode)
+{
/*
- * Eat any separators at the start of the path.
+ * Do not return RTEMS_FILESYSTEM_HARD_LINK because this would result in an
+ * eval link which does not make sense in the case of the RFS file
+ * system. All directory entries are links to an inode. A link such as a HARD
+ * link is actually the normal path to a regular file, directory, device
+ * etc's inode. Links to inodes can be considered "the real" one, yet they
+ * are all links.
*/
- stripped = rtems_filesystem_prefix_separators (path, pathlen);
- path += stripped;
- pathlen -= stripped;
-
- rtems_rfs_rtems_lock (fs);
-
- while (true)
- {
- /*
- * Open and load the inode.
- */
- rc = rtems_rfs_inode_open (fs, ino, &inode, true);
- if (rc > 0)
- {
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_path: opening inode", rc);
- }
-
- /*
- * Is this the end of the pathname we were given ?
- */
- if ((*path == '\0') || (pathlen == 0))
- break;
-
- /*
- * If a directory the execute bit must be set for us to enter.
- */
- if (RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)) &&
- !rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_SEARCH))
- {
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_path: eval perms", EACCES);
- }
-
- /*
- * Extract the node name we will look for this time around.
- */
- node = path;
- node_len = 0;
- while (!rtems_filesystem_is_separator (*path) &&
- (*path != '\0') && pathlen &&
- ((node_len + 1) < rtems_rfs_fs_max_name (fs)))
- {
- path++;
- pathlen--;
- node_len++;
- }
-
- /*
- * Eat any separators at the start of the path.
- */
- stripped = rtems_filesystem_prefix_separators (path, pathlen);
- path += stripped;
- pathlen -= stripped;
- node_len += stripped;
-
- /*
- * If the node is the current directory and there is more path to come move
- * on to it otherwise we are at the inode we want.
- */
- if (rtems_rfs_current_dir (node))
- {
- if (*path)
- {
- rtems_rfs_inode_close (fs, &inode);
- continue;
- }
- break;
- }
-
- /*
- * If the node is a parent we must move up one directory. If the location
- * is on another file system we have a crossmount so we call that file
- * system to handle the remainder of the path.
- */
- if (rtems_rfs_parent_dir (node))
- {
- /*
- * If we are at the root inode of the file system we have a crossmount
- * path.
- */
- if (ino == RTEMS_RFS_ROOT_INO)
- {
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
- printf("rtems-rfs-rtems: eval-path: crossmount: path:%s (%zd)\n",
- path - node_len, pathlen + node_len);
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- *pathloc = pathloc->mt_entry->mt_point_node;
- return (*pathloc->ops->evalpath_h)(path - node_len, pathlen + node_len,
- flags, pathloc);
- }
-
- /*
- * We need to find the parent of this node.
- */
- rc = rtems_rfs_dir_lookup_ino (fs, &inode,
- RTEMS_RFS_PARENT_DIR_STR,
- RTEMS_RFS_PARENT_DIR_SIZE, &ino, &doff);
- if (rc > 0)
- {
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_path: read parent inode", rc);
- }
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
- printf("rtems-rfs-rtems: eval-path: parent: ino:%" PRId32 "\n", ino);
- }
- else
- {
- /*
- * Look up the node name in this directory. If found drop through, close
- * the current inode and let the loop open the inode so the mode can be
- * read and handlers set.
- */
- rc = rtems_rfs_dir_lookup_ino (fs, &inode,
- node, node_len - stripped, &ino, &doff);
- if (rc > 0)
- {
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- return ((errno = rc) == 0) ? 0 : -1;
- }
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
- printf("rtems-rfs-rtems: eval-path: down: path:%s ino:%" PRId32 "\n", node, ino);
- }
+ uint16_t mode = rtems_rfs_inode_get_mode (inode);
+ if (RTEMS_RFS_S_ISDIR (mode))
+ return RTEMS_FILESYSTEM_DIRECTORY;
+ else if (RTEMS_RFS_S_ISLNK (mode))
+ return RTEMS_FILESYSTEM_SYM_LINK;
+ else if (RTEMS_RFS_S_ISBLK (mode) || RTEMS_RFS_S_ISCHR (mode))
+ return RTEMS_FILESYSTEM_DEVICE;
+ else
+ return RTEMS_FILESYSTEM_MEMORY_FILE;
+}
- rc = rtems_rfs_inode_close (fs, &inode);
- if (rc > 0)
- {
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_path: closing node", rc);
- }
- }
+static void
+rtems_rfs_rtems_lock_by_mt_entry (rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ rtems_rfs_file_system* fs = mt_entry->fs_info;
- rtems_rfs_rtems_set_pathloc_ino (pathloc, ino);
- rtems_rfs_rtems_set_pathloc_doff (pathloc, doff);
+ rtems_rfs_rtems_lock (fs);
+}
- rc = rtems_rfs_rtems_set_handlers (pathloc, &inode) ? 0 : EIO;
+static void
+rtems_rfs_rtems_unlock_by_mt_entry (rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ rtems_rfs_file_system* fs = mt_entry->fs_info;
- rtems_rfs_inode_close (fs, &inode);
rtems_rfs_rtems_unlock (fs);
-
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
- printf("rtems-rfs-rtems: eval-path: ino:%" PRId32 "\n", ino);
-
- return rc;
}
-/**
- * The following routine evaluates a path for a new node to be created. The
- * pathloc is returned with a pointer to the parent of the new node. The name
- * is returned with a pointer to the first character in the new node name. The
- * parent node is verified to be a directory.
- *
- * @param path
- * @param pathloc
- * @param name
- * @return int
- */
-static int
-rtems_rfs_rtems_eval_for_make (const char* path,
- rtems_filesystem_location_info_t* pathloc,
- const char** name)
+static bool
+rtems_rfs_rtems_is_directory(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg
+)
{
- rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
- rtems_rfs_inode_handle inode;
- rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
- rtems_rfs_ino node_ino;
- uint32_t doff = 0;
- const char* node;
- int node_len;
- int stripped;
- int rc;
+ rtems_rfs_inode_handle* inode = arg;
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
- printf ("rtems-rfs-rtems: eval-for-make: path:%s ino:%" PRId32 "\n", path, ino);
-
- *name = path + strlen (path);
-
- while (*name != path)
- {
- (*name)--;
- if (rtems_filesystem_is_separator (**name))
- {
- (*name)++;
- break;
- }
- }
-
- /*
- * Eat any separators at start of the path.
- */
- stripped = rtems_filesystem_prefix_separators (path, strlen(path));
- path += stripped;
-
- rtems_rfs_rtems_lock (fs);
-
- while (true)
- {
- /*
- * Open and load the inode.
- */
- rc = rtems_rfs_inode_open (fs, ino, &inode, true);
- if (rc > 0)
- {
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_for_make: read ino", rc);
- }
+ return rtems_rfs_rtems_node_type_by_inode (inode)
+ == RTEMS_FILESYSTEM_DIRECTORY;
+}
- /*
- * If a directory the execute bit must be set for us to enter.
- */
- if (RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)) &&
- !rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_SEARCH))
- {
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_for_make: eval perms", EACCES);
- }
+static void rtems_rfs_rtems_follow_link(
+ rtems_filesystem_eval_path_context_t* ctx,
+ rtems_rfs_file_system* fs,
+ rtems_rfs_ino ino
+)
+{
+ size_t len = MAXPATHLEN;
+ char *link = malloc(len + 1);
- /*
- * Is this the end of the pathname we were given ?
- */
- if (path == *name)
- break;
-
- /*
- * Extract the node name we will look for this time around.
- */
- node = path;
- node_len = 0;
- while (!rtems_filesystem_is_separator(*path) &&
- (*path != '\0') &&
- (node_len < (rtems_rfs_fs_max_name (fs) - 1)))
- {
- node_len++;
- path++;
- }
+ if (link != NULL) {
+ int rc = rtems_rfs_symlink_read (fs, ino, link, len, &len);
- /*
- * Eat any separators at start of the new path.
- */
- stripped = rtems_filesystem_prefix_separators (path, strlen (path));
- path += stripped;
- node_len += stripped;
-
- /*
- * If the node is the current directory and there is more path to come move
- * on to it otherwise we are at the inode we want.
- */
- if (rtems_rfs_current_dir (node))
- {
- if (*path)
- {
- rtems_rfs_inode_close (fs, &inode);
- continue;
- }
- break;
+ if (rc == 0) {
+ rtems_filesystem_eval_path_recursive (ctx, link, len);
+ } else {
+ rtems_filesystem_eval_path_error (ctx, 0);
}
- /*
- * If the node is a parent we must move up one directory. If the location
- * is on another file system we have a crossmount so we call that file
- * system to handle the remainder of the path.
- */
- if (rtems_rfs_parent_dir (path))
- {
- /*
- * If we are at the root inode of the file system we have a crossmount
- * path.
- */
- if (ino == RTEMS_RFS_ROOT_INO)
- {
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
- printf("rtems-rfs-rtems: eval-for-make: crossmount: path:%s\n",
- path - node_len);
-
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- *pathloc = pathloc->mt_entry->mt_point_node;
- return (*pathloc->ops->evalformake_h)(path + 2, pathloc, name);
- }
+ free(link);
+ } else {
+ rtems_filesystem_eval_path_error (ctx, ENOMEM);
+ }
+}
- /*
- * If not a directory give and up return. We cannot change dir from a
- * regular file or device node.
- */
- if (!RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)))
- {
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_for_make: not dir", ENOTSUP);
+static rtems_filesystem_eval_path_generic_status
+rtems_rfs_rtems_eval_token(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg,
+ const char *token,
+ size_t tokenlen
+)
+{
+ rtems_filesystem_eval_path_generic_status status =
+ RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
+ rtems_rfs_inode_handle* inode = arg;
+ bool access_ok = rtems_rfs_rtems_eval_perms (ctx, RTEMS_LIBIO_PERMS_SEARCH, inode);
+
+ if (access_ok) {
+ if (rtems_filesystem_is_current_directory (token, tokenlen)) {
+ rtems_filesystem_eval_path_clear_token (ctx);
+ } else {
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc( ctx );
+ rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (currentloc);
+ rtems_rfs_ino entry_ino;
+ uint32_t entry_doff;
+ int rc = rtems_rfs_dir_lookup_ino (
+ fs,
+ inode,
+ token,
+ tokenlen,
+ &entry_ino,
+ &entry_doff
+ );
+
+ if (rc == 0) {
+ rc = rtems_rfs_inode_close (fs, inode);
+ if (rc == 0) {
+ rc = rtems_rfs_inode_open (fs, entry_ino, inode, true);
+ }
+
+ if (rc != 0) {
+ /*
+ * This prevents the rtems_rfs_inode_close() from doing something in
+ * rtems_rfs_rtems_eval_path().
+ */
+ memset (inode, 0, sizeof(*inode));
+ }
+ } else {
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
+ rc = -1;
}
- /*
- * We need to find the parent of this node.
- */
- rc = rtems_rfs_dir_lookup_ino (fs, &inode,
- RTEMS_RFS_PARENT_DIR_STR,
- RTEMS_RFS_PARENT_DIR_SIZE, &ino, &doff);
- if (rc > 0)
- {
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_for_make: read parent inode", rc);
- }
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
- printf ("rtems-rfs-rtems: eval-for-make: parent: ino:%" PRId32 "\n", ino);
- }
- else
- {
- /*
- * Read the inode so we know it exists and what type it is.
- */
- rc = rtems_rfs_dir_lookup_ino (fs, &inode,
- node, node_len - stripped, &ino, &doff);
- if (rc > 0)
- {
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_for_make: reading inode", rc);
+ if (rc == 0) {
+ bool is_sym_link = rtems_rfs_rtems_node_type_by_inode (inode)
+ == RTEMS_FILESYSTEM_SYM_LINK;
+ int eval_flags = rtems_filesystem_eval_path_get_flags (ctx);
+ bool follow_sym_link = (eval_flags & RTEMS_LIBIO_FOLLOW_SYM_LINK) != 0;
+ bool terminal = !rtems_filesystem_eval_path_has_path (ctx);
+
+ rtems_filesystem_eval_path_clear_token (ctx);
+
+ if (is_sym_link && (follow_sym_link || !terminal)) {
+ rtems_rfs_rtems_follow_link (ctx, fs, entry_ino);
+ } else {
+ rc = rtems_rfs_rtems_set_handlers (currentloc, inode) ? 0 : EIO;
+ if (rc == 0) {
+ rtems_rfs_rtems_set_pathloc_ino (currentloc, entry_ino);
+ rtems_rfs_rtems_set_pathloc_doff (currentloc, entry_doff);
+
+ if (!terminal) {
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
+ }
+ } else {
+ rtems_filesystem_eval_path_error (
+ ctx,
+ rtems_rfs_rtems_error ("eval_path: set handlers", rc)
+ );
+ }
+ }
}
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
- printf("rtems-rfs-rtems: eval-for-make: down: path:%s ino:%" PRId32 "\n",
- node, ino);
- }
-
- rc = rtems_rfs_inode_close (fs, &inode);
- if (rc > 0)
- {
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_for_make: closing node", rc);
}
}
- if (!RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)))
- {
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_for_make: not dir", ENOTDIR);
- }
+ return status;
+}
- if (!rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_WX))
- {
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_for_make: cannot write", EACCES);
- }
+static const rtems_filesystem_eval_path_generic_config
+rtems_rfs_rtems_eval_config = {
+ .is_directory = rtems_rfs_rtems_is_directory,
+ .eval_token = rtems_rfs_rtems_eval_token
+};
- /*
- * Make sure the name does not already exists in the directory.
- */
- rc = rtems_rfs_dir_lookup_ino (fs, &inode, *name, strlen (*name),
- &node_ino, &doff);
- if (rc == 0)
- {
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_for_make: found name", EEXIST);
- }
+static void
+rtems_rfs_rtems_eval_path (rtems_filesystem_eval_path_context_t *ctx)
+{
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc (ctx);
+ rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (currentloc);
+ rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (currentloc);
+ rtems_rfs_inode_handle inode;
+ int rc;
- if (rc != ENOENT)
- {
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("eval_for_make: look up", rc);
+ rc = rtems_rfs_inode_open (fs, ino, &inode, true);
+ if (rc == 0) {
+ rtems_filesystem_eval_path_generic (
+ ctx,
+ &inode,
+ &rtems_rfs_rtems_eval_config
+ );
+ rc = rtems_rfs_inode_close (fs, &inode);
+ if (rc != 0) {
+ rtems_filesystem_eval_path_error (
+ ctx,
+ rtems_rfs_rtems_error ("eval_path: closing inode", rc)
+ );
+ }
+ } else {
+ rtems_filesystem_eval_path_error (
+ ctx,
+ rtems_rfs_rtems_error ("eval_path: opening inode", rc)
+ );
}
-
- /*
- * Set the parent ino in the path location.
- */
-
- rtems_rfs_rtems_set_pathloc_ino (pathloc, ino);
- rtems_rfs_rtems_set_pathloc_doff (pathloc, doff);
-
- rc = rtems_rfs_rtems_set_handlers (pathloc, &inode) ? 0 : EIO;
-
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
- printf("rtems-rfs-rtems: eval-for-make: parent ino:%" PRId32 " name:%s\n",
- ino, *name);
-
- rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
-
- return rc;
}
/**
* The following rouine creates a new link node under parent with the name
- * given in name. The link node is set to point to the node at to_loc.
- *
- * @param to_loc
- * @param parent_loc
- * @param name
- * @return int
+ * given in name. The link node is set to point to the node at targetloc.
*/
static int
-rtems_rfs_rtems_link (rtems_filesystem_location_info_t* to_loc,
- rtems_filesystem_location_info_t* parent_loc,
- const char* name)
+rtems_rfs_rtems_link (const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *targetloc,
+ const char *name,
+ size_t namelen)
{
- rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (to_loc);
- rtems_rfs_ino target = rtems_rfs_rtems_get_pathloc_ino (to_loc);
- rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc);
+ rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (targetloc);
+ rtems_rfs_ino target = rtems_rfs_rtems_get_pathloc_ino (targetloc);
+ rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parentloc);
int rc;
if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_LINK))
printf ("rtems-rfs-rtems: link: in: parent:%" PRId32 " target:%" PRId32 "\n",
parent, target);
- rtems_rfs_rtems_lock (fs);
-
- rc = rtems_rfs_link (fs, name, strlen (name), parent, target, false);
+ rc = rtems_rfs_link (fs, name, namelen, parent, target, false);
if (rc)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("link: linking", rc);
}
- rtems_rfs_rtems_unlock (fs);
return 0;
}
/**
- * Routine to remove a link node from the file system.
- *
- * @param parent_loc
- * @param loc
- * @return int
- */
-
-static int
-rtems_rfs_rtems_unlink (rtems_filesystem_location_info_t* parent_loc,
- rtems_filesystem_location_info_t* loc)
-{
- rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parent_loc);
- rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc);
- rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (loc);
- uint32_t doff = rtems_rfs_rtems_get_pathloc_doff (loc);
- int rc;
-
- rtems_rfs_rtems_lock (fs);
-
- if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_UNLINK))
- printf("rtems-rfs-rtems: unlink: parent:%" PRId32 " doff:%" PRIu32 " ino:%" PRId32 "\n",
- parent, doff, ino);
-
- rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_denied);
- if (rc)
- {
- rtems_rfs_rtems_unlock (fs);
- return rtems_rfs_rtems_error ("unlink: unlink inode", rc);
- }
-
- rtems_rfs_rtems_unlock (fs);
-
- return 0;
-}
-
-/**
* The following verifies that and returns the type of node that the loc refers
* to.
*
@@ -559,51 +285,28 @@ rtems_rfs_rtems_unlink (rtems_filesystem_location_info_t* parent_loc,
*/
static rtems_filesystem_node_types_t
-rtems_rfs_rtems_node_type (rtems_filesystem_location_info_t* pathloc)
+rtems_rfs_rtems_node_type (const rtems_filesystem_location_info_t* pathloc)
{
rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
rtems_filesystem_node_types_t type;
rtems_rfs_inode_handle inode;
- uint16_t mode;
int rc;
- rtems_rfs_rtems_lock (fs);
-
rc = rtems_rfs_inode_open (fs, ino, &inode, true);
if (rc > 0)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("node_type: opening inode", rc);
}
- /*
- * Do not return RTEMS_FILESYSTEM_HARD_LINK because this would result in an
- * eval link which does not make sense in the case of the RFS file
- * system. All directory entries are links to an inode. A link such as a HARD
- * link is actually the normal path to a regular file, directory, device
- * etc's inode. Links to inodes can be considered "the real" one, yet they
- * are all links.
- */
- mode = rtems_rfs_inode_get_mode (&inode);
- if (RTEMS_RFS_S_ISDIR (mode))
- type = RTEMS_FILESYSTEM_DIRECTORY;
- else if (RTEMS_RFS_S_ISLNK (mode))
- type = RTEMS_FILESYSTEM_SYM_LINK;
- else if (RTEMS_RFS_S_ISBLK (mode) || RTEMS_RFS_S_ISCHR (mode))
- type = RTEMS_FILESYSTEM_DEVICE;
- else
- type = RTEMS_FILESYSTEM_MEMORY_FILE;
+ type = rtems_rfs_rtems_node_type_by_inode (&inode);
rc = rtems_rfs_inode_close (fs, &inode);
if (rc > 0)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("node_type: closing inode", rc);
}
- rtems_rfs_rtems_unlock (fs);
-
return type;
}
@@ -618,9 +321,9 @@ rtems_rfs_rtems_node_type (rtems_filesystem_location_info_t* pathloc)
*/
static int
-rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc,
- uid_t owner,
- gid_t group)
+rtems_rfs_rtems_chown (const rtems_filesystem_location_info_t *pathloc,
+ uid_t owner,
+ gid_t group)
{
rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
@@ -634,12 +337,9 @@ rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc,
printf ("rtems-rfs-rtems: chown: in: ino:%" PRId32 " uid:%d gid:%d\n",
ino, owner, group);
- rtems_rfs_rtems_lock (fs);
-
rc = rtems_rfs_inode_open (fs, ino, &inode, true);
if (rc > 0)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("chown: opening inode", rc);
}
@@ -653,7 +353,6 @@ rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc,
if ((uid != rtems_rfs_inode_get_uid (&inode)) && (uid != 0))
{
rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("chown: not able", EPERM);
}
#endif
@@ -663,12 +362,9 @@ rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc,
rc = rtems_rfs_inode_close (fs, &inode);
if (rc)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("chown: closing inode", rc);
}
- rtems_rfs_rtems_unlock (fs);
-
return 0;
}
@@ -683,21 +379,18 @@ rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc,
*/
static int
-rtems_rfs_rtems_utime(rtems_filesystem_location_info_t* pathloc,
- time_t atime,
- time_t mtime)
+rtems_rfs_rtems_utime(const rtems_filesystem_location_info_t* pathloc,
+ time_t atime,
+ time_t mtime)
{
rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
rtems_rfs_inode_handle inode;
int rc;
- rtems_rfs_rtems_lock (fs);
-
rc = rtems_rfs_inode_open (fs, ino, &inode, true);
if (rc)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("utime: read inode", rc);
}
@@ -707,73 +400,46 @@ rtems_rfs_rtems_utime(rtems_filesystem_location_info_t* pathloc,
rc = rtems_rfs_inode_close (fs, &inode);
if (rc)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("utime: closing inode", rc);
}
- rtems_rfs_rtems_unlock (fs);
-
return 0;
}
/**
- * The following rouine creates a new symbolic link node under parent with the
- * name given in name. The node is set to point to the node at to_loc.
- *
- * @param parent_loc
- * @param link_name
- * @param node_name
- * return int
+ * The following routine creates a new symbolic link node under parent with the
+ * name given in node_name.
*/
static int
-rtems_rfs_rtems_symlink (rtems_filesystem_location_info_t* parent_loc,
- const char* link_name,
- const char* node_name)
+rtems_rfs_rtems_symlink (const rtems_filesystem_location_info_t* parent_loc,
+ const char* node_name,
+ size_t node_name_len,
+ const char* target)
{
rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parent_loc);
rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc);
- uid_t uid;
- gid_t gid;
int rc;
-#if defined(RTEMS_POSIX_API)
- uid = geteuid ();
- gid = getegid ();
-#else
- uid = 0;
- gid = 0;
-#endif
-
- rtems_rfs_rtems_lock (fs);
-
- rc = rtems_rfs_symlink (fs, node_name, strlen (node_name),
- link_name, strlen (link_name),
- uid, gid, parent);
+ rc = rtems_rfs_symlink (fs, node_name, node_name_len,
+ target, strlen (target),
+ geteuid(), getegid(), parent);
if (rc)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("symlink: linking", rc);
}
- rtems_rfs_rtems_unlock (fs);
-
return 0;
}
/**
* The following rouine puts the symblic links destination name into buf.
- *
- * @param loc
- * @param buf
- * @param bufsize
- * @return int
*/
static ssize_t
-rtems_rfs_rtems_readlink (rtems_filesystem_location_info_t* pathloc,
- char* buf,
- size_t bufsize)
+rtems_rfs_rtems_readlink (const rtems_filesystem_location_info_t* pathloc,
+ char* buf,
+ size_t bufsize)
{
rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
@@ -783,23 +449,18 @@ rtems_rfs_rtems_readlink (rtems_filesystem_location_info_t* pathloc,
if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_READLINK))
printf ("rtems-rfs-rtems: readlink: in: ino:%" PRId32 "\n", ino);
- rtems_rfs_rtems_lock (fs);
-
rc = rtems_rfs_symlink_read (fs, ino, buf, bufsize, &length);
if (rc)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("readlink: reading link", rc);
}
- rtems_rfs_rtems_unlock (fs);
-
- return (int) length;
+ return (ssize_t) length;
}
-int
-rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc,
- mode_t mode)
+static int
+rtems_rfs_rtems_fchmod (const rtems_filesystem_location_info_t* pathloc,
+ mode_t mode)
{
rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
@@ -814,12 +475,9 @@ rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc,
printf ("rtems-rfs-rtems: fchmod: in: ino:%" PRId32 " mode:%06" PRIomode_t "\n",
ino, mode);
- rtems_rfs_rtems_lock (fs);
-
rc = rtems_rfs_inode_open (fs, ino, &inode, true);
if (rc)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("fchmod: opening inode", rc);
}
@@ -834,7 +492,6 @@ rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc,
if ((uid != rtems_rfs_inode_get_uid (&inode)) && (uid != 0))
{
rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("fchmod: checking uid", EPERM);
}
#endif
@@ -847,18 +504,15 @@ rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc,
rc = rtems_rfs_inode_close (fs, &inode);
if (rc > 0)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("fchmod: closing inode", rc);
}
- rtems_rfs_rtems_unlock (fs);
-
return 0;
}
int
-rtems_rfs_rtems_fstat (rtems_filesystem_location_info_t* pathloc,
- struct stat* buf)
+rtems_rfs_rtems_fstat (const rtems_filesystem_location_info_t* pathloc,
+ struct stat* buf)
{
rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
@@ -870,12 +524,9 @@ rtems_rfs_rtems_fstat (rtems_filesystem_location_info_t* pathloc,
if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_STAT))
printf ("rtems-rfs-rtems: stat: in: ino:%" PRId32 "\n", ino);
- rtems_rfs_rtems_lock (fs);
-
rc = rtems_rfs_inode_open (fs, ino, &inode, true);
if (rc)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("stat: opening inode", rc);
}
@@ -931,32 +582,25 @@ rtems_rfs_rtems_fstat (rtems_filesystem_location_info_t* pathloc,
rc = rtems_rfs_inode_close (fs, &inode);
if (rc > 0)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("stat: closing inode", rc);
}
- rtems_rfs_rtems_unlock (fs);
return 0;
}
/**
* Routine to create a node in the RFS file system.
- *
- * @param name
- * @param mode
- * @param dev
- * @param pathloc
- * @return int
*/
static int
-rtems_rfs_rtems_mknod (const char *name,
- mode_t mode,
- dev_t dev,
- rtems_filesystem_location_info_t *pathloc)
+rtems_rfs_rtems_mknod (const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev)
{
- rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
- rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (pathloc);
+ rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parentloc);
+ rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parentloc);
rtems_rfs_ino ino;
rtems_rfs_inode_handle inode;
uid_t uid;
@@ -971,21 +615,17 @@ rtems_rfs_rtems_mknod (const char *name,
gid = 0;
#endif
- rtems_rfs_rtems_lock (fs);
-
- rc = rtems_rfs_inode_create (fs, parent, name, strlen (name),
+ rc = rtems_rfs_inode_create (fs, parent, name, namelen,
rtems_rfs_rtems_imode (mode),
1, uid, gid, &ino);
if (rc > 0)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("mknod: inode create", rc);
}
rc = rtems_rfs_inode_open (fs, ino, &inode, true);
if (rc > 0)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("mknod: inode open", rc);
}
@@ -1003,18 +643,15 @@ rtems_rfs_rtems_mknod (const char *name,
else
{
rtems_rfs_inode_close (fs, &inode);
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("mknod: bad mode", EINVAL);
}
rc = rtems_rfs_inode_close (fs, &inode);
if (rc > 0)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("mknod: closing inode", rc);
}
- rtems_rfs_rtems_unlock (fs);
return 0;
}
@@ -1026,8 +663,8 @@ rtems_rfs_rtems_mknod (const char *name,
* @return int
*/
int
-rtems_rfs_rtems_rmnod (rtems_filesystem_location_info_t* parent_pathloc,
- rtems_filesystem_location_info_t* pathloc)
+rtems_rfs_rtems_rmnod (const rtems_filesystem_location_info_t* parent_pathloc,
+ const rtems_filesystem_location_info_t* pathloc)
{
rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_pathloc);
@@ -1039,16 +676,15 @@ rtems_rfs_rtems_rmnod (rtems_filesystem_location_info_t* parent_pathloc,
printf ("rtems-rfs: rmnod: parent:%" PRId32 " doff:%" PRIu32 ", ino:%" PRId32 "\n",
parent, doff, ino);
- rtems_rfs_rtems_lock (fs);
+ if (ino == RTEMS_RFS_ROOT_INO)
+ return rtems_rfs_rtems_error ("rmnod: root inode", EBUSY);
- rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_denied);
+ rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_if_empty);
if (rc)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("rmnod: unlinking", rc);
}
- rtems_rfs_rtems_unlock (fs);
return 0;
}
@@ -1073,18 +709,13 @@ rtems_rfs_rtems_fdatasync (rtems_libio_t* iop)
/**
* Rename the node.
- *
- * @param old_parent_loc The old name's parent location.
- * @param old_loc The old name's location.
- * @param new_parent_loc The new name's parent location.
- * @param new_name The new name.
- * @return int
*/
static int
-rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_loc,
- rtems_filesystem_location_info_t* old_loc,
- rtems_filesystem_location_info_t* new_parent_loc,
- const char* new_name)
+rtems_rfs_rtems_rename(const rtems_filesystem_location_info_t* old_parent_loc,
+ const rtems_filesystem_location_info_t* old_loc,
+ const rtems_filesystem_location_info_t* new_parent_loc,
+ const char* new_name,
+ size_t new_name_len)
{
rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (old_loc);
rtems_rfs_ino old_parent;
@@ -1100,19 +731,16 @@ rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_loc,
doff = rtems_rfs_rtems_get_pathloc_doff (old_loc);
if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RENAME))
- printf ("rtems-rfs: rename: ino:%" PRId32 " doff:%" PRIu32 ", new parent:%" PRId32 " new name:%s\n",
- ino, doff, new_parent, new_name);
-
- rtems_rfs_rtems_lock (fs);
+ printf ("rtems-rfs: rename: ino:%" PRId32 " doff:%" PRIu32 ", new parent:%" PRId32 "\n",
+ ino, doff, new_parent);
/*
* Link to the inode before unlinking so the inode is not erased when
* unlinked.
*/
- rc = rtems_rfs_link (fs, new_name, strlen (new_name), new_parent, ino, true);
+ rc = rtems_rfs_link (fs, new_name, new_name_len, new_parent, ino, true);
if (rc)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("rename: linking", rc);
}
@@ -1124,12 +752,9 @@ rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_loc,
rtems_rfs_unlink_dir_allowed);
if (rc)
{
- rtems_rfs_rtems_unlock (fs);
return rtems_rfs_rtems_error ("rename: unlinking", rc);
}
- rtems_rfs_rtems_unlock (fs);
-
return 0;
}
@@ -1141,8 +766,8 @@ rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_loc,
* @return int
*/
static int
-rtems_rfs_rtems_statvfs (rtems_filesystem_location_info_t* pathloc,
- struct statvfs* sb)
+rtems_rfs_rtems_statvfs (const rtems_filesystem_location_info_t* pathloc,
+ struct statvfs* sb)
{
rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
size_t blocks;
@@ -1177,12 +802,10 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_link_handlers =
.ioctl_h = rtems_filesystem_default_ioctl,
.lseek_h = rtems_filesystem_default_lseek,
.fstat_h = rtems_rfs_rtems_fstat,
- .fchmod_h = rtems_filesystem_default_fchmod,
.ftruncate_h = rtems_filesystem_default_ftruncate,
.fsync_h = rtems_filesystem_default_fsync,
.fdatasync_h = rtems_filesystem_default_fdatasync,
- .fcntl_h = rtems_filesystem_default_fcntl,
- .rmnod_h = rtems_rfs_rtems_rmnod
+ .fcntl_h = rtems_filesystem_default_fcntl
};
/**
@@ -1191,27 +814,30 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_link_handlers =
int rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t *mt_entry,
const void *data);
-int rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t *mt_entry);
+void rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t *mt_entry);
/**
* RFS file system operations table.
*/
const rtems_filesystem_operations_table rtems_rfs_ops =
{
- .evalpath_h = rtems_rfs_rtems_eval_path,
- .evalformake_h = rtems_rfs_rtems_eval_for_make,
+ .lock_h = rtems_rfs_rtems_lock_by_mt_entry,
+ .unlock_h = rtems_rfs_rtems_unlock_by_mt_entry,
+ .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
+ .eval_path_h = rtems_rfs_rtems_eval_path,
.link_h = rtems_rfs_rtems_link,
- .unlink_h = rtems_rfs_rtems_unlink,
.node_type_h = rtems_rfs_rtems_node_type,
+ .fchmod_h = rtems_rfs_rtems_fchmod,
.mknod_h = rtems_rfs_rtems_mknod,
+ .rmnod_h = rtems_rfs_rtems_rmnod,
.chown_h = rtems_rfs_rtems_chown,
+ .clonenod_h = rtems_filesystem_default_clonenode,
.freenod_h = rtems_filesystem_default_freenode,
.mount_h = rtems_filesystem_default_mount,
.fsmount_me_h = rtems_rfs_rtems_initialise,
.unmount_h = rtems_filesystem_default_unmount,
.fsunmount_me_h = rtems_rfs_rtems_shutdown,
.utime_h = rtems_rfs_rtems_utime,
- .eval_link_h = rtems_filesystem_default_evaluate_link, /* never called cause we lie in the node type */
.symlink_h = rtems_rfs_rtems_symlink,
.readlink_h = rtems_rfs_rtems_readlink,
.rename_h = rtems_rfs_rtems_rename,
@@ -1292,9 +918,9 @@ rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t* mt_entry,
mt_entry->fs_info = fs;
- mt_entry->mt_fs_root.node_access = (void*) RTEMS_RFS_ROOT_INO;
- mt_entry->mt_fs_root.handlers = &rtems_rfs_rtems_dir_handlers;
- mt_entry->mt_fs_root.ops = &rtems_rfs_ops;
+ mt_entry->mt_fs_root->location.node_access = (void*) RTEMS_RFS_ROOT_INO;
+ mt_entry->mt_fs_root->location.handlers = &rtems_rfs_rtems_dir_handlers;
+ mt_entry->mt_fs_root->location.ops = &rtems_rfs_ops;
rtems_rfs_rtems_unlock (fs);
@@ -1304,19 +930,17 @@ rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t* mt_entry,
/**
* Shutdown the file system.
*/
-int
+void
rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t* mt_entry)
{
rtems_rfs_file_system* fs = mt_entry->fs_info;
rtems_rfs_rtems_private* rtems;
- int rc;
rtems = rtems_rfs_fs_user (fs);
- rc = rtems_rfs_fs_close(fs);
+ /* FIXME: Return value? */
+ rtems_rfs_fs_close(fs);
rtems_rfs_mutex_destroy (&rtems->access);
free (rtems);
-
- return rtems_rfs_rtems_error ("shutdown: close", rc);
}
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems.h b/cpukit/libfs/src/rfs/rtems-rfs-rtems.h
index a1b0e8556e..c4f8c9a358 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-rtems.h
+++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems.h
@@ -225,16 +225,6 @@ typedef struct rtems_rfs_rtems_private
&rtems_rfs_rtems_ ## _h ## _handlers
/**
- * Evaluate the permissions of the inode's mode against the flags.
- *
- * @param inode The inode handler to check the mode, uid and gid.
- * @param flags The flags to check permissions of.
- * @retval true The permissions allow access to the inode.
- * @retval false Access to the inode is not permitted.
- */
-bool rtems_rfs_rtems_eval_perms (rtems_rfs_inode_handle* inode, int flags);
-
-/**
* Set the handlers in the path location based on the mode of the inode.
*
* @param loc Pointer to the path location to set the handlers in.
@@ -292,23 +282,9 @@ extern const rtems_filesystem_file_handlers_r rtems_rfs_rtems_file_handlers;
/**
* The following routine does a stat on a node.
- *
- * @param iop
- * @param buf
- * @return int
- */
-int rtems_rfs_rtems_fstat (rtems_filesystem_location_info_t* pathloc,
- struct stat* buf);
-
-/**
- * File change mode routine.
- *
- * @param iop
- * @param mode
- * @return int
*/
-int rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc,
- mode_t mode);
+int rtems_rfs_rtems_fstat (const rtems_filesystem_location_info_t* pathloc,
+ struct stat* buf);
/**
* Routine to remove a node from the RFS file system.
@@ -316,8 +292,8 @@ int rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc,
* @param parent_pathloc
* @param pathloc
*/
-int rtems_rfs_rtems_rmnod (rtems_filesystem_location_info_t* parent_pathloc,
- rtems_filesystem_location_info_t* pathloc);
+int rtems_rfs_rtems_rmnod (const rtems_filesystem_location_info_t* parent_pathloc,
+ const rtems_filesystem_location_info_t* pathloc);
/**
* The following routine does a sync on an inode node. Currently it flushes
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-shell.c b/cpukit/libfs/src/rfs/rtems-rfs-shell.c
index 6969f1c588..8ef5b76ff5 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-shell.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-shell.c
@@ -102,10 +102,12 @@ rtems_rfs_get_fs (const char* path, rtems_rfs_file_system** fs)
* system data.
*/
{
- rtems_filesystem_location_info_t pathloc;
- rc = rtems_filesystem_evaluate_path (path, strlen (path), 0, &pathloc, true);
- *fs = rtems_rfs_rtems_pathloc_dev (&pathloc);
- rtems_filesystem_freenode (&pathloc);
+ rtems_filesystem_eval_path_context_t ctx;
+ int eval_flags = RTEMS_LIBIO_FOLLOW_LINK;
+ const rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_start (&ctx, path, eval_flags);
+ *fs = rtems_rfs_rtems_pathloc_dev (currentloc);
+ rtems_filesystem_eval_path_cleanup (&ctx);
}
#endif
diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am
index e468dd13a0..654c0505aa 100644
--- a/cpukit/libmisc/Makefile.am
+++ b/cpukit/libmisc/Makefile.am
@@ -103,6 +103,7 @@ libshell_a_SOURCES = shell/cat_file.c shell/cmds.c shell/internal.h \
shell/main_time.c shell/main_mknod.c \
shell/main_setenv.c shell/main_getenv.c shell/main_unsetenv.c \
shell/main_mkrfs.c shell/main_debugrfs.c \
+ shell/main_lsof.c \
shell/shell-wait-for-input.c
if LIBNETWORKING
diff --git a/cpukit/libmisc/shell/main_lsof.c b/cpukit/libmisc/shell/main_lsof.c
new file mode 100644
index 0000000000..993d107da8
--- /dev/null
+++ b/cpukit/libmisc/shell/main_lsof.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+
+static void lsof(void)
+{
+ rtems_chain_control *mt_chain = &rtems_filesystem_mount_table;
+ rtems_chain_node *mt_node = NULL;
+
+ for (
+ mt_node = rtems_chain_first( mt_chain );
+ !rtems_chain_is_tail( mt_chain, mt_node );
+ mt_node = rtems_chain_next( mt_node )
+ ) {
+ rtems_filesystem_mount_table_entry_t *mt_entry =
+ (rtems_filesystem_mount_table_entry_t *) mt_node;
+ rtems_chain_control *mt_entry_chain = &mt_entry->location_chain;
+ rtems_chain_node *mt_entry_node = NULL;
+
+ printk(
+ "%c %c %s %s -> %s root 0x%08x -> 0x%08x\n",
+ mt_entry->mounted ? 'M' : 'U',
+ mt_entry->writeable ? 'W' : 'R',
+ mt_entry->type,
+ mt_entry->target,
+ mt_entry->dev,
+ mt_entry->mt_fs_root,
+ mt_entry->mt_fs_root->location.node_access
+ );
+
+ for (
+ mt_entry_node = rtems_chain_first( mt_entry_chain );
+ !rtems_chain_is_tail( mt_entry_chain, mt_entry_node );
+ mt_entry_node = rtems_chain_next( mt_entry_node )
+ ) {
+ const rtems_filesystem_location_info_t *loc =
+ (rtems_filesystem_location_info_t *) mt_entry_node;
+
+ printk(
+ "\t0x%08x -> 0x%08x\n",
+ loc,
+ loc->node_access
+ );
+ }
+ }
+}
+
+static int rtems_shell_main_lsof(int argc, char **argv)
+{
+ lsof();
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_LSOF_Command = {
+ .name = "lsof",
+ .usage = "lsof",
+ .topic = "files",
+ .command = rtems_shell_main_lsof
+};
diff --git a/cpukit/libmisc/shell/shellconfig.h b/cpukit/libmisc/shell/shellconfig.h
index 971df25b22..85fb3d0a6d 100644
--- a/cpukit/libmisc/shell/shellconfig.h
+++ b/cpukit/libmisc/shell/shellconfig.h
@@ -61,6 +61,7 @@ extern rtems_shell_cmd_t rtems_shell_RM_Command;
extern rtems_shell_cmd_t rtems_shell_LN_Command;
extern rtems_shell_cmd_t rtems_shell_MKNOD_Command;
extern rtems_shell_cmd_t rtems_shell_UMASK_Command;
+extern rtems_shell_cmd_t rtems_shell_LSOF_Command;
extern rtems_shell_cmd_t rtems_shell_MOUNT_Command;
extern rtems_shell_cmd_t rtems_shell_UNMOUNT_Command;
extern rtems_shell_cmd_t rtems_shell_BLKSYNC_Command;
@@ -329,6 +330,11 @@ extern rtems_shell_alias_t *rtems_shell_Initial_aliases[];
&rtems_shell_UMASK_Command,
#endif
#if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_LSOF)) || \
+ defined(CONFIGURE_SHELL_COMMAND_LSOF)
+ &rtems_shell_LSOF_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
!defined(CONFIGURE_SHELL_NO_COMMAND_MOUNT)) || \
defined(CONFIGURE_SHELL_COMMAND_MOUNT)
&rtems_shell_MOUNT_Command,
diff --git a/cpukit/libnetworking/lib/ftpfs.c b/cpukit/libnetworking/lib/ftpfs.c
index e588bc41ad..b50890e4c9 100644
--- a/cpukit/libnetworking/lib/ftpfs.c
+++ b/cpukit/libnetworking/lib/ftpfs.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2009, 2010, 2011
+ * Copyright (c) 2009-2012
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
@@ -54,7 +54,7 @@
#include <rtems.h>
#include <rtems/ftpfs.h>
#include <rtems/imfs.h>
-#include <rtems/libio.h>
+#include <rtems/libio_.h>
#include <rtems/rtems_bsdnet.h>
#include <rtems/seterr.h>
@@ -939,8 +939,8 @@ static int rtems_ftpfs_open_data_connection_passive(
static int rtems_ftpfs_open(
rtems_libio_t *iop,
const char *path,
- uint32_t flags,
- uint32_t mode
+ int oflag,
+ mode_t mode
)
{
int eno = 0;
@@ -962,11 +962,6 @@ static int rtems_ftpfs_open(
/* Invalidate data handle */
iop->data1 = NULL;
- /* Check location, it was allocated during path evaluation */
- if (location == NULL) {
- rtems_set_errno_and_return_minus_one(ENOMEM);
- }
-
/* Split location into parts */
ok = rtems_ftpfs_split_names(
location,
@@ -976,17 +971,7 @@ static int rtems_ftpfs_open(
&filename
);
if (!ok) {
- if (strlen(location) == 0) {
- /*
- * This is an access to the root node that will be used for file system
- * option settings.
- */
- iop->pathinfo.handlers = &rtems_ftpfs_root_handlers;
-
- return 0;
- } else {
- rtems_set_errno_and_return_minus_one(ENOENT);
- }
+ rtems_set_errno_and_return_minus_one(ENOENT);
}
DEBUG_PRINTF(
"user = '%s', password = '%s', filename = '%s'\n",
@@ -1154,39 +1139,40 @@ static int rtems_ftpfs_ftruncate(rtems_libio_t *iop, off_t count)
return 0;
}
-static int rtems_ftpfs_eval_path(
- const char *pathname,
- size_t pathnamelen,
- int flags,
- rtems_filesystem_location_info_t *pathloc
+static void rtems_ftpfs_eval_path(
+ rtems_filesystem_eval_path_context_t *self
)
{
- /*
- * The caller of this routine has striped off the mount prefix from the path.
- * We need to store this path here or otherwise we would have to do this job
- * again. The path is used in rtems_ftpfs_open() via iop->pathinfo.node_access.
- */
- char *pathname_dup = malloc(pathnamelen + 1);
+ rtems_filesystem_eval_path_eat_delimiter(self);
- if (pathname_dup != NULL) {
- memcpy(pathname_dup, pathname, pathnamelen);
- pathname_dup [pathnamelen] = '\0';
- }
+ if (rtems_filesystem_eval_path_has_path(self)) {
+ const char *path = rtems_filesystem_eval_path_get_path(self);
+ size_t pathlen = rtems_filesystem_eval_path_get_pathlen(self);
+ char *pathdup = malloc(pathlen + 1);
- pathloc->node_access = pathname_dup;
+ rtems_filesystem_eval_path_clear_path(self);
- return 0;
+ if (pathdup != NULL) {
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc(self);
+
+ memcpy(pathdup, path, pathlen);
+ pathdup [pathlen] = '\0';
+ currentloc->node_access = pathdup;
+ currentloc->handlers = &rtems_ftpfs_handlers;
+ } else {
+ rtems_filesystem_eval_path_error(self, ENOMEM);
+ }
+ }
}
-static int rtems_ftpfs_free_node(rtems_filesystem_location_info_t *pathloc)
+static void rtems_ftpfs_free_node(const rtems_filesystem_location_info_t *loc)
{
- free(pathloc->node_access);
-
- return 0;
+ free(loc->node_access);
}
static rtems_filesystem_node_types_t rtems_ftpfs_node_type(
- rtems_filesystem_location_info_t *pathloc
+ const rtems_filesystem_location_info_t *loc
)
{
return RTEMS_FILESYSTEM_MEMORY_FILE;
@@ -1209,11 +1195,11 @@ int rtems_ftpfs_initialize(
me->timeout.tv_usec = 0;
/* Set handler and oparations table */
- e->mt_fs_root.handlers = &rtems_ftpfs_handlers;
- e->mt_fs_root.ops = &rtems_ftpfs_ops;
+ e->mt_fs_root->location.handlers = &rtems_ftpfs_root_handlers;
+ e->mt_fs_root->location.ops = &rtems_ftpfs_ops;
/* We maintain no real file system nodes, so there is no real root */
- e->mt_fs_root.node_access = NULL;
+ e->mt_fs_root->location.node_access = NULL;
/* Just use the limits from IMFS */
e->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
@@ -1221,13 +1207,11 @@ int rtems_ftpfs_initialize(
return 0;
}
-static int rtems_ftpfs_unmount_me(
+static void rtems_ftpfs_unmount_me(
rtems_filesystem_mount_table_entry_t *e
)
{
free(e->fs_info);
-
- return 0;
}
static int rtems_ftpfs_ioctl(
@@ -1271,14 +1255,12 @@ static int rtems_ftpfs_ioctl(
* a remote to remote copy. This is not a very sophisticated method.
*/
static int rtems_ftpfs_fstat(
- rtems_filesystem_location_info_t *loc,
+ const rtems_filesystem_location_info_t *loc,
struct stat *st
)
{
static unsigned ino = 0;
- memset(st, 0, sizeof(*st));
-
/* FIXME */
st->st_ino = ++ino;
st->st_dev = rtems_filesystem_make_dev_t(0xcc494cd6U, 0x1d970b4dU);
@@ -1289,22 +1271,27 @@ static int rtems_ftpfs_fstat(
}
static const rtems_filesystem_operations_table rtems_ftpfs_ops = {
- .evalpath_h = rtems_ftpfs_eval_path,
- .evalformake_h = rtems_filesystem_default_evalformake,
+ .lock_h = rtems_filesystem_default_lock,
+ .unlock_h = rtems_filesystem_default_unlock,
+ .eval_path_h = rtems_ftpfs_eval_path,
.link_h = rtems_filesystem_default_link,
- .unlink_h = rtems_filesystem_default_unlink,
+ .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
.node_type_h = rtems_ftpfs_node_type,
.mknod_h = rtems_filesystem_default_mknod,
+ .rmnod_h = rtems_filesystem_default_rmnod,
+ .fchmod_h = rtems_filesystem_default_fchmod,
.chown_h = rtems_filesystem_default_chown,
+ .clonenod_h = rtems_filesystem_default_clonenode,
.freenod_h = rtems_ftpfs_free_node,
.mount_h = rtems_filesystem_default_mount,
.fsmount_me_h = rtems_ftpfs_initialize,
.unmount_h = rtems_filesystem_default_unmount,
.fsunmount_me_h = rtems_ftpfs_unmount_me,
.utime_h = rtems_filesystem_default_utime,
- .eval_link_h = rtems_filesystem_default_evaluate_link,
.symlink_h = rtems_filesystem_default_symlink,
- .readlink_h = rtems_filesystem_default_readlink
+ .readlink_h = rtems_filesystem_default_readlink,
+ .rename_h = rtems_filesystem_default_rename,
+ .statvfs_h = rtems_filesystem_default_statvfs
};
static const rtems_filesystem_file_handlers_r rtems_ftpfs_handlers = {
@@ -1315,12 +1302,10 @@ static const rtems_filesystem_file_handlers_r rtems_ftpfs_handlers = {
.ioctl_h = rtems_filesystem_default_ioctl,
.lseek_h = rtems_filesystem_default_lseek,
.fstat_h = rtems_ftpfs_fstat,
- .fchmod_h = rtems_filesystem_default_fchmod,
.ftruncate_h = rtems_ftpfs_ftruncate,
.fsync_h = rtems_filesystem_default_fsync,
.fdatasync_h = rtems_filesystem_default_fdatasync,
- .fcntl_h = rtems_filesystem_default_fcntl,
- .rmnod_h = rtems_filesystem_default_rmnod
+ .fcntl_h = rtems_filesystem_default_fcntl
};
static const rtems_filesystem_file_handlers_r rtems_ftpfs_root_handlers = {
@@ -1331,10 +1316,8 @@ static const rtems_filesystem_file_handlers_r rtems_ftpfs_root_handlers = {
.ioctl_h = rtems_ftpfs_ioctl,
.lseek_h = rtems_filesystem_default_lseek,
.fstat_h = rtems_filesystem_default_fstat,
- .fchmod_h = rtems_filesystem_default_fchmod,
.ftruncate_h = rtems_filesystem_default_ftruncate,
.fsync_h = rtems_filesystem_default_fsync,
.fdatasync_h = rtems_filesystem_default_fdatasync,
- .fcntl_h = rtems_filesystem_default_fcntl,
- .rmnod_h = rtems_filesystem_default_rmnod
+ .fcntl_h = rtems_filesystem_default_fcntl
};
diff --git a/cpukit/libnetworking/lib/tftpDriver.c b/cpukit/libnetworking/lib/tftpDriver.c
index c5e6c6b075..0e284c1e5c 100644
--- a/cpukit/libnetworking/lib/tftpDriver.c
+++ b/cpukit/libnetworking/lib/tftpDriver.c
@@ -9,6 +9,9 @@
* Saskatoon, Saskatchewan, CANADA
* eric@skatter.usask.ca
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* $Id$
*
*/
@@ -146,13 +149,6 @@ struct tftpStream {
#define TFTPFS_VERBOSE (1 << 0)
/*
- * Root node_access value
- * By using the address of the file system
- * we ensure a unique value for this identifier.
- */
-#define ROOT_NODE_ACCESS(_fs) (_fs)
-
-/*
* TFTP File system info.
*/
typedef struct tftpfs_info_s {
@@ -170,39 +166,48 @@ typedef struct tftpfs_info_s {
* Number of streams open at the same time
*/
-typedef const char *tftp_node;
static const rtems_filesystem_operations_table rtems_tftp_ops;
static const rtems_filesystem_file_handlers_r rtems_tftp_handlers;
+static bool rtems_tftp_is_directory(
+ const char *path,
+ size_t pathlen
+)
+{
+ return path [pathlen - 1] == '/';
+}
+
int rtems_tftpfs_initialize(
rtems_filesystem_mount_table_entry_t *mt_entry,
const void *data
)
{
- tftpfs_info_t *fs;
rtems_status_code sc;
+ const char *device = mt_entry->dev;
+ size_t devicelen = strlen (device);
+ tftpfs_info_t *fs;
+ char *root_path;
- mt_entry->mt_fs_root.handlers = &rtems_tftp_handlers;
- mt_entry->mt_fs_root.ops = &rtems_tftp_ops;
+ if (devicelen == 0)
+ rtems_set_errno_and_return_minus_one (ENXIO);
- /*
- * We have no tftp filesystem specific data to maintain. This
- * filesystem may only be mounted ONCE.
- *
- * And we maintain no real filesystem nodes, so there is no real root.
- */
+ fs = malloc (sizeof (*fs));
+ root_path = malloc (devicelen + 2);
+ if (root_path == NULL || fs == NULL)
+ goto error;
- fs = malloc (sizeof (tftpfs_info_t));
- if (!fs)
- rtems_set_errno_and_return_minus_one (ENOMEM);
+ root_path = memcpy (root_path, device, devicelen);
+ root_path [devicelen] = '/';
+ root_path [devicelen + 1] = '\0';
fs->flags = 0;
fs->nStreams = 0;
fs->tftpStreams = 0;
- mt_entry->fs_info = fs;
- mt_entry->mt_fs_root.node_access = ROOT_NODE_ACCESS (fs);
- mt_entry->mt_fs_root.node_access_2 = NULL;
+ mt_entry->fs_info = fs;
+ mt_entry->mt_fs_root->location.node_access = root_path;
+ mt_entry->mt_fs_root->location.handlers = &rtems_tftp_handlers;
+ mt_entry->mt_fs_root->location.ops = &rtems_tftp_ops;
/*
* Now allocate a semaphore for mutual exclusion.
@@ -223,7 +228,7 @@ int rtems_tftpfs_initialize(
);
if (sc != RTEMS_SUCCESSFUL)
- rtems_set_errno_and_return_minus_one (ENOMEM);
+ goto error;
if (data) {
char* config = (char*) data;
@@ -238,6 +243,13 @@ int rtems_tftpfs_initialize(
}
return 0;
+
+error:
+
+ free (fs);
+ free (root_path);
+
+ rtems_set_errno_and_return_minus_one (ENOMEM);
}
/*
@@ -254,7 +266,7 @@ releaseStream (tftpfs_info_t *fs, int s)
rtems_semaphore_release (fs->tftp_mutex);
}
-static int
+static void
rtems_tftpfs_shutdown (rtems_filesystem_mount_table_entry_t* mt_entry)
{
tftpfs_info_t *fs = tftpfs_info_mount_table (mt_entry);
@@ -263,7 +275,7 @@ rtems_tftpfs_shutdown (rtems_filesystem_mount_table_entry_t* mt_entry)
releaseStream (fs, s);
rtems_semaphore_delete (fs->tftp_mutex);
free (fs);
- return 0;
+ free (mt_entry->mt_fs_root->location.node_access);
}
/*
@@ -418,17 +430,6 @@ sendAck (struct tftpStream *tp)
return 0;
}
-static int rtems_tftp_evaluate_for_make(
- const char *path __attribute__((unused)), /* IN */
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- const char **name __attribute__((unused)) /* OUT */
-)
-{
- pathloc->node_access = NULL;
- pathloc->node_access_2 = NULL;
- rtems_set_errno_and_return_minus_one (EIO);
-}
-
/*
* Convert a path to canonical form
*/
@@ -483,62 +484,41 @@ fixPath (char *path)
return;
}
-static int rtems_tftp_eval_path(
- const char *pathname, /* IN */
- size_t pathnamelen, /* IN */
- int flags, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
-)
+static void rtems_tftp_eval_path(rtems_filesystem_eval_path_context_t *self)
{
- tftpfs_info_t *fs;
- char *cp;
-
- /*
- * Get the file system info.
- */
- fs = tftpfs_info_pathloc (pathloc);
-
- pathloc->handlers = &rtems_tftp_handlers;
-
- /*
- * Hack to provide the illusion of directories inside the TFTP file system.
- * Paths ending in a / are assumed to be directories.
- */
- if (pathname[strlen(pathname)-1] == '/') {
- int nal = 0;
- if (pathloc->node_access != ROOT_NODE_ACCESS (fs))
- nal = strlen(pathloc->node_access);
- cp = malloc(nal + pathnamelen + 1);
- if (cp == NULL)
- rtems_set_errno_and_return_minus_one(ENOMEM);
- if (nal)
- memcpy (cp, pathloc->node_access, nal);
- memcpy(cp + nal, pathname, pathnamelen);
- cp[nal + pathnamelen] = '\0';
- fixPath (cp);
- pathloc->node_access = cp;
- }
- else {
- if (pathnamelen) {
- /*
- * Reject it if it's not read-only or write-only.
- */
- flags &= RTEMS_LIBIO_PERMS_READ | RTEMS_LIBIO_PERMS_WRITE;
- if ((flags != RTEMS_LIBIO_PERMS_READ) \
- && (flags != RTEMS_LIBIO_PERMS_WRITE))
- rtems_set_errno_and_return_minus_one(EINVAL);
-
- cp = malloc(pathnamelen + 1);
- if (cp == NULL)
- rtems_set_errno_and_return_minus_one(ENOMEM);
- memcpy(cp, pathname, pathnamelen);
- cp[pathnamelen] = '\0';
- fixPath (cp);
- pathloc->node_access_2 = cp;
+ int eval_flags = rtems_filesystem_eval_path_get_flags (self);
+
+ if ((eval_flags & RTEMS_LIBIO_MAKE) == 0) {
+ int rw = RTEMS_LIBIO_PERMS_READ | RTEMS_LIBIO_PERMS_WRITE;
+
+ if ((eval_flags & rw) != rw) {
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc (self);
+ char *current = currentloc->node_access;
+ size_t currentlen = strlen (current);
+ const char *path = rtems_filesystem_eval_path_get_path (self);
+ size_t pathlen = rtems_filesystem_eval_path_get_pathlen (self);
+ size_t len = currentlen + pathlen;
+
+ rtems_filesystem_eval_path_clear_path (self);
+
+ current = realloc (current, len + 1);
+ if (current != NULL) {
+ memcpy (current + currentlen, path, pathlen);
+ current [len] = '\0';
+ if (!rtems_tftp_is_directory (current, len)) {
+ fixPath (current);
+ }
+ currentloc->node_access = current;
+ } else {
+ rtems_filesystem_eval_path_error (self, ENOMEM);
+ }
+ } else {
+ rtems_filesystem_eval_path_error (self, EINVAL);
}
+ } else {
+ rtems_filesystem_eval_path_error (self, EIO);
}
-
- return 0;
}
/*
@@ -547,8 +527,7 @@ static int rtems_tftp_eval_path(
static int rtems_tftp_open_worker(
rtems_libio_t *iop,
char *full_path_name,
- uint32_t flags,
- uint32_t mode __attribute__((unused))
+ int oflag
)
{
tftpfs_info_t *fs;
@@ -680,7 +659,7 @@ static int rtems_tftp_open_worker(
/*
* Create the request
*/
- if ((flags & O_ACCMODE) == O_RDONLY) {
+ if ((oflag & O_ACCMODE) == O_RDONLY) {
tp->writing = 0;
tp->pkbuf.tftpRWRQ.opcode = htons (TFTP_OPCODE_RRQ);
}
@@ -751,91 +730,37 @@ static int rtems_tftp_open_worker(
return 0;
}
-/*
- * The IMFS open handler
- */
static int rtems_tftp_open(
rtems_libio_t *iop,
const char *new_name,
- uint32_t flags,
- uint32_t mode
+ int oflag,
+ mode_t mode
)
{
tftpfs_info_t *fs;
- const char *device;
char *full_path_name;
- char *na;
- char *na2;
- int dlen;
- int nalen;
- int na2len;
- int sep1;
int err;
+ full_path_name = iop->pathinfo.node_access;
+
+ if (rtems_tftp_is_directory (full_path_name, strlen (full_path_name))) {
+ rtems_set_errno_and_return_minus_one (ENOTSUP);
+ }
+
/*
* Get the file system info.
*/
fs = tftpfs_info_iop (iop);
-
- /*
- * Tack the prefix directory if one exists from the device name.
- */
- device =
- rtems_filesystem_mount_device (rtems_filesystem_location_mount (&iop->pathinfo));
- dlen = strlen (device);
- if (dlen == 0)
- rtems_set_errno_and_return_minus_one (ENOENT);
-
- if (iop->pathinfo.node_access_2 == NULL)
- rtems_set_errno_and_return_minus_one (ENOENT);
-
- if (iop->pathinfo.node_access != ROOT_NODE_ACCESS (fs)) {
- na = iop->pathinfo.node_access;
- nalen = strlen (na);
- }
- else {
- na = NULL;
- nalen = 0;
- }
-
- na2 = iop->pathinfo.node_access_2;
-
- na2len = strlen (na2);
-
- if (nalen) {
- sep1 = 1;
- if (na[nalen] == '/') {
- sep1 = 0;
- if (na2[0] == '/')
- ++na2;
- }
- else {
- if (na2[0] == '/')
- sep1 = 0;
- else
- sep1 = 1;
- }
- }
- else
- sep1 = 0;
-
- full_path_name = malloc (dlen + nalen + sep1 + na2len + 1);
- if (full_path_name == NULL)
- rtems_set_errno_and_return_minus_one(ENOMEM);
- strcpy (full_path_name, device);
- if (nalen)
- strcat (full_path_name, na);
- if (sep1)
- strcat (full_path_name, "/");
- strcat (full_path_name, na2);
- fixPath (full_path_name);
if (fs->flags & TFTPFS_VERBOSE)
- printf ("TFTPFS: %s %s %s -> %s\n", device, na, na2, full_path_name);
+ printf ("TFTPFS: %s\n", full_path_name);
- err = rtems_tftp_open_worker (iop, full_path_name, flags, mode);
- free (full_path_name);
- rtems_set_errno_and_return_minus_one(err);
+ err = rtems_tftp_open_worker (iop, full_path_name, oflag);
+ if (err != 0) {
+ rtems_set_errno_and_return_minus_one (err);
+ }
+
+ return 0;
}
/*
@@ -1051,52 +976,70 @@ static int rtems_tftp_ftruncate(
}
static rtems_filesystem_node_types_t rtems_tftp_node_type(
- rtems_filesystem_location_info_t *pathloc /* IN */
+ const rtems_filesystem_location_info_t *loc
)
{
- tftpfs_info_t *fs = tftpfs_info_pathloc (pathloc);
- if ((pathloc->node_access == NULL)
- || (pathloc->node_access_2 != NULL)
- || (pathloc->node_access == ROOT_NODE_ACCESS (fs)))
- return RTEMS_FILESYSTEM_MEMORY_FILE;
- return RTEMS_FILESYSTEM_DIRECTORY;
+ const char *path = loc->node_access;
+ size_t pathlen = strlen (path);
+
+ return rtems_tftp_is_directory (path, pathlen) ?
+ RTEMS_FILESYSTEM_DIRECTORY
+ : RTEMS_FILESYSTEM_MEMORY_FILE;
}
-static int rtems_tftp_free_node_info(
- rtems_filesystem_location_info_t *pathloc /* IN */
+static int rtems_tftp_clone(
+ rtems_filesystem_location_info_t *loc
)
{
- tftpfs_info_t *fs = tftpfs_info_pathloc (pathloc);
- if (pathloc->node_access && \
- (pathloc->node_access != ROOT_NODE_ACCESS (fs))) {
- free (pathloc->node_access);
- pathloc->node_access = NULL;
- }
- if (pathloc->node_access_2) {
- free (pathloc->node_access_2);
- pathloc->node_access_2 = NULL;
+ int rv = 0;
+
+ loc->node_access = strdup (loc->node_access);
+
+ if (loc->node_access == NULL) {
+ errno = ENOMEM;
+ rv = -1;
}
- return 0;
+
+ return rv;
}
+static void rtems_tftp_free_node_info(
+ const rtems_filesystem_location_info_t *loc
+)
+{
+ free (loc->node_access);
+}
+
+static bool rtems_tftp_are_nodes_equal(
+ const rtems_filesystem_location_info_t *a,
+ const rtems_filesystem_location_info_t *b
+)
+{
+ return strcmp (a->node_access, b->node_access) == 0;
+}
static const rtems_filesystem_operations_table rtems_tftp_ops = {
- .evalpath_h = rtems_tftp_eval_path,
- .evalformake_h = rtems_tftp_evaluate_for_make,
+ .lock_h = rtems_filesystem_default_lock,
+ .unlock_h = rtems_filesystem_default_unlock,
+ .eval_path_h = rtems_tftp_eval_path,
.link_h = rtems_filesystem_default_link,
- .unlink_h = rtems_filesystem_default_unlink,
+ .are_nodes_equal_h = rtems_tftp_are_nodes_equal,
.node_type_h = rtems_tftp_node_type,
.mknod_h = rtems_filesystem_default_mknod,
+ .rmnod_h = rtems_filesystem_default_rmnod,
+ .fchmod_h = rtems_filesystem_default_fchmod,
.chown_h = rtems_filesystem_default_chown,
+ .clonenod_h = rtems_tftp_clone,
.freenod_h = rtems_tftp_free_node_info,
.mount_h = rtems_filesystem_default_mount,
.fsmount_me_h = rtems_tftpfs_initialize,
.unmount_h = rtems_filesystem_default_unmount,
.fsunmount_me_h = rtems_tftpfs_shutdown,
.utime_h = rtems_filesystem_default_utime,
- .eval_link_h = rtems_filesystem_default_evaluate_link,
.symlink_h = rtems_filesystem_default_symlink,
- .readlink_h = rtems_filesystem_default_readlink
+ .readlink_h = rtems_filesystem_default_readlink,
+ .rename_h = rtems_filesystem_default_rename,
+ .statvfs_h = rtems_filesystem_default_statvfs
};
static const rtems_filesystem_file_handlers_r rtems_tftp_handlers = {
@@ -1107,10 +1050,8 @@ static const rtems_filesystem_file_handlers_r rtems_tftp_handlers = {
.ioctl_h = rtems_filesystem_default_ioctl,
.lseek_h = rtems_filesystem_default_lseek,
.fstat_h = rtems_filesystem_default_fstat,
- .fchmod_h = rtems_filesystem_default_fchmod,
.ftruncate_h = rtems_tftp_ftruncate,
.fsync_h = rtems_filesystem_default_fsync,
.fdatasync_h = rtems_filesystem_default_fdatasync,
- .fcntl_h = rtems_filesystem_default_fcntl,
- .rmnod_h = rtems_filesystem_default_rmnod
+ .fcntl_h = rtems_filesystem_default_fcntl
};
diff --git a/cpukit/libnetworking/rtems/rtems_bsdnet_internal.h b/cpukit/libnetworking/rtems/rtems_bsdnet_internal.h
index c8bdfd4b44..3e1ce72455 100644
--- a/cpukit/libnetworking/rtems/rtems_bsdnet_internal.h
+++ b/cpukit/libnetworking/rtems/rtems_bsdnet_internal.h
@@ -13,6 +13,7 @@
#define _RTEMS_RTEMS_BSDNET_INTERNAL_H
#include <rtems.h>
+#include <rtems/fs.h>
#ifdef __cplusplus
extern "C" {
@@ -198,6 +199,10 @@ int ioctl (int, ioctl_command_t, ...);
# error "Network event conflict"
#endif
+int rtems_bsdnet_makeFdForSocket(
+ void *so, const rtems_filesystem_file_handlers_r *h);
+struct socket *rtems_bsdnet_fdToSocket(int fd);
+
#ifdef __cplusplus
}
#endif
diff --git a/cpukit/libnetworking/rtems/rtems_syscall.c b/cpukit/libnetworking/rtems/rtems_syscall.c
index a5d724afbe..f043e094f4 100644
--- a/cpukit/libnetworking/rtems/rtems_syscall.c
+++ b/cpukit/libnetworking/rtems/rtems_syscall.c
@@ -42,9 +42,6 @@ ssize_t recv(int, void *, size_t, int);
* Hooks to RTEMS I/O system
*/
static const rtems_filesystem_file_handlers_r socket_handlers;
-int rtems_bsdnet_makeFdForSocket(
- void *so, const rtems_filesystem_file_handlers_r *h);
-struct socket *rtems_bsdnet_fdToSocket(int fd);
/*
* Package system call argument into mbuf.
@@ -738,7 +735,7 @@ rtems_bsdnet_ioctl (rtems_libio_t *iop, uint32_t command, void *buffer)
}
static int
-rtems_bsdnet_fcntl (int cmd, rtems_libio_t *iop)
+rtems_bsdnet_fcntl (rtems_libio_t *iop, int cmd)
{
struct socket *so;
@@ -758,7 +755,7 @@ rtems_bsdnet_fcntl (int cmd, rtems_libio_t *iop)
}
static int
-rtems_bsdnet_fstat (rtems_filesystem_location_info_t *loc, struct stat *sp)
+rtems_bsdnet_fstat (const rtems_filesystem_location_info_t *loc, struct stat *sp)
{
sp->st_mode = S_IFSOCK;
return 0;
@@ -772,10 +769,8 @@ static const rtems_filesystem_file_handlers_r socket_handlers = {
rtems_bsdnet_ioctl, /* ioctl */
rtems_filesystem_default_lseek, /* lseek */
rtems_bsdnet_fstat, /* fstat */
- rtems_filesystem_default_fchmod, /* fchmod */
rtems_filesystem_default_ftruncate, /* ftruncate */
rtems_filesystem_default_fsync, /* fsync */
rtems_filesystem_default_fdatasync, /* fdatasync */
- rtems_bsdnet_fcntl, /* fcntl */
- rtems_filesystem_default_rmnod /* rmnod */
+ rtems_bsdnet_fcntl /* fcntl */
};
diff --git a/cpukit/posix/src/sysconf.c b/cpukit/posix/src/sysconf.c
index 3d64e2843f..5874661336 100644
--- a/cpukit/posix/src/sysconf.c
+++ b/cpukit/posix/src/sysconf.c
@@ -45,6 +45,9 @@ long sysconf(
if ( name == _SC_PAGESIZE )
return PAGE_SIZE;
+ if ( name == _SC_SYMLOOP_MAX )
+ return RTEMS_FILESYSTEM_SYMLOOP_MAX;
+
#if defined(__sparc__)
if ( name == 515 ) /* Solaris _SC_STACK_PROT */
return 0;
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index 89e6b5c094..8f03c876a9 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -428,9 +428,7 @@ rtems_fs_init_functions_t rtems_fs_init_helper =
* the bsp overwrides this. In which case the value is set
* to BSP_MAXIMUM_DEVICES.
*/
- #if defined(CONFIGURE_APPLICATION_DISABLE_FILESYSTEM)
- #define CONFIGURE_MEMORY_FOR_DEVFS 0
- #elif defined(CONFIGURE_FILESYSTEM_DEVFS)
+ #ifdef CONFIGURE_FILESYSTEM_DEVFS
#ifndef CONFIGURE_MAXIMUM_DEVICES
#if defined(BSP_MAXIMUM_DEVICES)
#define CONFIGURE_MAXIMUM_DEVICES BSP_MAXIMUM_DEVICES
@@ -439,12 +437,6 @@ rtems_fs_init_functions_t rtems_fs_init_helper =
#endif
#endif
#include <rtems/devfs.h>
- uint32_t rtems_device_table_size = CONFIGURE_MAXIMUM_DEVICES;
- #define CONFIGURE_MEMORY_FOR_DEVFS \
- _Configure_Object_RAM(CONFIGURE_MAXIMUM_DEVICES, \
- sizeof (rtems_device_name_t))
- #else
- #define CONFIGURE_MEMORY_FOR_DEVFS 0
#endif
#ifndef RTEMS_SCHEDSIM
@@ -503,23 +495,31 @@ rtems_fs_init_functions_t rtems_fs_init_helper =
#endif
#ifndef CONFIGURE_HAS_OWN_MOUNT_TABLE
- extern const rtems_filesystem_mount_table_t configuration_mount_table;
- const rtems_filesystem_mount_table_t configuration_mount_table = {
+ #if defined(CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM)
+ static devFS_node devFS_root_filesystem_nodes [CONFIGURE_MAXIMUM_DEVICES];
+ static const devFS_data devFS_root_filesystem_data = {
+ devFS_root_filesystem_nodes,
+ CONFIGURE_MAXIMUM_DEVICES
+ };
+ #endif
+ const rtems_filesystem_mount_configuration
+ rtems_filesystem_root_configuration = {
+ NULL,
+ NULL,
#if defined(CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM)
RTEMS_FILESYSTEM_TYPE_DEVFS,
#elif defined(CONFIGURE_USE_MINIIMFS_AS_BASE_FILESYSTEM)
RTEMS_FILESYSTEM_TYPE_MINIIMFS,
- #else /* using IMFS as base filesystem */
+ #else
RTEMS_FILESYSTEM_TYPE_IMFS,
#endif
RTEMS_FILESYSTEM_READ_WRITE,
- NULL,
- NULL
+ #if defined(CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM)
+ &devFS_root_filesystem_data
+ #else
+ NULL
+ #endif
};
-
- const rtems_filesystem_mount_table_t
- *rtems_filesystem_mount_table = &configuration_mount_table;
- const int rtems_filesystem_mount_table_size = 1;
#endif
#endif
@@ -2020,7 +2020,6 @@ rtems_fs_init_functions_t rtems_fs_init_helper =
#define CONFIGURE_EXECUTIVE_RAM_SIZE \
(( \
CONFIGURE_MEMORY_FOR_SYSTEM_OVERHEAD + \
- CONFIGURE_MEMORY_FOR_DEVFS + \
CONFIGURE_MEMORY_FOR_TASKS( \
CONFIGURE_TOTAL_TASKS_AND_THREADS, CONFIGURE_TOTAL_TASKS_AND_THREADS) + \
CONFIGURE_MEMORY_FOR_CLASSIC + \