diff options
-rw-r--r-- | cpukit/libfs/Makefile.am | 1 | ||||
-rw-r--r-- | cpukit/libfs/src/imfs/imfs.h | 46 | ||||
-rw-r--r-- | cpukit/libfs/src/imfs/imfs_make_generic_node.c | 108 | ||||
-rw-r--r-- | testsuites/fstests/Makefile.am | 1 | ||||
-rw-r--r-- | testsuites/fstests/configure.ac | 1 | ||||
-rw-r--r-- | testsuites/fstests/fsimfsgeneric01/Makefile.am | 20 | ||||
-rw-r--r-- | testsuites/fstests/fsimfsgeneric01/fsimfsgeneric01.doc | 11 | ||||
-rw-r--r-- | testsuites/fstests/fsimfsgeneric01/fsimfsgeneric01.scn | 2 | ||||
-rw-r--r-- | testsuites/fstests/fsimfsgeneric01/init.c | 408 |
9 files changed, 598 insertions, 0 deletions
diff --git a/cpukit/libfs/Makefile.am b/cpukit/libfs/Makefile.am index 342f5eb063..c629bc99a1 100644 --- a/cpukit/libfs/Makefile.am +++ b/cpukit/libfs/Makefile.am @@ -45,6 +45,7 @@ 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_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_handlers_link.c \ diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h index ae247c5833..eca8824ca3 100644 --- a/cpukit/libfs/src/imfs/imfs.h +++ b/cpukit/libfs/src/imfs/imfs.h @@ -56,6 +56,10 @@ typedef struct { pipe_control_t *pipe; } IMFS_fifo_t; +typedef struct { + void *context; +} IMFS_generic_t; + /* * IMFS "memfile" information * @@ -133,9 +137,11 @@ typedef enum { IMFS_MEMORY_FILE = RTEMS_FILESYSTEM_MEMORY_FILE, IMFS_LINEAR_FILE, IMFS_FIFO, + IMFS_GENERIC, IMFS_INVALID_NODE } IMFS_jnode_types_t; +/* The IMFS_GENERIC does not count */ #define IMFS_TYPE_COUNT (IMFS_FIFO + 1) typedef union { @@ -146,6 +152,7 @@ typedef union { IMFS_memfile_t file; IMFS_linearfile_t linearfile; IMFS_fifo_t fifo; + IMFS_generic_t generic; } IMFS_types_union; typedef IMFS_jnode_t *(*IMFS_node_control_initialize)( @@ -158,6 +165,11 @@ IMFS_jnode_t *IMFS_node_initialize_default( const IMFS_types_union *info ); +IMFS_jnode_t *IMFS_node_initialize_generic( + IMFS_jnode_t *node, + const IMFS_types_union *info +); + typedef IMFS_jnode_t *(*IMFS_node_control_remove)( IMFS_jnode_t *node, const IMFS_jnode_t *root_node @@ -370,6 +382,17 @@ extern IMFS_jnode_t *IMFS_create_node_with_control( const IMFS_types_union *info ); +extern bool IMFS_is_imfs_instance( + const rtems_filesystem_location_info_t *loc +); + +extern int IMFS_make_generic_node( + const char *path, + mode_t mode, + const IMFS_node_control *node_control, + void *context +); + extern int IMFS_mount( rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ ); @@ -573,6 +596,29 @@ static inline IMFS_jnode_t *IMFS_create_node( ); } +static inline void *IMFS_generic_get_context_by_node( + const IMFS_jnode_t *node +) +{ + return node->info.generic.context; +} + +static inline void *IMFS_generic_get_context_by_location( + const rtems_filesystem_location_info_t *loc +) +{ + const IMFS_jnode_t *node = (const IMFS_jnode_t *) loc->node_access; + + return IMFS_generic_get_context_by_node( node ); +} + +static inline void *IMFS_generic_get_context_by_iop( + const rtems_libio_t *iop +) +{ + return IMFS_generic_get_context_by_location( &iop->pathinfo ); +} + #ifdef __cplusplus } #endif diff --git a/cpukit/libfs/src/imfs/imfs_make_generic_node.c b/cpukit/libfs/src/imfs/imfs_make_generic_node.c new file mode 100644 index 0000000000..5b7a7d9cec --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_make_generic_node.c @@ -0,0 +1,108 @@ +/* + * 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 "imfs.h" + +IMFS_jnode_t *IMFS_node_initialize_generic( + IMFS_jnode_t *node, + const IMFS_types_union *info +) +{ + node->info.generic.context = info->generic.context; + + return node; +} + +bool IMFS_is_imfs_instance( + const rtems_filesystem_location_info_t *loc +) +{ + const char *type = loc->mt_entry->type; + + return strcmp(type, RTEMS_FILESYSTEM_TYPE_IMFS) == 0 + || strcmp(type, RTEMS_FILESYSTEM_TYPE_MINIIMFS) == 0; +} + +int IMFS_make_generic_node( + const char *path, + mode_t mode, + const IMFS_node_control *node_control, + void *context +) +{ + int rv = 0; + + mode &= ~rtems_filesystem_umask; + + switch (mode & S_IFMT) { + case S_IFBLK: + case S_IFCHR: + case S_IFIFO: + case S_IFREG: + break; + default: + errno = EINVAL; + rv = -1; + break; + } + + if ( rv == 0 ) { + if ( node_control->imfs_type == IMFS_GENERIC ) { + rtems_filesystem_eval_path_context_t ctx; + int eval_flags = RTEMS_FS_FOLLOW_LINK + | RTEMS_FS_MAKE + | RTEMS_FS_EXCLUSIVE; + const rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); + + if ( IMFS_is_imfs_instance( currentloc ) ) { + IMFS_types_union info; + IMFS_jnode_t *new_node; + + info.generic.context = context; + new_node = IMFS_create_node_with_control( + currentloc, + node_control, + rtems_filesystem_eval_path_get_token( &ctx ), + rtems_filesystem_eval_path_get_tokenlen( &ctx ), + mode, + &info + ); + + if ( new_node != NULL ) { + IMFS_jnode_t *parent = currentloc->node_access; + + IMFS_update_ctime( parent ); + IMFS_update_mtime( parent ); + } else { + rv = -1; + } + } else { + rtems_filesystem_eval_path_error( &ctx, ENOTSUP ); + rv = -1; + } + + rtems_filesystem_eval_path_cleanup( &ctx ); + } else { + errno = EINVAL; + rv = -1; + } + } + + return rv; +} diff --git a/testsuites/fstests/Makefile.am b/testsuites/fstests/Makefile.am index 535862b4a2..d731eb6591 100644 --- a/testsuites/fstests/Makefile.am +++ b/testsuites/fstests/Makefile.am @@ -31,6 +31,7 @@ SUBDIRS += mrfs_fsrdwr SUBDIRS += mrfs_fssymlink SUBDIRS += mrfs_fstime SUBDIRS += fsnofs01 +SUBDIRS += fsimfsgeneric01 EXTRA_DIST = EXTRA_DIST += support/ramdisk_support.c diff --git a/testsuites/fstests/configure.ac b/testsuites/fstests/configure.ac index ce3bdf7ebe..f2ca983699 100644 --- a/testsuites/fstests/configure.ac +++ b/testsuites/fstests/configure.ac @@ -105,6 +105,7 @@ mrfs_fsrdwr/Makefile mrfs_fssymlink/Makefile mrfs_fstime/Makefile fsnofs01/Makefile +fsimfsgeneric01/Makefile ]) AC_OUTPUT diff --git a/testsuites/fstests/fsimfsgeneric01/Makefile.am b/testsuites/fstests/fsimfsgeneric01/Makefile.am new file mode 100644 index 0000000000..e8ab9f40a7 --- /dev/null +++ b/testsuites/fstests/fsimfsgeneric01/Makefile.am @@ -0,0 +1,20 @@ +rtems_tests_PROGRAMS = fsimfsgeneric01 +fsimfsgeneric01_SOURCES = init.c + +dist_rtems_tests_DATA = fsimfsgeneric01.scn fsimfsgeneric01.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(fsimfsgeneric01_OBJECTS) +LINK_LIBS = $(fsimfsgeneric01_LDLIBS) + +fsimfsgeneric01$(EXEEXT): $(fsimfsgeneric01_OBJECTS) $(fsimfsgeneric01_DEPENDENCIES) + @rm -f fsimfsgeneric01$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/fstests/fsimfsgeneric01/fsimfsgeneric01.doc b/testsuites/fstests/fsimfsgeneric01/fsimfsgeneric01.doc new file mode 100644 index 0000000000..120fccb1c7 --- /dev/null +++ b/testsuites/fstests/fsimfsgeneric01/fsimfsgeneric01.doc @@ -0,0 +1,11 @@ +This file describes the directives and concepts tested by this test set. + +test set name: fsimfsgeneric01 + +directives: + + IMFS_IMFS_make_generic_node + +concepts: + + TBD diff --git a/testsuites/fstests/fsimfsgeneric01/fsimfsgeneric01.scn b/testsuites/fstests/fsimfsgeneric01/fsimfsgeneric01.scn new file mode 100644 index 0000000000..fa34addb2f --- /dev/null +++ b/testsuites/fstests/fsimfsgeneric01/fsimfsgeneric01.scn @@ -0,0 +1,2 @@ +*** TEST FSIMFSGENERIC 1 *** +*** END OF TEST FSIMFSGENERIC 1 *** diff --git a/testsuites/fstests/fsimfsgeneric01/init.c b/testsuites/fstests/fsimfsgeneric01/init.c new file mode 100644 index 0000000000..d7abad3ee2 --- /dev/null +++ b/testsuites/fstests/fsimfsgeneric01/init.c @@ -0,0 +1,408 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include "tmacros.h" + +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#include <rtems/imfs.h> +#include <rtems/malloc.h> + +typedef enum { + TEST_NEW, + TEST_INITIALIZED, + TEST_FSTAT_OPEN, + TEST_OPEN, + TEST_READ, + TEST_WRITE, + TEST_IOCTL, + TEST_LSEEK, + TEST_FTRUNCATE, + TEST_FSYNC, + TEST_FDATASYNC, + TEST_FCNTL, + TEST_CLOSED, + TEST_FSTAT_UNLINK, + TEST_REMOVED, + TEST_DESTROYED +} test_state; + +static test_state global_state = TEST_NEW; + +static int handler_open( + rtems_libio_t *iop, + const char *path, + int oflag, + mode_t mode +) +{ + test_state *state = IMFS_generic_get_context_by_iop(iop); + + rtems_test_assert(*state == TEST_FSTAT_OPEN); + *state = TEST_OPEN; + + return 0; +} + +static int handler_close( + rtems_libio_t *iop +) +{ + test_state *state = IMFS_generic_get_context_by_iop(iop); + + rtems_test_assert(*state == TEST_FCNTL); + *state = TEST_CLOSED; + + return 0; +} + +static ssize_t handler_read( + rtems_libio_t *iop, + void *buffer, + size_t count +) +{ + test_state *state = IMFS_generic_get_context_by_iop(iop); + + rtems_test_assert(*state == TEST_OPEN); + *state = TEST_READ; + + return 0; +} + +static ssize_t handler_write( + rtems_libio_t *iop, + const void *buffer, + size_t count +) +{ + test_state *state = IMFS_generic_get_context_by_iop(iop); + + rtems_test_assert(*state == TEST_READ); + *state = TEST_WRITE; + + return 0; +} + +static int handler_ioctl( + rtems_libio_t *iop, + uint32_t request, + void *buffer +) +{ + test_state *state = IMFS_generic_get_context_by_iop(iop); + + rtems_test_assert(*state == TEST_WRITE); + *state = TEST_IOCTL; + + return 0; +} + +static off_t handler_lseek( + rtems_libio_t *iop, + off_t length, + int whence +) +{ + test_state *state = IMFS_generic_get_context_by_iop(iop); + + rtems_test_assert(*state == TEST_IOCTL); + *state = TEST_LSEEK; + + return 0; +} + +static int handler_fstat( + const rtems_filesystem_location_info_t *loc, + struct stat *buf +) +{ + test_state *state = IMFS_generic_get_context_by_location(loc); + + switch (*state) { + case TEST_INITIALIZED: + *state = TEST_FSTAT_OPEN; + break; + case TEST_CLOSED: + *state = TEST_FSTAT_UNLINK; + break; + default: + rtems_test_assert(0); + break; + } + + return rtems_filesystem_default_fstat(loc, buf); +} + +static int handler_ftruncate( + rtems_libio_t *iop, + off_t length +) +{ + test_state *state = IMFS_generic_get_context_by_iop(iop); + + rtems_test_assert(*state == TEST_LSEEK); + *state = TEST_FTRUNCATE; + + return 0; +} + +static int handler_fsync( + rtems_libio_t *iop +) +{ + test_state *state = IMFS_generic_get_context_by_iop(iop); + + rtems_test_assert(*state == TEST_FTRUNCATE); + *state = TEST_FSYNC; + + return 0; +} + +static int handler_fdatasync( + rtems_libio_t *iop +) +{ + test_state *state = IMFS_generic_get_context_by_iop(iop); + + rtems_test_assert(*state == TEST_FSYNC); + *state = TEST_FDATASYNC; + + return 0; +} + +static int handler_fcntl( + rtems_libio_t *iop, + int cmd +) +{ + test_state *state = IMFS_generic_get_context_by_iop(iop); + + rtems_test_assert(*state == TEST_FDATASYNC); + *state = TEST_FCNTL; + + return 0; +} + +static const rtems_filesystem_file_handlers_r node_handlers = { + .open_h = handler_open, + .close_h = handler_close, + .read_h = handler_read, + .write_h = handler_write, + .ioctl_h = handler_ioctl, + .lseek_h = handler_lseek, + .fstat_h = handler_fstat, + .ftruncate_h = handler_ftruncate, + .fsync_h = handler_fsync, + .fdatasync_h = handler_fdatasync, + .fcntl_h = handler_fcntl +}; + +static IMFS_jnode_t *node_initialize( + IMFS_jnode_t *node, + const IMFS_types_union *info +) +{ + test_state *state = NULL; + + node = IMFS_node_initialize_generic(node, info); + state = IMFS_generic_get_context_by_node(node); + + rtems_test_assert(*state == TEST_NEW); + *state = TEST_INITIALIZED; + + return node; +} + +static IMFS_jnode_t *node_remove( + IMFS_jnode_t *node, + const IMFS_jnode_t *root_node +) +{ + test_state *state = IMFS_generic_get_context_by_node(node); + + rtems_test_assert(*state == TEST_FSTAT_UNLINK); + *state = TEST_REMOVED; + + return node; +} + +static IMFS_jnode_t *node_destroy(IMFS_jnode_t *node) +{ + test_state *state = IMFS_generic_get_context_by_node(node); + + rtems_test_assert(*state == TEST_REMOVED); + *state = TEST_DESTROYED; + + return node; +} + +static const IMFS_node_control node_control = { + .imfs_type = IMFS_GENERIC, + .handlers = &node_handlers, + .node_initialize = node_initialize, + .node_remove = node_remove, + .node_destroy = node_destroy +}; + +static void test_imfs_make_generic_node(void) +{ + int rv = 0; + int fd = 0; + const char *path = "generic"; + char buf [1]; + ssize_t n = 0; + off_t off = 0; + + rv = IMFS_make_generic_node( + path, + S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, + &node_control, + &global_state + ); + rtems_test_assert(rv == 0); + + fd = open(path, O_RDWR); + rtems_test_assert(fd >= 0); + + n = read(fd, buf, sizeof(buf)); + rtems_test_assert(n == 0); + + n = write(fd, buf, sizeof(buf)); + rtems_test_assert(n == 0); + + rv = ioctl(fd, 0); + rtems_test_assert(rv == 0); + + off = lseek(fd, off, SEEK_SET); + rtems_test_assert(off == 0); + + rv = ftruncate(fd, 0); + rtems_test_assert(rv == 0); + + rv = fsync(fd); + rtems_test_assert(rv == 0); + + rv = fdatasync(fd); + rtems_test_assert(rv == 0); + + rv = fcntl(fd, F_GETFD); + rtems_test_assert(rv >= 0); + + rv = close(fd); + rtems_test_assert(rv == 0); + + rv = unlink(path); + rtems_test_assert(rv == 0); + + rtems_test_assert(global_state == TEST_DESTROYED); +} + +static const IMFS_node_control node_invalid_control = { + .imfs_type = IMFS_DIRECTORY, + .handlers = &node_handlers, + .node_initialize = node_initialize, + .node_remove = node_remove, + .node_destroy = node_destroy +}; + +static void test_imfs_make_generic_node_errors(void) +{ + int rv = 0; + const char *path = "generic"; + rtems_chain_control *chain = &rtems_filesystem_mount_table; + rtems_filesystem_mount_table_entry_t *mt_entry = + (rtems_filesystem_mount_table_entry_t *) rtems_chain_first(chain); + const char *type = mt_entry->type; + void *opaque = NULL; + + errno = 0; + rv = IMFS_make_generic_node( + path, + S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, + &node_invalid_control, + NULL + ); + rtems_test_assert(rv == -1); + rtems_test_assert(errno == EINVAL); + + errno = 0; + rv = IMFS_make_generic_node( + path, + S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO, + &node_control, + NULL + ); + rtems_test_assert(rv == -1); + rtems_test_assert(errno == EINVAL); + + mt_entry->type = "XXX"; + errno = 0; + rv = IMFS_make_generic_node( + path, + S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, + &node_control, + NULL + ); + rtems_test_assert(rv == -1); + rtems_test_assert(errno == ENOTSUP); + mt_entry->type = type; + + opaque = rtems_heap_greedy_allocate(0); + errno = 0; + rv = IMFS_make_generic_node( + path, + S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, + &node_control, + NULL + ); + rtems_test_assert(rv == -1); + rtems_test_assert(errno == ENOMEM); + rtems_heap_greedy_free(opaque); +} + +static void Init(rtems_task_argument arg) +{ + printf("\n\n*** TEST FSIMFSGENERIC 1 ***\n"); + + test_imfs_make_generic_node(); + test_imfs_make_generic_node_errors(); + + printf("*** END OF TEST FSIMFSGENERIC 1 ***\n"); + + rtems_test_exit(0); +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4 + +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM + +#define CONFIGURE_MAXIMUM_TASKS 1 + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include <rtems/confdefs.h> |