source: rtems/testsuites/psxtests/psxfile01/test.c @ b00c3cd

4.11
Last change on this file since b00c3cd was b00c3cd, checked in by Sebastian Huber <sebastian.huber@…>, on Jun 8, 2010 at 1:12:56 PM

2010-06-08 Sebastian Huber <Sebastian.Huber@…>

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