source: rtems/testsuites/psxtests/psxfile01/test.c @ 6c2de60

4.115
Last change on this file since 6c2de60 was 6c2de60, checked in by Joel Sherrill <joel.sherrill@…>, on 05/11/12 at 19:12:11

psxtests - Eliminate missing prototype warnings

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