Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:30

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2012, 2020 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031 
0032 #include <sys/stat.h>
0033 #include <sys/ioctl.h>
0034 #include <sys/uio.h>
0035 #include <fcntl.h>
0036 #include <unistd.h>
0037 #include <errno.h>
0038 
0039 #include <rtems/imfs.h>
0040 #include <rtems/malloc.h>
0041 #include <rtems/libcsupport.h>
0042 
0043 #include <tmacros.h>
0044 
0045 const char rtems_test_name[] = "FSIMFSGENERIC 1";
0046 
0047 typedef enum {
0048   TEST_NEW,
0049   TEST_INITIALIZED,
0050   TEST_FSTAT_OPEN_0,
0051   TEST_FSTAT_OPEN_1,
0052   TEST_OPEN,
0053   TEST_READ,
0054   TEST_WRITE,
0055   TEST_IOCTL,
0056   TEST_LSEEK,
0057   TEST_FTRUNCATE,
0058   TEST_FSYNC,
0059   TEST_FDATASYNC,
0060   TEST_FCNTL,
0061   TEST_READV,
0062   TEST_WRITEV,
0063   TEST_CLOSED,
0064   TEST_FSTAT_UNLINK,
0065   TEST_REMOVED,
0066   TEST_DESTROYED
0067 } test_state;
0068 
0069 static int handler_open(
0070   rtems_libio_t *iop,
0071   const char *path,
0072   int oflag,
0073   mode_t mode
0074 )
0075 {
0076   test_state *state = IMFS_generic_get_context_by_iop(iop);
0077 
0078   rtems_test_assert(*state == TEST_FSTAT_OPEN_1);
0079   *state = TEST_OPEN;
0080 
0081   return 0;
0082 }
0083 
0084 static int handler_close(
0085   rtems_libio_t *iop
0086 )
0087 {
0088   test_state *state = IMFS_generic_get_context_by_iop(iop);
0089 
0090   rtems_test_assert(*state == TEST_WRITEV);
0091   *state = TEST_CLOSED;
0092 
0093   return 0;
0094 }
0095 
0096 static ssize_t handler_read(
0097   rtems_libio_t *iop,
0098   void *buffer,
0099   size_t count
0100 )
0101 {
0102   test_state *state = IMFS_generic_get_context_by_iop(iop);
0103 
0104   rtems_test_assert(*state == TEST_OPEN);
0105   *state = TEST_READ;
0106 
0107   return 0;
0108 }
0109 
0110 static ssize_t handler_write(
0111   rtems_libio_t *iop,
0112   const void *buffer,
0113   size_t count
0114 )
0115 {
0116   test_state *state = IMFS_generic_get_context_by_iop(iop);
0117 
0118   rtems_test_assert(*state == TEST_READ);
0119   *state = TEST_WRITE;
0120 
0121   return 0;
0122 }
0123 
0124 static int handler_ioctl(
0125   rtems_libio_t *iop,
0126   ioctl_command_t request,
0127   void *buffer
0128 )
0129 {
0130   test_state *state = IMFS_generic_get_context_by_iop(iop);
0131 
0132   rtems_test_assert(*state == TEST_WRITE);
0133   *state = TEST_IOCTL;
0134 
0135   return 0;
0136 }
0137 
0138 static off_t handler_lseek(
0139   rtems_libio_t *iop,
0140   off_t length,
0141   int whence
0142 )
0143 {
0144   test_state *state = IMFS_generic_get_context_by_iop(iop);
0145 
0146   rtems_test_assert(*state == TEST_IOCTL);
0147   *state = TEST_LSEEK;
0148 
0149   return 0;
0150 }
0151 
0152 static int handler_fstat(
0153   const rtems_filesystem_location_info_t *loc,
0154   struct stat *buf
0155 )
0156 {
0157   test_state *state = IMFS_generic_get_context_by_location(loc);
0158 
0159   switch (*state) {
0160     case TEST_INITIALIZED:
0161       *state = TEST_FSTAT_OPEN_0;
0162       break;
0163     case TEST_FSTAT_OPEN_0:
0164       *state = TEST_FSTAT_OPEN_1;
0165       break;
0166     case TEST_CLOSED:
0167       *state = TEST_FSTAT_UNLINK;
0168       break;
0169     default:
0170       rtems_test_assert(0);
0171       break;
0172   }
0173 
0174   buf->st_mode = S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO;
0175 
0176   return 0;
0177 }
0178 
0179 static int handler_ftruncate(
0180   rtems_libio_t *iop,
0181   off_t length
0182 )
0183 {
0184   test_state *state = IMFS_generic_get_context_by_iop(iop);
0185 
0186   rtems_test_assert(*state == TEST_LSEEK);
0187   *state = TEST_FTRUNCATE;
0188 
0189   return 0;
0190 }
0191 
0192 static int handler_fsync(
0193   rtems_libio_t *iop
0194 )
0195 {
0196   test_state *state = IMFS_generic_get_context_by_iop(iop);
0197 
0198   rtems_test_assert(*state == TEST_FTRUNCATE);
0199   *state = TEST_FSYNC;
0200 
0201   return 0;
0202 }
0203 
0204 static int handler_fdatasync(
0205   rtems_libio_t *iop
0206 )
0207 {
0208   test_state *state = IMFS_generic_get_context_by_iop(iop);
0209 
0210   rtems_test_assert(*state == TEST_FSYNC);
0211   *state = TEST_FDATASYNC;
0212 
0213   return 0;
0214 }
0215 
0216 static int handler_fcntl(
0217   rtems_libio_t *iop,
0218   int cmd
0219 )
0220 {
0221   test_state *state = IMFS_generic_get_context_by_iop(iop);
0222 
0223   rtems_test_assert(*state == TEST_FDATASYNC);
0224   *state = TEST_FCNTL;
0225 
0226   return 0;
0227 }
0228 
0229 static ssize_t handler_readv(
0230   rtems_libio_t *iop,
0231   const struct iovec *iov,
0232   int iovcnt,
0233   ssize_t total
0234 )
0235 {
0236   test_state *state = IMFS_generic_get_context_by_iop(iop);
0237 
0238   rtems_test_assert(*state == TEST_FCNTL);
0239   *state = TEST_READV;
0240 
0241   return 0;
0242 }
0243 
0244 static ssize_t handler_writev(
0245   rtems_libio_t *iop,
0246   const struct iovec *iov,
0247   int iovcnt,
0248   ssize_t total
0249 )
0250 {
0251   test_state *state = IMFS_generic_get_context_by_iop(iop);
0252 
0253   rtems_test_assert(*state == TEST_READV);
0254   *state = TEST_WRITEV;
0255 
0256   return 0;
0257 }
0258 
0259 static const rtems_filesystem_file_handlers_r node_handlers = {
0260   .open_h = handler_open,
0261   .close_h = handler_close,
0262   .read_h = handler_read,
0263   .write_h = handler_write,
0264   .ioctl_h = handler_ioctl,
0265   .lseek_h = handler_lseek,
0266   .fstat_h = handler_fstat,
0267   .ftruncate_h = handler_ftruncate,
0268   .fsync_h = handler_fsync,
0269   .fdatasync_h = handler_fdatasync,
0270   .fcntl_h = handler_fcntl,
0271   .readv_h = handler_readv,
0272   .writev_h = handler_writev
0273 };
0274 
0275 static IMFS_jnode_t *node_initialize(
0276   IMFS_jnode_t *node,
0277   void *arg
0278 )
0279 {
0280   test_state *state = NULL;
0281 
0282   node = IMFS_node_initialize_generic(node, arg);
0283   state = IMFS_generic_get_context_by_node(node);
0284 
0285   rtems_test_assert(*state == TEST_NEW);
0286   *state = TEST_INITIALIZED;
0287 
0288   return node;
0289 }
0290 
0291 static IMFS_jnode_t *node_remove(IMFS_jnode_t *node)
0292 {
0293   test_state *state = IMFS_generic_get_context_by_node(node);
0294 
0295   rtems_test_assert(*state == TEST_FSTAT_UNLINK);
0296   *state = TEST_REMOVED;
0297 
0298   return node;
0299 }
0300 
0301 static void node_destroy(IMFS_jnode_t *node)
0302 {
0303   test_state *state = IMFS_generic_get_context_by_node(node);
0304 
0305   rtems_test_assert(*state == TEST_REMOVED);
0306   *state = TEST_DESTROYED;
0307 
0308   IMFS_node_destroy_default(node);
0309 }
0310 
0311 static const IMFS_node_control node_control = {
0312   .handlers = &node_handlers,
0313   .node_initialize = node_initialize,
0314   .node_remove = node_remove,
0315   .node_destroy = node_destroy
0316 };
0317 
0318 static void test_node_operations(const char *path)
0319 {
0320   int rv;
0321   int fd;
0322   char buf[1];
0323   ssize_t n;
0324   off_t off;
0325   struct iovec iov = {
0326     .iov_base = &buf[0],
0327     .iov_len = (int) sizeof(buf)
0328   };
0329 
0330   fd = open(path, O_RDWR);
0331   rtems_test_assert(fd >= 0);
0332 
0333   n = read(fd, buf, sizeof(buf));
0334   rtems_test_assert(n == 0);
0335 
0336   n = write(fd, buf, sizeof(buf));
0337   rtems_test_assert(n == 0);
0338 
0339   rv = ioctl(fd, 0);
0340   rtems_test_assert(rv == 0);
0341 
0342   off = lseek(fd, 0, SEEK_SET);
0343   rtems_test_assert(off == 0);
0344 
0345   rv = ftruncate(fd, 0);
0346   rtems_test_assert(rv == 0);
0347 
0348   rv = fsync(fd);
0349   rtems_test_assert(rv == 0);
0350 
0351   rv = fdatasync(fd);
0352   rtems_test_assert(rv == 0);
0353 
0354   rv = fcntl(fd, F_GETFD);
0355   rtems_test_assert(rv >= 0);
0356 
0357   rv = readv(fd, &iov, 1);
0358   rtems_test_assert(rv == 0);
0359 
0360   rv = writev(fd, &iov, 1);
0361   rtems_test_assert(rv == 0);
0362 
0363   rv = close(fd);
0364   rtems_test_assert(rv == 0);
0365 
0366   rv = unlink(path);
0367   rtems_test_assert(rv == 0);
0368 }
0369 
0370 static void test_imfs_make_generic_node(void)
0371 {
0372   static const char path[] = "generic";
0373   test_state state;
0374   int rv;
0375 
0376   state = TEST_NEW;
0377   rv = IMFS_make_generic_node(
0378     path,
0379     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
0380     &node_control,
0381     &state
0382   );
0383   rtems_test_assert(rv == 0);
0384 
0385   test_node_operations(path);
0386   rtems_test_assert(state == TEST_DESTROYED);
0387 }
0388 
0389 static IMFS_jnode_t *node_initialize_error(
0390   IMFS_jnode_t *node,
0391   void *arg
0392 )
0393 {
0394   errno = EIO;
0395 
0396   return NULL;
0397 }
0398 
0399 static IMFS_jnode_t *node_remove_inhibited(IMFS_jnode_t *node)
0400 {
0401   rtems_test_assert(false);
0402 
0403   return node;
0404 }
0405 
0406 static void node_destroy_inhibited(IMFS_jnode_t *node)
0407 {
0408   rtems_test_assert(false);
0409 }
0410 
0411 static const IMFS_node_control node_initialization_error_control = {
0412   .handlers = &node_handlers,
0413   .node_initialize = node_initialize_error,
0414   .node_remove = node_remove_inhibited,
0415   .node_destroy = node_destroy_inhibited
0416 };
0417 
0418 static const rtems_filesystem_operations_table *imfs_ops;
0419 
0420 static int other_clone(rtems_filesystem_location_info_t *loc)
0421 {
0422   return (*imfs_ops->clonenod_h)(loc);
0423 }
0424 
0425 static rtems_filesystem_mount_table_entry_t *get_imfs_mt_entry(void)
0426 {
0427   return (rtems_filesystem_mount_table_entry_t *)
0428     rtems_chain_first(&rtems_filesystem_mount_table);
0429 }
0430 
0431 static void test_imfs_make_generic_node_errors(void)
0432 {
0433   static const char path[] = "generic";
0434   rtems_filesystem_mount_table_entry_t *mt_entry;
0435   rtems_filesystem_operations_table other_ops;
0436   rtems_resource_snapshot before;
0437   void *opaque;
0438   int rv;
0439 
0440   rtems_resource_snapshot_take(&before);
0441 
0442   errno = 0;
0443   rv = IMFS_make_generic_node(
0444     path,
0445     S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO,
0446     &node_control,
0447     NULL
0448   );
0449   rtems_test_assert(rv == -1);
0450   rtems_test_assert(errno == EINVAL);
0451   rtems_test_assert(rtems_resource_snapshot_check(&before));
0452 
0453   errno = 0;
0454   mt_entry = get_imfs_mt_entry();
0455   imfs_ops = mt_entry->ops;
0456   other_ops = *imfs_ops;
0457   other_ops.clonenod_h = other_clone;
0458   mt_entry->ops = &other_ops;
0459   rv = IMFS_make_generic_node(
0460     path,
0461     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
0462     &node_control,
0463     NULL
0464   );
0465   mt_entry->ops = imfs_ops;
0466   rtems_test_assert(rv == -1);
0467   rtems_test_assert(errno == ENOTSUP);
0468   rtems_test_assert(rtems_resource_snapshot_check(&before));
0469 
0470   errno = 0;
0471   opaque = rtems_heap_greedy_allocate(NULL, 0);
0472   rv = IMFS_make_generic_node(
0473     path,
0474     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
0475     &node_control,
0476     NULL
0477   );
0478   rtems_heap_greedy_free(opaque);
0479   rtems_test_assert(rv == -1);
0480   rtems_test_assert(errno == ENOMEM);
0481   rtems_test_assert(rtems_resource_snapshot_check(&before));
0482 
0483   errno = 0;
0484   rv = IMFS_make_generic_node(
0485     path,
0486     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
0487     &node_initialization_error_control,
0488     NULL
0489   );
0490   rtems_test_assert(rv == -1);
0491   rtems_test_assert(errno == EIO);
0492   rtems_test_assert(rtems_resource_snapshot_check(&before));
0493 
0494   errno = 0;
0495   rv = IMFS_make_generic_node(
0496     "/nil/nada",
0497     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
0498     &node_control,
0499     NULL
0500   );
0501   rtems_test_assert(rv == -1);
0502   rtems_test_assert(errno == ENOENT);
0503   rtems_test_assert(rtems_resource_snapshot_check(&before));
0504 }
0505 
0506 static void user_node_destroy(IMFS_jnode_t *node)
0507 {
0508   test_state *state = IMFS_generic_get_context_by_node(node);
0509 
0510   rtems_test_assert(*state == TEST_REMOVED);
0511   *state = TEST_DESTROYED;
0512 }
0513 
0514 static const IMFS_node_control user_node_control = {
0515   .handlers = &node_handlers,
0516   .node_initialize = node_initialize,
0517   .node_remove = node_remove,
0518   .node_destroy = user_node_destroy
0519 };
0520 
0521 static void test_imfs_add_node(void)
0522 {
0523   static const char path[] = "/";
0524   static const char name[] = "node";
0525   size_t namelen = sizeof(name) - 1;
0526   void *opaque;
0527   rtems_resource_snapshot before;
0528   IMFS_generic_t node = IMFS_GENERIC_NODE_INITIALIZER(
0529     &user_node_control,
0530     name,
0531     namelen,
0532     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO
0533   );
0534   test_state state;
0535   int rv;
0536 
0537   /* Ensure that sure no dynamic memory is used */
0538   opaque = rtems_heap_greedy_allocate(NULL, 0);
0539 
0540   rtems_resource_snapshot_take(&before);
0541 
0542   state = TEST_NEW;
0543   rv = IMFS_add_node(path, &node.Node, &state);
0544   rtems_test_assert(rv == 0);
0545 
0546   test_node_operations(name);
0547   rtems_test_assert(state == TEST_DESTROYED);
0548 
0549   rtems_test_assert(rtems_resource_snapshot_check(&before));
0550   rtems_heap_greedy_free(opaque);
0551 }
0552 
0553 static void test_imfs_add_node_errors(void)
0554 {
0555   static const char path[] = "/";
0556   static const char name[] = "node";
0557   size_t namelen = sizeof(name) - 1;
0558   const char invalid_name[] = "/node";
0559   size_t invalid_namelen = sizeof(invalid_name) - 1;
0560   IMFS_jnode_t node = IMFS_NODE_INITIALIZER(
0561     &user_node_control,
0562     name,
0563     namelen,
0564     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO
0565   );
0566   IMFS_jnode_t invalid_mode_node = IMFS_NODE_INITIALIZER(
0567     &user_node_control,
0568     name,
0569     namelen,
0570     S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO
0571   );
0572   IMFS_jnode_t init_error_node = IMFS_NODE_INITIALIZER(
0573     &node_initialization_error_control,
0574     name,
0575     namelen,
0576     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO
0577   );
0578   IMFS_jnode_t invalid_name_node = IMFS_NODE_INITIALIZER(
0579     &user_node_control,
0580     invalid_name,
0581     invalid_namelen,
0582     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO
0583   );
0584   rtems_filesystem_mount_table_entry_t *mt_entry;
0585   rtems_filesystem_operations_table other_ops;
0586   void *opaque;
0587   rtems_resource_snapshot before;
0588   int rv;
0589 
0590   /* Ensure that sure no dynamic memory is used */
0591   opaque = rtems_heap_greedy_allocate(NULL, 0);
0592 
0593   rtems_resource_snapshot_take(&before);
0594 
0595   errno = 0;
0596   rv = IMFS_add_node(path, &invalid_mode_node, NULL);
0597   rtems_test_assert(rv == -1);
0598   rtems_test_assert(errno == EINVAL);
0599   rtems_test_assert(rtems_resource_snapshot_check(&before));
0600 
0601   errno = 0;
0602   mt_entry = get_imfs_mt_entry();
0603   imfs_ops = mt_entry->ops;
0604   other_ops = *imfs_ops;
0605   other_ops.clonenod_h = other_clone;
0606   mt_entry->ops = &other_ops;
0607   rv = IMFS_add_node(path, &node, NULL);
0608   mt_entry->ops = imfs_ops;
0609   rtems_test_assert(rv == -1);
0610   rtems_test_assert(errno == ENOTSUP);
0611   rtems_test_assert(rtems_resource_snapshot_check(&before));
0612 
0613   errno = 0;
0614   rv = IMFS_add_node(path, &init_error_node, NULL);
0615   rtems_test_assert(rv == -1);
0616   rtems_test_assert(errno == EIO);
0617   rtems_test_assert(rtems_resource_snapshot_check(&before));
0618 
0619   errno = 0;
0620   rv = IMFS_add_node("/nil/nada", &node, NULL);
0621   rtems_test_assert(rv == -1);
0622   rtems_test_assert(errno == ENOENT);
0623   rtems_test_assert(rtems_resource_snapshot_check(&before));
0624 
0625   errno = 0;
0626   rv = IMFS_add_node(path, &invalid_name_node, NULL);
0627   rtems_test_assert(rv == -1);
0628   rtems_test_assert(errno == EINVAL);
0629   rtems_test_assert(rtems_resource_snapshot_check(&before));
0630 
0631   rtems_heap_greedy_free(opaque);
0632 }
0633 
0634 static void Init(rtems_task_argument arg)
0635 {
0636   TEST_BEGIN();
0637 
0638   test_imfs_make_generic_node();
0639   test_imfs_make_generic_node_errors();
0640   test_imfs_add_node();
0641   test_imfs_add_node_errors();
0642 
0643   TEST_END();
0644   rtems_test_exit(0);
0645 }
0646 
0647 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0648 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0649 
0650 #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 4
0651 
0652 #define CONFIGURE_MAXIMUM_TASKS 1
0653 
0654 #define CONFIGURE_UNIFIED_WORK_AREAS
0655 
0656 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0657 
0658 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0659 
0660 #define CONFIGURE_INIT
0661 
0662 #include <rtems/confdefs.h>