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