summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/libfs/Makefile.am1
-rw-r--r--cpukit/libfs/src/imfs/imfs.h46
-rw-r--r--cpukit/libfs/src/imfs/imfs_make_generic_node.c108
-rw-r--r--testsuites/fstests/Makefile.am1
-rw-r--r--testsuites/fstests/configure.ac1
-rw-r--r--testsuites/fstests/fsimfsgeneric01/Makefile.am20
-rw-r--r--testsuites/fstests/fsimfsgeneric01/fsimfsgeneric01.doc11
-rw-r--r--testsuites/fstests/fsimfsgeneric01/fsimfsgeneric01.scn2
-rw-r--r--testsuites/fstests/fsimfsgeneric01/init.c408
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>