From f78549221be6d9142263b70e246ec6adf1d58ba9 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Sat, 14 Feb 2015 20:07:19 +0100 Subject: IMFS: Add CONFIGURE_IMFS_DISABLE_READDIR --- cpukit/libfs/Makefile.am | 6 +- cpukit/libfs/src/imfs/imfs.h | 30 ++--- cpukit/libfs/src/imfs/imfs_dir.c | 52 +++++++++ cpukit/libfs/src/imfs/imfs_dir_default.c | 143 ++++++++++++++++++++++++ cpukit/libfs/src/imfs/imfs_dir_minimal.c | 48 ++++++++ cpukit/libfs/src/imfs/imfs_directory.c | 88 --------------- cpukit/libfs/src/imfs/imfs_handlers_directory.c | 113 ------------------- cpukit/libfs/src/imfs/imfs_init.c | 2 +- cpukit/sapi/include/confdefs.h | 6 +- doc/user/conf.t | 27 +++++ testsuites/fstests/fsimfsconfig01/init.c | 20 ++++ 11 files changed, 309 insertions(+), 226 deletions(-) create mode 100644 cpukit/libfs/src/imfs/imfs_dir.c create mode 100644 cpukit/libfs/src/imfs/imfs_dir_default.c create mode 100644 cpukit/libfs/src/imfs/imfs_dir_minimal.c delete mode 100644 cpukit/libfs/src/imfs/imfs_directory.c delete mode 100644 cpukit/libfs/src/imfs/imfs_handlers_directory.c diff --git a/cpukit/libfs/Makefile.am b/cpukit/libfs/Makefile.am index 802dfdb141..531e080cb7 100644 --- a/cpukit/libfs/Makefile.am +++ b/cpukit/libfs/Makefile.am @@ -42,13 +42,15 @@ libimfs_a_SOURCES = libimfs_a_SOURCES += src/imfs/deviceio.c \ src/imfs/imfs_chown.c src/imfs/imfs_config.c \ - src/imfs/imfs_creat.c src/imfs/imfs_directory.c \ + src/imfs/imfs_creat.c \ src/imfs/imfs_eval.c src/imfs/imfs_fchmod.c \ + src/imfs/imfs_dir.c \ + src/imfs/imfs_dir_default.c \ + src/imfs/imfs_dir_minimal.c \ src/imfs/imfs_fifo.c \ src/imfs/imfs_make_generic_node.c \ src/imfs/imfs_fsunmount.c \ src/imfs/imfs_handlers_device.c \ - src/imfs/imfs_handlers_directory.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_linfile.c \ diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h index c03257a0fa..2a1eddcfcc 100644 --- a/cpukit/libfs/src/imfs/imfs.h +++ b/cpukit/libfs/src/imfs/imfs.h @@ -135,6 +135,11 @@ IMFS_jnode_t *IMFS_node_initialize_default( void *arg ); +IMFS_jnode_t *IMFS_node_initialize_directory( + IMFS_jnode_t *node, + void *arg +); + /** * @brief Returns the node and sets the generic node context. * @@ -179,6 +184,8 @@ IMFS_jnode_t *IMFS_node_remove_default( IMFS_jnode_t *node ); +IMFS_jnode_t *IMFS_node_remove_directory( IMFS_jnode_t *node ); + /** * @brief Destroys an IMFS node. * @@ -384,7 +391,8 @@ typedef struct { * Shared Data */ -extern const IMFS_mknod_control IMFS_mknod_control_directory; +extern const IMFS_mknod_control IMFS_mknod_control_dir_default; +extern const IMFS_mknod_control IMFS_mknod_control_dir_minimal; extern const IMFS_mknod_control IMFS_mknod_control_device; extern const IMFS_mknod_control IMFS_mknod_control_memfile; extern const IMFS_node_control IMFS_node_control_linfile; @@ -699,26 +707,6 @@ extern int IMFS_unmount( rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ ); -/** - * @brief Read the next directory of the IMFS. - * - * This routine will read the next directory entry based on the directory - * offset. The offset should be equal to -n- time the size of an individual - * dirent structure. If n is not an integer multiple of the sizeof a - * dirent structure, an integer division will be performed to determine - * directory entry that will be returned in the buffer. Count should reflect - * -m- times the sizeof dirent bytes to be placed in the buffer. - * If there are not -m- dirent elements from the current directory position - * to the end of the exisiting file, the remaining entries will be placed in - * the buffer and the returned value will be equal to -m actual- times the - * size of a directory entry. - */ -extern ssize_t imfs_dir_read( - rtems_libio_t *iop, /* IN */ - void *buffer, /* IN */ - size_t count /* IN */ -); - /** * @name IMFS Memory File Handlers * diff --git a/cpukit/libfs/src/imfs/imfs_dir.c b/cpukit/libfs/src/imfs/imfs_dir.c new file mode 100644 index 0000000000..2aefc936b4 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_dir.c @@ -0,0 +1,52 @@ +/** + * @file + * + * @ingroup IMFS + */ + +/* + * 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.org/license/LICENSE. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include "imfs.h" + +IMFS_jnode_t *IMFS_node_initialize_directory( + IMFS_jnode_t *node, + void *arg +) +{ + IMFS_directory_t *dir = (IMFS_directory_t *) node; + + rtems_chain_initialize_empty( &dir->Entries ); + + return node; +} + +static bool IMFS_is_mount_point( const IMFS_directory_t *dir ) +{ + return dir->mt_fs != NULL; +} + +IMFS_jnode_t *IMFS_node_remove_directory( IMFS_jnode_t *node ) +{ + IMFS_directory_t *dir = (IMFS_directory_t *) node; + + if ( !rtems_chain_is_empty( &dir->Entries ) ) { + errno = ENOTEMPTY; + dir = NULL; + } else if ( IMFS_is_mount_point( dir ) ) { + errno = EBUSY; + dir = NULL; + } + + return &dir->Node; +} diff --git a/cpukit/libfs/src/imfs/imfs_dir_default.c b/cpukit/libfs/src/imfs/imfs_dir_default.c new file mode 100644 index 0000000000..98f06dfce4 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_dir_default.c @@ -0,0 +1,143 @@ +/** + * @file + * + * @ingroup IMFS + */ + +/* + * 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.org/license/LICENSE. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include "imfs.h" + +#include +#include + +static ssize_t IMFS_dir_read( + rtems_libio_t *iop, + void *buffer, + size_t count +) +{ + /* + * Read up to element iop->offset in the directory chain of the + * imfs_jnode_t struct for this file descriptor. + */ + const IMFS_directory_t *dir; + const rtems_chain_node *node; + const rtems_chain_control *entries; + struct dirent *dir_ent; + ssize_t bytes_transferred; + off_t current_entry; + off_t first_entry; + off_t last_entry; + + rtems_filesystem_instance_lock( &iop->pathinfo ); + + dir = IMFS_iop_to_directory( iop ); + entries = &dir->Entries; + + /* Move to the first of the desired directory entries */ + + bytes_transferred = 0; + first_entry = iop->offset; + /* protect against using sizes that are not exact multiples of the */ + /* -dirent- size. These could result in unexpected results */ + last_entry = first_entry + + (count / sizeof( *dir_ent )) * sizeof( *dir_ent ); + + /* The directory was not empty so try to move to the desired entry in chain*/ + for ( + current_entry = 0, + node = rtems_chain_immutable_first( entries ); + current_entry < last_entry + && !rtems_chain_is_tail( entries, node ); + current_entry += sizeof( *dir_ent ), + node = rtems_chain_immutable_next( node ) + ) { + if( current_entry >= first_entry ) { + const IMFS_jnode_t *imfs_node = (const IMFS_jnode_t *) node; + + dir_ent = (struct dirent *) ((char *) buffer + bytes_transferred); + + /* Move the entry to the return buffer */ + dir_ent->d_off = current_entry; + dir_ent->d_reclen = sizeof( *dir_ent ); + dir_ent->d_ino = IMFS_node_to_ino( imfs_node ); + dir_ent->d_namlen = strlen( imfs_node->name ); + memcpy( dir_ent->d_name, imfs_node->name, dir_ent->d_namlen + 1 ); + + iop->offset += sizeof( *dir_ent ); + bytes_transferred += (ssize_t) sizeof( *dir_ent ); + } + } + + rtems_filesystem_instance_unlock( &iop->pathinfo ); + + return bytes_transferred; +} + +static size_t IMFS_directory_size( const IMFS_jnode_t *node ) +{ + size_t size = 0; + const IMFS_directory_t *dir = (const IMFS_directory_t *) node; + const rtems_chain_control *chain = &dir->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; +} + +static int IMFS_stat_directory( + const rtems_filesystem_location_info_t *loc, + struct stat *buf +) +{ + const IMFS_jnode_t *node = loc->node_access; + + buf->st_size = IMFS_directory_size( node ); + + return IMFS_stat( loc, buf ); +} + +static const rtems_filesystem_file_handlers_r IMFS_dir_default_handlers = { + .open_h = rtems_filesystem_default_open, + .close_h = rtems_filesystem_default_close, + .read_h = IMFS_dir_read, + .write_h = rtems_filesystem_default_write, + .ioctl_h = rtems_filesystem_default_ioctl, + .lseek_h = rtems_filesystem_default_lseek_directory, + .fstat_h = IMFS_stat_directory, + .ftruncate_h = rtems_filesystem_default_ftruncate_directory, + .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success, + .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success, + .fcntl_h = rtems_filesystem_default_fcntl, + .kqfilter_h = rtems_filesystem_default_kqfilter, + .poll_h = rtems_filesystem_default_poll, + .readv_h = rtems_filesystem_default_readv, + .writev_h = rtems_filesystem_default_writev +}; + +const IMFS_mknod_control IMFS_mknod_control_dir_default = { + { + .handlers = &IMFS_dir_default_handlers, + .node_initialize = IMFS_node_initialize_directory, + .node_remove = IMFS_node_remove_directory, + .node_destroy = IMFS_node_destroy_default + }, + .node_size = sizeof( IMFS_directory_t ) +}; diff --git a/cpukit/libfs/src/imfs/imfs_dir_minimal.c b/cpukit/libfs/src/imfs/imfs_dir_minimal.c new file mode 100644 index 0000000000..3ef5173535 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_dir_minimal.c @@ -0,0 +1,48 @@ +/** + * @file + * + * @ingroup IMFS + */ + +/* + * 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.org/license/LICENSE. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include "imfs.h" + +static const rtems_filesystem_file_handlers_r IMFS_dir_minimal_handlers = { + .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_directory, + .fstat_h = IMFS_stat, + .ftruncate_h = rtems_filesystem_default_ftruncate_directory, + .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success, + .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success, + .fcntl_h = rtems_filesystem_default_fcntl, + .kqfilter_h = rtems_filesystem_default_kqfilter, + .poll_h = rtems_filesystem_default_poll, + .readv_h = rtems_filesystem_default_readv, + .writev_h = rtems_filesystem_default_writev +}; + +const IMFS_mknod_control IMFS_mknod_control_dir_minimal = { + { + .handlers = &IMFS_dir_minimal_handlers, + .node_initialize = IMFS_node_initialize_directory, + .node_remove = IMFS_node_remove_directory, + .node_destroy = IMFS_node_destroy_default + }, + .node_size = sizeof( IMFS_directory_t ) +}; diff --git a/cpukit/libfs/src/imfs/imfs_directory.c b/cpukit/libfs/src/imfs/imfs_directory.c deleted file mode 100644 index 5769e0741b..0000000000 --- a/cpukit/libfs/src/imfs/imfs_directory.c +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @file - * - * @brief IMFS Read Next Directory - * @ingroup IMFS - */ - -/* - * 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.org/license/LICENSE. - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "imfs.h" - -#include -#include - -ssize_t imfs_dir_read( - rtems_libio_t *iop, - void *buffer, - size_t count -) -{ - /* - * Read up to element iop->offset in the directory chain of the - * imfs_jnode_t struct for this file descriptor. - */ - const IMFS_directory_t *dir; - const rtems_chain_node *node; - const rtems_chain_control *entries; - struct dirent *dir_ent; - ssize_t bytes_transferred; - off_t current_entry; - off_t first_entry; - off_t last_entry; - - rtems_filesystem_instance_lock( &iop->pathinfo ); - - dir = IMFS_iop_to_directory( iop ); - entries = &dir->Entries; - - /* Move to the first of the desired directory entries */ - - bytes_transferred = 0; - first_entry = iop->offset; - /* protect against using sizes that are not exact multiples of the */ - /* -dirent- size. These could result in unexpected results */ - last_entry = first_entry - + (count / sizeof( *dir_ent )) * sizeof( *dir_ent ); - - /* The directory was not empty so try to move to the desired entry in chain*/ - for ( - current_entry = 0, - node = rtems_chain_immutable_first( entries ); - current_entry < last_entry - && !rtems_chain_is_tail( entries, node ); - current_entry += sizeof( *dir_ent ), - node = rtems_chain_immutable_next( node ) - ) { - if( current_entry >= first_entry ) { - const IMFS_jnode_t *imfs_node = (const IMFS_jnode_t *) node; - - dir_ent = (struct dirent *) ((char *) buffer + bytes_transferred); - - /* Move the entry to the return buffer */ - dir_ent->d_off = current_entry; - dir_ent->d_reclen = sizeof( *dir_ent ); - dir_ent->d_ino = IMFS_node_to_ino( imfs_node ); - dir_ent->d_namlen = strlen( imfs_node->name ); - memcpy( dir_ent->d_name, imfs_node->name, dir_ent->d_namlen + 1 ); - - iop->offset += sizeof( *dir_ent ); - bytes_transferred += (ssize_t) sizeof( *dir_ent ); - } - } - - rtems_filesystem_instance_unlock( &iop->pathinfo ); - - return bytes_transferred; -} diff --git a/cpukit/libfs/src/imfs/imfs_handlers_directory.c b/cpukit/libfs/src/imfs/imfs_handlers_directory.c deleted file mode 100644 index bcfe3e7365..0000000000 --- a/cpukit/libfs/src/imfs/imfs_handlers_directory.c +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @file - * - * @brief Operations Table for Directories - * @ingroup IMFS - */ - -/* - * 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.org/license/LICENSE. - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "imfs.h" - -#include - -static size_t IMFS_directory_size( const IMFS_jnode_t *node ) -{ - size_t size = 0; - const IMFS_directory_t *dir = (const IMFS_directory_t *) node; - const rtems_chain_control *chain = &dir->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; -} - -static int IMFS_stat_directory( - const rtems_filesystem_location_info_t *loc, - struct stat *buf -) -{ - const IMFS_jnode_t *node = loc->node_access; - - buf->st_size = IMFS_directory_size( node ); - - return IMFS_stat( loc, buf ); -} - -static const rtems_filesystem_file_handlers_r IMFS_directory_handlers = { - .open_h = rtems_filesystem_default_open, - .close_h = rtems_filesystem_default_close, - .read_h = imfs_dir_read, - .write_h = rtems_filesystem_default_write, - .ioctl_h = rtems_filesystem_default_ioctl, - .lseek_h = rtems_filesystem_default_lseek_directory, - .fstat_h = IMFS_stat_directory, - .ftruncate_h = rtems_filesystem_default_ftruncate_directory, - .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success, - .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success, - .fcntl_h = rtems_filesystem_default_fcntl, - .kqfilter_h = rtems_filesystem_default_kqfilter, - .poll_h = rtems_filesystem_default_poll, - .readv_h = rtems_filesystem_default_readv, - .writev_h = rtems_filesystem_default_writev -}; - -static IMFS_jnode_t *IMFS_node_initialize_directory( - IMFS_jnode_t *node, - void *arg -) -{ - IMFS_directory_t *dir = (IMFS_directory_t *) node; - - rtems_chain_initialize_empty( &dir->Entries ); - - return node; -} - -static bool IMFS_is_mount_point( const IMFS_directory_t *dir ) -{ - return dir->mt_fs != NULL; -} - -static IMFS_jnode_t *IMFS_node_remove_directory( - IMFS_jnode_t *node -) -{ - IMFS_directory_t *dir = (IMFS_directory_t *) node; - - if ( !rtems_chain_is_empty( &dir->Entries ) ) { - errno = ENOTEMPTY; - dir = NULL; - } else if ( IMFS_is_mount_point( dir ) ) { - errno = EBUSY; - dir = NULL; - } - - return &dir->Node; -} - -const IMFS_mknod_control IMFS_mknod_control_directory = { - { - .handlers = &IMFS_directory_handlers, - .node_initialize = IMFS_node_initialize_directory, - .node_remove = IMFS_node_remove_directory, - .node_destroy = IMFS_node_destroy_default - }, - .node_size = sizeof( IMFS_directory_t ) -}; diff --git a/cpukit/libfs/src/imfs/imfs_init.c b/cpukit/libfs/src/imfs/imfs_init.c index bbab2cb3e1..da4c0a8cfb 100644 --- a/cpukit/libfs/src/imfs/imfs_init.c +++ b/cpukit/libfs/src/imfs/imfs_init.c @@ -48,7 +48,7 @@ static const rtems_filesystem_operations_table IMFS_ops = { }; static const IMFS_mknod_controls IMFS_default_mknod_controls = { - .directory = &IMFS_mknod_control_directory, + .directory = &IMFS_mknod_control_dir_default, .device = &IMFS_mknod_control_device, .file = &IMFS_mknod_control_memfile, .fifo = &IMFS_mknod_control_enosys diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h index 580a1380aa..7d9e3b9e08 100644 --- a/cpukit/sapi/include/confdefs.h +++ b/cpukit/sapi/include/confdefs.h @@ -619,7 +619,11 @@ const rtems_libio_helper rtems_fs_init_helper = }; static const IMFS_mknod_controls _Configure_IMFS_mknod_controls = { - &IMFS_mknod_control_directory, + #ifdef CONFIGURE_IMFS_DISABLE_READDIR + &IMFS_mknod_control_dir_minimal, + #else + &IMFS_mknod_control_dir_default, + #endif &IMFS_mknod_control_device, #ifdef CONFIGURE_IMFS_DISABLE_MKNOD_FILE &IMFS_mknod_control_enosys, diff --git a/doc/user/conf.t b/doc/user/conf.t index f6b203f73b..dc10816909 100644 --- a/doc/user/conf.t +++ b/doc/user/conf.t @@ -2894,6 +2894,33 @@ This is not defined by default. In case this configuration option is defined, then the support to rename nodes is disabled in the root IMFS. +@c +@c === CONFIGURE_IMFS_DISABLE_READDIR === +@c +@subsection Disable Directory Read Support of Root IMFS + +@findex CONFIGURE_IMFS_DISABLE_READDIR + +@table @b +@item CONSTANT: +@code{CONFIGURE_IMFS_DISABLE_READDIR} + +@item DATA TYPE: +Boolean feature macro. + +@item RANGE: +Defined or undefined. + +@item DEFAULT VALUE: +This is not defined by default. + +@end table + +@subheading DESCRIPTION: +In case this configuration option is defined, then the support to read a +directory is disabled in the root IMFS. It is still possible to open nodes in +a directory. + @c @c === CONFIGURE_IMFS_DISABLE_MOUNT === @c diff --git a/testsuites/fstests/fsimfsconfig01/init.c b/testsuites/fstests/fsimfsconfig01/init.c index 1d449d6828..dd587fae4c 100644 --- a/testsuites/fstests/fsimfsconfig01/init.c +++ b/testsuites/fstests/fsimfsconfig01/init.c @@ -19,6 +19,7 @@ #include "tmacros.h" #include +#include #include #include #include @@ -46,6 +47,9 @@ static void Init(rtems_task_argument arg) const char *fifo = "fifo"; int rv; int fd; + DIR *dirp; + struct dirent *dire; + struct stat st; TEST_BEGIN(); @@ -88,6 +92,21 @@ static void Init(rtems_task_argument arg) rtems_test_assert(rv == -1); rtems_test_assert(errno == ENOSYS); + dirp = opendir(mnt); + rtems_test_assert(dirp != NULL); + + errno = 0; + dire = readdir(dirp); + rtems_test_assert(dire == NULL); + rtems_test_assert(errno == ENOTSUP); + + rv = closedir(dirp); + rtems_test_assert(rv == 0); + + rv = stat(mnt, &st); + rtems_test_assert(rv == 0); + rtems_test_assert(st.st_size == 0); + errno = 0; rv = mount( "", @@ -145,6 +164,7 @@ static void Init(rtems_task_argument arg) #define CONFIGURE_IMFS_DISABLE_MKNOD_FILE #define CONFIGURE_IMFS_DISABLE_MOUNT #define CONFIGURE_IMFS_DISABLE_RENAME +#define CONFIGURE_IMFS_DISABLE_READDIR #define CONFIGURE_IMFS_DISABLE_RMNOD #define CONFIGURE_IMFS_DISABLE_SYMLINK #define CONFIGURE_IMFS_DISABLE_UTIME -- cgit v1.2.3