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

4.115
Last change on this file since a3fd09b was a3fd09b, checked in by Ralf Corsepius <ralf.corsepius@…>, on 10/22/11 at 12:20:33

2011-10-22 Ralf Corsépius <ralf.corsepius@…>

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