File indexing completed on 2025-05-11 08:24:33
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 <stdio.h>
0033 #include <errno.h>
0034
0035 #include <sys/reent.h>
0036 #include <sys/stat.h>
0037
0038 #include <rtems.h>
0039 #include <rtems/console.h>
0040 #include <rtems/imfs.h>
0041 #include <rtems/libcsupport.h>
0042 #include <rtems/sysinit.h>
0043
0044 #include "tmacros.h"
0045
0046 #ifndef _REENT_CLEANUP
0047 #define _REENT_CLEANUP(ptr) ((ptr)->__cleanup)
0048 #endif
0049
0050 const char rtems_test_name[] = "NEWLIB 1";
0051
0052 static const char stdio_file_path[] = "/stdio-file";
0053
0054 static const char non_stdio_file_path[] = "/non-stdio-file";
0055
0056 typedef enum {
0057 INIT,
0058 OPEN,
0059 WRITTEN,
0060 CLOSED
0061 } test_state;
0062
0063 typedef struct {
0064 rtems_id main_task_id;
0065 rtems_id worker_task_id;
0066 test_state current;
0067 FILE *non_stdio_file;
0068 int non_stdio_fd;
0069 } test_context;
0070
0071 static test_context test_instance;
0072
0073 static void wake_up_main(const test_context *ctx)
0074 {
0075 rtems_status_code sc;
0076
0077 sc = rtems_event_transient_send(ctx->main_task_id);
0078 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0079 }
0080
0081 static void wait(void)
0082 {
0083 rtems_status_code sc;
0084
0085 sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0086 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0087 }
0088
0089
0090
0091
0092
0093
0094
0095 static void test_rand(void)
0096 {
0097 int rv;
0098
0099 rv = rand();
0100 rtems_test_assert(rv == 1481765933);
0101 rv = rand();
0102 rtems_test_assert(rv == 1085377743);
0103 rv = rand();
0104 rtems_test_assert(rv == 1270216262);
0105
0106 srand(1);
0107 rv = rand();
0108 rtems_test_assert(rv == 1481765933);
0109 rv = rand();
0110 rtems_test_assert(rv == 1085377743);
0111 rv = rand();
0112 rtems_test_assert(rv == 1270216262);
0113 }
0114
0115
0116
0117
0118
0119
0120
0121 static void test_lrand48(void)
0122 {
0123 long rv;
0124
0125 rv = lrand48();
0126 rtems_test_assert(rv == 851401618);
0127 rv = lrand48();
0128 rtems_test_assert(rv == 1804928587);
0129 rv = lrand48();
0130 rtems_test_assert(rv == 758783491);
0131 }
0132
0133 static void stdio_file_worker(rtems_task_argument arg)
0134 {
0135 test_context *ctx = &test_instance;
0136 FILE *output;
0137 char buf[1] = { 'x' };
0138 size_t n;
0139
0140 test_rand();
0141 test_lrand48();
0142
0143 rtems_test_assert(_REENT_CLEANUP(_REENT) == NULL);
0144
0145 output = stdout = fopen(&stdio_file_path[0], "r+");
0146 rtems_test_assert(stdout != NULL);
0147
0148
0149
0150
0151 rtems_test_assert(_REENT_CLEANUP(_REENT) == NULL);
0152 rtems_test_assert(fflush(stdout) == 0);
0153 rtems_test_assert(_REENT_CLEANUP(_REENT) != NULL);
0154 rtems_test_assert(stdout == output);
0155
0156 n = fwrite(&buf[0], sizeof(buf), 1, stdout);
0157 rtems_test_assert(n == 1);
0158
0159 rtems_test_assert(ctx->current == OPEN);
0160
0161 wake_up_main(ctx);
0162
0163 rtems_test_assert(0);
0164 }
0165
0166 static void non_stdio_file_worker(rtems_task_argument arg)
0167 {
0168 test_context *ctx = &test_instance;
0169 FILE *fp;
0170 char buf[1] = { 'y' };
0171 size_t n;
0172 int fd;
0173
0174 fp = ctx->non_stdio_file = fopen(&non_stdio_file_path[0], "w");
0175 rtems_test_assert(fp != NULL);
0176
0177
0178 fd = fileno(fp);
0179 rtems_test_assert(fd != -1);
0180 ctx->non_stdio_fd = fd;
0181
0182 n = fwrite(&buf[0], sizeof(buf), 1, fp);
0183 rtems_test_assert(n == 1);
0184
0185 wake_up_main(ctx);
0186
0187 rtems_test_assert(0);
0188 }
0189
0190 static int handler_open(
0191 rtems_libio_t *iop,
0192 const char *path,
0193 int oflag,
0194 mode_t mode
0195 )
0196 {
0197 test_context *ctx = &test_instance;
0198
0199 rtems_test_assert(ctx->current == INIT);
0200 ctx->current = OPEN;
0201
0202 return 0;
0203 }
0204
0205 static int handler_close(
0206 rtems_libio_t *iop
0207 )
0208 {
0209 test_context *ctx = &test_instance;
0210
0211 rtems_test_assert(ctx->current == WRITTEN);
0212 ctx->current = CLOSED;
0213
0214 return 0;
0215 }
0216
0217 static ssize_t handler_read(
0218 rtems_libio_t *iop,
0219 void *buffer,
0220 size_t count
0221 )
0222 {
0223 rtems_test_assert(0);
0224
0225 return 0;
0226 }
0227
0228 static ssize_t handler_write(
0229 rtems_libio_t *iop,
0230 const void *buffer,
0231 size_t count
0232 )
0233 {
0234 test_context *ctx = &test_instance;
0235
0236 rtems_test_assert(ctx->current == OPEN);
0237 ctx->current = WRITTEN;
0238
0239 iop->offset += count;
0240
0241 return (ssize_t) count;
0242 }
0243
0244 static int handler_ioctl(
0245 rtems_libio_t *iop,
0246 ioctl_command_t request,
0247 void *buffer
0248 )
0249 {
0250 rtems_test_assert(0);
0251
0252 return 0;
0253 }
0254
0255 static off_t handler_lseek(
0256 rtems_libio_t *iop,
0257 off_t length,
0258 int whence
0259 )
0260 {
0261 rtems_test_assert(0);
0262
0263 return 0;
0264 }
0265
0266 static int handler_ftruncate(
0267 rtems_libio_t *iop,
0268 off_t length
0269 )
0270 {
0271 rtems_test_assert(0);
0272
0273 return 0;
0274 }
0275
0276 static int handler_fsync(
0277 rtems_libio_t *iop
0278 )
0279 {
0280 rtems_test_assert(0);
0281
0282 return 0;
0283 }
0284
0285 static int handler_fdatasync(
0286 rtems_libio_t *iop
0287 )
0288 {
0289 rtems_test_assert(0);
0290
0291 return 0;
0292 }
0293
0294 static int handler_fcntl(
0295 rtems_libio_t *iop,
0296 int cmd
0297 )
0298 {
0299 rtems_test_assert(0);
0300
0301 return 0;
0302 }
0303
0304 static ssize_t handler_readv(
0305 rtems_libio_t *iop,
0306 const struct iovec *iov,
0307 int iovcnt,
0308 ssize_t total
0309 )
0310 {
0311 rtems_test_assert(0);
0312
0313 return 0;
0314 }
0315
0316 static ssize_t handler_writev(
0317 rtems_libio_t *iop,
0318 const struct iovec *iov,
0319 int iovcnt,
0320 ssize_t total
0321 )
0322 {
0323 rtems_test_assert(0);
0324
0325 return 0;
0326 }
0327
0328 static const rtems_filesystem_file_handlers_r node_handlers = {
0329 .open_h = handler_open,
0330 .close_h = handler_close,
0331 .read_h = handler_read,
0332 .write_h = handler_write,
0333 .ioctl_h = handler_ioctl,
0334 .lseek_h = handler_lseek,
0335 .fstat_h = rtems_filesystem_default_fstat,
0336 .ftruncate_h = handler_ftruncate,
0337 .fsync_h = handler_fsync,
0338 .fdatasync_h = handler_fdatasync,
0339 .fcntl_h = handler_fcntl,
0340 .readv_h = handler_readv,
0341 .writev_h = handler_writev
0342 };
0343
0344 static const IMFS_node_control node_control = IMFS_GENERIC_INITIALIZER(
0345 &node_handlers,
0346 IMFS_node_initialize_default,
0347 IMFS_node_destroy_default
0348 );
0349
0350 static void create_and_run_worker(test_context *ctx, rtems_task_entry entry)
0351 {
0352 rtems_status_code sc;
0353
0354 sc = rtems_task_create(
0355 rtems_build_name('W', 'O', 'R', 'K'),
0356 2,
0357 RTEMS_MINIMUM_STACK_SIZE,
0358 RTEMS_DEFAULT_MODES,
0359 RTEMS_DEFAULT_ATTRIBUTES,
0360 &ctx->worker_task_id
0361 );
0362 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0363
0364 sc = rtems_task_start(ctx->worker_task_id, entry, 0);
0365 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0366
0367 wait();
0368
0369 sc = rtems_task_delete(ctx->worker_task_id);
0370 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0371 }
0372
0373
0374
0375
0376
0377 static void test_stdio_file(test_context *ctx)
0378 {
0379 int rv;
0380 rtems_resource_snapshot snapshot;
0381
0382 rtems_resource_snapshot_take(&snapshot);
0383
0384 rv = IMFS_make_generic_node(
0385 &stdio_file_path[0],
0386 S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
0387 &node_control,
0388 NULL
0389 );
0390 rtems_test_assert(rv == 0);
0391
0392 create_and_run_worker(ctx, stdio_file_worker);
0393
0394 rv = unlink(&stdio_file_path[0]);
0395 rtems_test_assert(rv == 0);
0396
0397 rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0398 }
0399
0400
0401
0402
0403
0404 static void test_non_stdio_file(test_context *ctx)
0405 {
0406 create_and_run_worker(ctx, non_stdio_file_worker);
0407 }
0408
0409
0410
0411
0412
0413
0414
0415 static void check_after_libio_exit(void)
0416 {
0417 test_context *ctx = &test_instance;
0418 struct stat unused;
0419 int rv;
0420
0421 errno = 0;
0422 rv = fstat(0, &unused);
0423 rtems_test_assert(rv == -1);
0424 rtems_test_assert(errno == EBADF);
0425
0426 errno = 0;
0427 rv = fstat(1, &unused);
0428 rtems_test_assert(rv == -1);
0429 rtems_test_assert(errno == EBADF);
0430
0431 errno = 0;
0432 rv = fstat(2, &unused);
0433 rtems_test_assert(rv == -1);
0434 rtems_test_assert(errno == EBADF);
0435
0436 rtems_test_assert(stdin->_flags != 0);
0437 rtems_test_assert(stdout->_flags != 0);
0438 rtems_test_assert(stderr->_flags != 0);
0439
0440
0441
0442
0443
0444 rv = fstat(ctx->non_stdio_fd, &unused);
0445 rtems_test_assert(rv == 0);
0446 rtems_test_assert(ctx->non_stdio_file->_flags != 0);
0447 }
0448
0449 static void register_exit_handler_before_libio_exit(void)
0450 {
0451 int rv;
0452
0453 rv = atexit(check_after_libio_exit);
0454 rtems_test_assert(rv == 0);
0455 }
0456
0457
0458
0459
0460
0461
0462 RTEMS_SYSINIT_ITEM(register_exit_handler_before_libio_exit,
0463 RTEMS_SYSINIT_STD_FILE_DESCRIPTORS, RTEMS_SYSINIT_ORDER_FIRST);
0464
0465
0466
0467
0468
0469
0470 static void test_exit_handling(test_context *ctx)
0471 {
0472 struct stat unused;
0473 int rv;
0474
0475 rv = fstat(0, &unused);
0476 rtems_test_assert(rv == 0);
0477
0478 rv = fstat(1, &unused);
0479 rtems_test_assert(rv == 0);
0480
0481 rv = fstat(2, &unused);
0482 rtems_test_assert(rv == 0);
0483
0484 rtems_test_assert(stdin->_flags != 0);
0485 rtems_test_assert(stdout->_flags != 0);
0486 rtems_test_assert(stderr->_flags != 0);
0487
0488
0489
0490
0491
0492 rv = fstat(ctx->non_stdio_fd, &unused);
0493 rtems_test_assert(rv == 0);
0494 rtems_test_assert(ctx->non_stdio_file->_flags != 0);
0495
0496
0497 exit(0);
0498 }
0499
0500 static void Init(rtems_task_argument arg)
0501 {
0502 test_context *ctx = &test_instance;
0503 FILE *file;
0504 int rv;
0505
0506 TEST_BEGIN();
0507 test_rand();
0508 test_lrand48();
0509
0510 ctx->main_task_id = rtems_task_self();
0511
0512
0513 file = fopen(CONSOLE_DEVICE_NAME, "r+");
0514 rtems_test_assert(file != NULL);
0515 rv = fclose(file);
0516 rtems_test_assert(rv == 0);
0517
0518 test_stdio_file(ctx);
0519 test_non_stdio_file(ctx);
0520 test_exit_handling(ctx);
0521 }
0522
0523 static void fatal_extension(
0524 rtems_fatal_source source,
0525 bool always_set_to_false,
0526 rtems_fatal_code error
0527 )
0528 {
0529 if (
0530 source == RTEMS_FATAL_SOURCE_EXIT
0531 && !always_set_to_false
0532 && error == 0
0533 ) {
0534
0535
0536
0537
0538 struct stat unused;
0539 int rv;
0540 test_context *ctx = &test_instance;
0541
0542 errno = 0;
0543 rv = fstat(0, &unused);
0544 rtems_test_assert(rv == -1);
0545 rtems_test_assert(errno == EBADF);
0546
0547 errno = 0;
0548 rv = fstat(1, &unused);
0549 rtems_test_assert(rv == -1);
0550 rtems_test_assert(errno == EBADF);
0551
0552 errno = 0;
0553 rv = fstat(2, &unused);
0554 rtems_test_assert(rv == -1);
0555 rtems_test_assert(errno == EBADF);
0556
0557 rtems_test_assert(stdin->_flags == 0);
0558 rtems_test_assert(stdout->_flags == 0);
0559 rtems_test_assert(stderr->_flags == 0);
0560
0561
0562 errno = 0;
0563 rv = fstat(ctx->non_stdio_fd, &unused);
0564 rtems_test_assert(rv == -1);
0565 rtems_test_assert(errno == EBADF);
0566 rtems_test_assert(ctx->non_stdio_file->_flags == 0);
0567
0568 TEST_END();
0569 }
0570 }
0571
0572 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0573 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0574
0575 #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 5
0576
0577 #define CONFIGURE_MAXIMUM_TASKS 2
0578
0579 #define CONFIGURE_INITIAL_EXTENSIONS \
0580 { .fatal = fatal_extension }, \
0581 RTEMS_TEST_INITIAL_EXTENSION
0582
0583 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0584
0585 #define CONFIGURE_INIT
0586
0587 #include <rtems/confdefs.h>