source: rtems/testsuites/psxtests/psxfile01/test.c @ 98c6d50

Last change on this file since 98c6d50 was 98c6d50, checked in by Chris Johns <chrisj@…>, on Oct 19, 2017 at 5:39:16 AM

testsuite: Use printk for all test output where possible.

  • Remove the printf support leaving the direct printk support configured with TESTS_USE_PRINTK and all other output goes via a buffered vsniprintf call to printk.
  • Control the test's single init for functions and global data with TEST_INIT and not CONFIGURE_INIT. They are now separate.

Updates #3170.

  • Property mode set to 100644
File size: 17.8 KB
Line 
1/**
2 *  @file
3 *
4 *  Simple test program to exercise some of the basic functionality of
5 *  POSIX Files and Directories Support.
6 *
7 *  This test assumes that the file system is initialized with the
8 *  following directory structure:
9 *
10 *  XXXX fill this in.
11 *    /
12 *    /dev
13 *    /dev/XXX   [where XXX includes at least console]
14 */
15
16/*
17 *  COPYRIGHT (c) 1989-2012.
18 *  On-Line Applications Research Corporation (OAR).
19 *
20 *  The license and distribution terms for this file may be
21 *  found in the file LICENSE in this distribution or at
22 *  http://www.rtems.org/license/LICENSE.
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <stdio.h>
30
31#include <pmacros.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <fcntl.h>
35#include <unistd.h>
36#include <errno.h>
37#include <string.h>
38#include <inttypes.h>
39#include <ctype.h>
40#include <reent.h>
41#include <rtems/imfs.h>
42
43#include <rtems.h>
44#include <rtems/libio.h>
45
46#include "primode.h"
47
48const char rtems_test_name[] = "PSXFILE 1";
49
50/* forward declarations to avoid warnings */
51void test_case_reopen_append(void);
52void dump_statbuf(struct stat *buf);
53void stat_a_file(const char *file);
54int test_main(void);
55
56char test_write_buffer[ 1024 ];
57rtems_filesystem_operations_table  IMFS_ops_no_evalformake;
58rtems_filesystem_operations_table  IMFS_ops_no_rename;
59
60/*
61 *  File test support routines.
62 */
63
64void test_cat(
65  char *file,
66  int   offset_arg,
67  int   length
68);
69
70void test_write(
71  char   *file,
72  off_t  offset,
73  char  *buffer
74);
75
76void test_extend(
77  char *file,
78  off_t new_len
79);
80
81/*
82 *  dump_statbuf
83 */
84void dump_statbuf( struct stat *buf )
85{
86  rtems_device_major_number major1;
87  rtems_device_minor_number minor1;
88  rtems_device_major_number major2;
89  rtems_device_minor_number minor2;
90
91  rtems_filesystem_split_dev_t( buf->st_dev, major1, minor1 );
92  rtems_filesystem_split_dev_t( buf->st_rdev, major2, minor2 );
93
94  printf( "....st_dev     (0x%" PRIx32 ":0x%" PRIx32 ")\n", major1, minor1 );
95  printf( "....st_rdev    (0x%" PRIx32 ":0x%" PRIx32 ")\n", major2, minor2 );
96  printf( "....st_ino     %" PRIxino_t "  may vary by small amount\n", buf->st_ino );
97  printf( "....mode  = %08" PRIomode_t "\n", buf->st_mode );
98  printf( "....nlink = %d\n", buf->st_nlink );
99
100  printf( "....uid = %d\n", buf->st_uid );
101  printf( "....gid = %d\n", buf->st_gid );
102
103  printf( "....atime = %s", ctime(&buf->st_atime) );
104  printf( "....mtime = %s", ctime(&buf->st_mtime) );
105  printf( "....ctime = %s", ctime(&buf->st_ctime) );
106
107  printf( "....st_blksize %" PRIxblksize_t "\n", buf->st_blksize );
108  printf( "....st_blocks  %" PRIxblkcnt_t "\n", buf->st_blocks );
109}
110
111void stat_a_file(
112  const char *file
113)
114{
115  int         status;
116  struct stat statbuf;
117
118  rtems_test_assert( file );
119
120  printf( "stat( %s ) returned ", file );
121
122  status = stat( file, &statbuf );
123
124  if ( status == -1 ) {
125    printf( ": %s\n", strerror( errno ) );
126  } else {
127    puts("");
128    dump_statbuf( &statbuf );
129  }
130
131}
132
133/*
134 *  Main entry point of the test
135 */
136
137#if defined(__rtems__)
138int test_main(void)
139#else
140int main(
141  int argc,
142  char **argv
143)
144#endif
145{
146  int               status;
147  size_t            max_size;
148  int               fd;
149  int               i;
150  struct stat       buf;
151  char              buffer[128];
152  FILE             *file;
153  time_t            atime1;
154  time_t            mtime1;
155  time_t            ctime1;
156  time_t            atime2;
157  time_t            mtime2;
158  time_t            ctime2;
159  rtems_status_code rtems_status;
160  rtems_time_of_day time;
161
162  TEST_BEGIN();
163
164  /*
165   *  Grab the maximum size of an in-memory file.
166   */
167
168  max_size = IMFS_MEMFILE_MAXIMUM_SIZE;
169
170  build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
171  rtems_status = rtems_clock_set( &time );
172  directive_failed( rtems_status, "clock set" );
173
174  /*
175   *  Simple stat() of /dev/console.
176   */
177
178  puts( "stat of /dev/console" );
179  status = stat( "/dev/console", &buf );
180  rtems_test_assert( !status );
181
182  dump_statbuf( &buf );
183
184  /*
185   *  Exercise mkdir() and some path evaluation.
186   */
187
188  puts( "" );
189  puts( "mkdir /dev/tty" );
190  status = mkdir( "/dev/tty", S_IRWXU );
191  rtems_test_assert( !status );
192
193  puts( "" );
194  puts( "mkdir /usr" );
195  status = mkdir( "/usr", S_IRWXU );
196  rtems_test_assert( !status );
197  puts( "mkdir /etc" );
198  status = mkdir( "/etc", S_IRWXU );
199  rtems_test_assert( !status );
200
201  puts( "mkdir /tmp" );
202  status = mkdir( "/tmp", S_IRWXU );
203  rtems_test_assert( !status );
204
205  /* this tests the ".." path in path name evaluation */
206  puts( "mkdir /tmp/.." );
207  status = mkdir( "/tmp/..", S_IRWXU );
208  rtems_test_assert( status == -1 );
209  rtems_test_assert( errno == EEXIST );
210
211  /* now check out trailing separators */
212  puts( "mkdir /tmp/" );
213  status = mkdir( "/tmp/", S_IRWXU );
214  rtems_test_assert( status == -1 );
215  rtems_test_assert( errno == EEXIST );
216
217  /* try to make a directory under a non-existent subdirectory */
218  puts( "mkdir /j/j1" );
219  status = mkdir( "/j/j1", S_IRWXU );
220  rtems_test_assert( status == -1 );
221  rtems_test_assert( errno == ENOENT );
222
223  /* this tests the ability to make a directory in the current one */
224  puts( "mkdir tmp" );
225  status = mkdir( "tmp", S_IRWXU );
226  rtems_test_assert( status == -1 );
227  rtems_test_assert( errno == EEXIST );
228
229  /*
230   *  Now switch gears and exercise rmdir().
231   */
232
233  puts( "" );
234  puts( "rmdir /usr" );
235  status = rmdir( "/usr" );
236  rtems_test_assert( !status );
237
238  puts( "rmdir /dev" );
239  status = rmdir( "/dev" );
240  rtems_test_assert( status == -1 );
241  rtems_test_assert( errno ==  ENOTEMPTY);
242
243  puts( "rmdir /fred" );
244  status = rmdir ("/fred");
245  rtems_test_assert (status == -1);
246  rtems_test_assert( errno == ENOENT );
247
248  puts( "rmdir /tmp/bha" );
249  status = rmdir( "/tmp/bha" );
250  rtems_test_assert( status == -1 );
251  rtems_test_assert( errno == ENOENT );
252
253  puts( "mknod /dev/test_console" );
254  status = mknod( "/dev/test_console", S_IFCHR, 0LL );
255  rtems_test_assert( !status );
256
257  puts( "mknod /dev/tty/S3" );
258  status = mknod( "/dev/tty/S3", S_IFCHR, 0xFF00000080LL );
259  rtems_test_assert( !status );
260
261  puts ("mknod /etc/passwd");
262  status = mknod( "/etc/passwd", (S_IFREG | S_IRWXU), 0LL );
263  rtems_test_assert( !status );
264
265  puts( "mkdir /tmp/my_dir");
266  status = mkdir( "/tmp/my_dir", S_IRWXU );
267  rtems_test_assert( status == 0 );
268
269  puts("mkfifo /c/my_dir" );
270  status = mkfifo( "/c/my_dir", S_IRWXU );
271  rtems_test_assert( status == -1 );
272
273  /*
274   *  Try to make a directory under a file -- ERROR
275   */
276
277  puts( "mkdir /etc/passwd/j" );
278  status = mkdir( "/etc/passwd/j", S_IRWXU );
279  rtems_test_assert( status == -1 );
280  rtems_test_assert( errno == ENOTDIR );
281
282  /*
283   *  Simple open failure case on non-existent file
284   */
285
286  puts( "open /tmp/joel - should fail with ENOENT" );
287  fd = open( "/tmp/joel", O_RDONLY );
288  rtems_test_assert( fd == -1 );
289  rtems_test_assert( errno == ENOENT );
290
291  /*
292   *  Simple open case where the file is created.
293   */
294
295  puts( "open /tmp/j" );
296  fd = open( "/tmp/j", O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO );
297  rtems_test_assert( fd != -1 );
298  printf( "open returned file descriptor %d\n", fd );
299
300  puts( "close /tmp/j" );
301  status = close( fd );
302  rtems_test_assert( !status );
303
304  puts( "close /tmp/j again" );
305  status = close( fd );
306  rtems_test_assert( status == -1 );
307
308  puts( "unlink /tmp/j" );
309  status = unlink( "/tmp/j" );
310  rtems_test_assert( !status );
311
312  puts( "unlink /tmp" );
313  status = unlink( "/tmp" );
314  rtems_test_assert( status );
315
316  /*
317   *  Simple open failure. Trying to create an existing file.
318   */
319
320  puts("create and close /tmp/tom");
321  fd = open( "/tmp/tom", O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO );
322  rtems_test_assert( fd != -1 );
323  status = close( fd );
324  rtems_test_assert( status == 0 );
325
326  puts("Attempt to recreate /tmp/tom");
327  fd = open( "/tmp/tom", O_CREAT | O_EXCL, S_IRWXU|S_IRWXG|S_IRWXO );
328  rtems_test_assert( fd == -1 );
329  rtems_test_assert( errno == EEXIST );
330
331  puts("create /tmp/john");
332  fd = open( "/tmp/john", O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO );
333  rtems_test_assert( fd != -1 );
334  status = close( fd );
335  rtems_test_assert( status == 0 );
336
337  /*
338   * Open a file in read-only mode and try to truncate
339   */
340
341  puts( "Attempt to create a file, open in read-only mode and truncate it" );
342  fd = open( "/tmp/bha", O_CREAT | O_RDONLY | O_TRUNC, S_IRUSR );
343  rtems_test_assert( fd == -1 );
344  rtems_test_assert( errno == EINVAL );
345
346  puts( "Exercise the reentrant version _link_r -- Expect ENOENT" );
347  status = _link_r( NULL, "/tmp/notexist", "/tmp/cannotexist" );
348  rtems_test_assert( status == -1 );
349  rtems_test_assert( errno == ENOENT );
350
351  puts( "Unlink /tmp/bha using the reentrant version -- OK" );
352  status = _unlink_r( NULL, "/tmp/bha" );
353  rtems_test_assert( status == 0 );
354
355  /*
356   * Simple test case for mknod
357   */
358
359  puts( "mknod with bad type - expect EINVAL" );
360  status = mknod( "/tmp/bha", 0, 0LL );
361  rtems_test_assert( status == -1 );
362  rtems_test_assert( errno == EINVAL );
363
364  /*
365   * Read from filedes opened for write
366   */
367
368  puts( "open /tmp/bha in write only mode -- OK" );
369  fd = open( "/tmp/bha", O_CREAT | O_WRONLY, S_IRWXU|S_IRWXG|S_IRWXO );
370  rtems_test_assert( fd != -1 );
371
372  puts( "attempt fcntl on opened file -- OK" );
373  status = fcntl( fd, F_SETFD, 0 );
374  rtems_test_assert( status == 0 );
375
376  puts( "attempt to read from /tmp/bha - expect EBADF" );
377  status = read( fd, buffer, 10 );
378  rtems_test_assert( status == -1 );
379  rtems_test_assert( errno == EBADF );
380
381  puts( "closing and unlinking /tmp/bha" );
382  status = close( fd );
383  status |= unlink( "/tmp/bha" );
384  rtems_test_assert( status == 0 );
385
386  puts( "open /tmp/bha in read only mode -- OK" );
387  fd = open( "/tmp/bha", O_CREAT | O_RDONLY, S_IRWXU|S_IRWXG|S_IRWXO );
388  rtems_test_assert( fd != -1 );
389
390  puts( "attempt to read from /tmp/bha - expect EBADF" );
391  status = write( fd, buffer, 10 );
392  rtems_test_assert( status == -1 );
393  rtems_test_assert( errno == EBADF );
394
395  puts( "closing and unlinking /tmp/bha" );
396  status = close( fd );
397  status |= unlink( "/tmp/bha" );
398  rtems_test_assert( status == 0 );
399
400  /*
401   * Read/write from an unopened filedes
402   */
403  puts( "attempt to read from an unopened filedes - expect EBADF" );
404  status = read( 5, buffer, 10 );
405  rtems_test_assert( status == -1 );
406  rtems_test_assert( errno == EBADF );
407
408  puts( "attempt to write to an unopened filedes - expect EBADF" );
409  status = write( 5, buffer, 10 );
410  rtems_test_assert( status == -1 );
411  rtems_test_assert( errno == EBADF );
412
413  /*
414   *  Test simple write to a file at offset 0
415   */
416
417  puts( "mknod /tmp/joel" );
418  status = mknod( "/tmp/joel", (S_IFREG | S_IRWXU), 0LL );
419  test_write( "/tmp/joel", 0, "the first write!!!\n" );
420  test_cat( "/tmp/joel", 0, 0 );
421
422  /* Exercise _rename_r */
423
424  /* Simple rename test */
425  puts( "rename /tmp/joel to /tmp/drjoel");
426  status = _rename_r(NULL,"/tmp/joel","/tmp/drjoel");
427  rtems_test_assert(status == 0);
428
429  /* Simple rename test */
430  puts("rename /tmp/drjoel to /tmp/joel");
431  status = _rename_r(NULL,"/tmp/drjoel","/tmp/joel");
432  rtems_test_assert(status == 0);
433
434  /* Invalid old path */
435  puts("rename /tmp/drjoel to /tmp/joel - Should result in an error \
436since old path is not valid");
437  status = _rename_r(NULL,"/tmp/drjoel","/tmp/joel");
438  rtems_test_assert(status == -1);
439
440  /* Invalid new path */
441  puts("rename /tmp/joel to /tmp/drjoel/joel - Should result in an error \
442since new path is not valid");
443  status = _rename_r(NULL,"/tmp/joel","/tmp/drjoel/joel");
444  rtems_test_assert(status == -1);
445
446  puts("changing dir to /tmp");
447  status = chdir("/tmp/");
448  rtems_test_assert(status == 0);
449
450  puts("rename joel to drjoel");
451  status = _rename_r(NULL,"joel","drjoel");
452  rtems_test_assert(status == 0);
453
454  puts("rename drjoel to joel");
455  status = _rename_r(NULL,"drjoel","joel");
456  rtems_test_assert(status == 0);
457
458  /* Rename across file systems */
459  puts("creating directory /imfs");
460  status = mkdir("/imfs",0777);
461  rtems_test_assert(status == 0);
462  puts("creating directory /imfs/hidden_on_mount");
463  status = mkdir("/imfs/hidden_on_mount",0777);
464  rtems_test_assert(status == 0);
465
466  puts("mounting filesystem with IMFS_ops at /imfs");
467  status = mount("null", "/imfs", "imfs", RTEMS_FILESYSTEM_READ_WRITE, NULL);
468  rtems_test_assert(status == 0);
469  puts("creating directory /imfs/test (on newly mounted filesystem)");
470  status = mkdir("/imfs/test", 0777);
471  rtems_test_assert(status == 0);
472
473  puts("attempt to rename directory joel to /imfs/test/joel - should fail with EXDEV");
474  status = _rename_r(NULL, "joel", "/imfs/test/joel");
475  rtems_test_assert(status == -1);
476  rtems_test_assert(errno == EXDEV);
477
478  puts("changing dir to /");
479  status = chdir("/");
480  rtems_test_assert(status == 0);
481
482  puts("attempt to rename across filesystem, with old path having a parent node");
483  puts("attempt to rename tmp/joel to /imfs/test/joel");
484  status = _rename_r(NULL, "tmp/joel", "/imfs/test/joel");
485  rtems_test_assert(status == -1);
486  rtems_test_assert(errno == EXDEV);
487
488  puts("End of _rename_r tests");
489
490  /*
491   *  Test simple write to a file at a non-0 offset in the first block
492   */
493
494  status = unlink( "/tmp/joel" );
495  rtems_test_assert( !status );
496
497  status = mknod( "/tmp/joel", (S_IFREG | S_IRWXU), 0LL );
498  rtems_test_assert( !status );
499
500  test_write( "/tmp/joel", 10, "the first write!!!\n" );
501  test_cat( "/tmp/joel", 0, 0 );
502  stat_a_file( "/tmp/joel" );
503
504  /*
505   *  Test simple write to a file at a non-0 offset in the second block.  Then
506   *  try to read from various offsets and lengths.
507   */
508
509  puts("unlink /tmp/joel");
510  status = unlink( "/tmp/joel" );
511  rtems_test_assert( !status );
512
513  /* Test a failure path */
514
515  puts( "unlink /tmp/joel" );
516  status = unlink( "/tmp/joel" );
517  rtems_test_assert( status == -1 );
518
519  puts( "mknod /tmp/joel");
520  status = mknod( "/tmp/joel", (S_IFREG | S_IRWXU), 0LL );
521  rtems_test_assert( !status );
522
523  test_write( "/tmp/joel", 514, "the first write!!!\n" );
524  test_write( "/tmp/joel", 1, test_write_buffer );
525  test_write( "/tmp/joel", 63, test_write_buffer );
526  test_cat( "/tmp/joel", 0, 1 );
527  test_cat( "/tmp/joel", 1, 1 );
528  test_cat( "/tmp/joel", 490, 1 );
529  test_cat( "/tmp/joel", 512, 1 );
530  test_cat( "/tmp/joel", 513, 1 );
531  test_cat( "/tmp/joel", 514, 1 );
532  test_cat( "/tmp/joel", 520, 1 );
533  test_cat( "/tmp/joel", 1, 1024 );
534
535  /*
536   *  Read from a much longer file so we can descend into doubly and
537   *  triply indirect blocks.
538   */
539
540  if ( max_size < (size_t) 300 * 1024 ) {
541    test_extend( "/tmp/joel", max_size - 1 );
542    test_cat( "/tmp/joel", max_size / 2, 1024 );
543  } else {
544    printf( "Skipping maximum file size test since max_size is %zu bytes\n", max_size );
545    puts("That is likely to be bigger than the available RAM on many targets." );
546  }
547
548  stat_a_file( "/tmp/joel" );
549
550  /*
551   *  Now try to use a FILE * descriptor
552   *
553   *  /tmp/j should not exist at this point.
554   */
555
556  puts( "stat of /tmp/j" );
557  errno = 0;
558  status = stat( "/tmp/j", &buf );
559  printf( "stat(/tmp/j) returned %d (errno=%d)\n", status, errno );
560  dump_statbuf( &buf );
561
562  puts( "fopen of /tmp/j" );
563  file = fopen( "/tmp/j", "w+" );
564  rtems_test_assert( file );
565
566  puts( "fprintf to /tmp/j" );
567  for (i=1 ; i<=5 ; i++) {
568    status = fprintf( file, "This is call %d to fprintf\n", i );
569    rtems_test_assert( status );
570    printf( "(%d) %d characters written to the file\n", i, status );
571  }
572
573  fflush( file );
574
575  status = stat( "/tmp/j", &buf );
576  rtems_test_assert( !status );
577  dump_statbuf( &buf );
578  atime2 = buf.st_atime;
579  mtime2 = buf.st_mtime;
580  ctime2 = buf.st_ctime;
581
582
583  status = rtems_task_wake_after( rtems_clock_get_ticks_per_second() );
584  rewind( file );
585  while ( fgets(buffer, 128, file) )
586    printf( "%s", buffer );
587
588  /*
589   * Verify only atime changed for a read.
590   */
591  status = stat( "/tmp/j", &buf );
592  rtems_test_assert( !status );
593  dump_statbuf( &buf );
594  atime1 = buf.st_atime;
595  mtime1 = buf.st_mtime;
596  ctime1 = buf.st_ctime;
597  rtems_test_assert( atime1 != atime2);
598  rtems_test_assert( mtime1 == mtime2);
599  rtems_test_assert( ctime1 == ctime2);
600
601  unlink( "/tmp/joel" );
602
603  /*
604   *  Now truncate a file
605   */
606
607  status = rtems_task_wake_after( rtems_clock_get_ticks_per_second() );
608  puts( "truncate /tmp/j to length of 40" );
609  status = truncate( "/tmp/j", 40 );
610  rtems_test_assert( !status );
611
612  /*
613   * Verify truncate changed all except atime.
614   */
615  status = stat( "/tmp/j", &buf );
616  rtems_test_assert( !status );
617  dump_statbuf( &buf );
618  atime2 = buf.st_atime;
619  mtime2 = buf.st_mtime;
620  ctime2 = buf.st_ctime;
621  rtems_test_assert( atime1 == atime2);
622  rtems_test_assert( mtime1 != mtime2);
623  rtems_test_assert( ctime1 != ctime2);
624
625  /* try to truncate the console and see what happens */
626  errno = 0;
627  status = truncate( "/dev/console", 40 );
628  rtems_test_assert( status == 0 || ( status == -1 && errno == EINVAL ) );
629
630  puts( "truncate /tmp/j to length of 0" );
631  status = truncate( "/tmp/j", 0 );
632  rtems_test_assert( !status );
633
634  puts( "truncate /tmp to length of 0 should fail with EISDIR\n");
635  status = truncate( "/tmp", 0 );
636  rtems_test_assert( status == -1 );
637  printf( "%d: %s\n", errno, strerror( errno ) );
638  rtems_test_assert( errno == EISDIR );
639
640  status = truncate( "/tmp/fred", 10 );
641  rtems_test_assert( status == -1);
642
643  rtems_status = rtems_io_register_name( "/dev/not_console", 0, 0 );
644  directive_failed( rtems_status, "io register" );
645
646  test_case_reopen_append();
647
648  TEST_END();
649  rtems_test_exit( 0 );
650}
651
652/*
653 *  Open/Create a File and write to it
654 *
655 *  Test case submitted by Andrew Bythell <abythell@nortelnetworks.com>.
656 *
657 */
658
659void test_file (char *filename, char *mode);
660
661void test_case_reopen_append(void)
662{
663  printf ("Writing First File\n");
664  test_file ("/one.txt", "a");
665  test_file ("/one.txt", "a");
666
667  /* but not the second time - this will insert junk.
668     the number of ^@'s seems to equal the number of
669     actual characters in the file */
670
671  printf ("Writing Second File\n");
672  test_file ("/two.txt", "a");
673  test_file ("/two.txt", "a");
674
675  test_cat( "/one.txt", 0, 1024 );
676  test_cat( "/two.txt", 0, 1024 );
677}
678
679void test_file (char *filename, char *mode)
680{
681  FILE *fp;
682  fp = fopen (filename, mode);
683  if (!fp)
684      perror ("fopen");
685  fprintf (fp, "this is a test line\n");
686  if (fclose (fp))
687      perror ("fclose");
688}
Note: See TracBrowser for help on using the repository browser.