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

4.115
Last change on this file since 12935408 was 12935408, checked in by Ralf Corsepius <ralf.corsepius@…>, on 10/25/11 at 15:10:52

Apply missing patch.

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