File indexing completed on 2025-05-11 08:24:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
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
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
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>