source: rtems/testsuites/psxtests/psxfile01/test.c @ 377c0cb0

4.104.115
Last change on this file since 377c0cb0 was cb930b4, checked in by Joel Sherrill <joel.sherrill@…>, on 04/28/10 at 15:01:51

2010-04-28 Joel Sherrill <joel.sherrill@…>

  • psxfile01/test.c: Add check for errno on chdir(NULL).
  • Property mode set to 100644
File size: 12.8 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
34#include <rtems.h>
35#include <rtems/libio.h>
36
37void test_case_reopen_append(void);
38
39char test_write_buffer[ 1024 ];
40
41/*
42 *  File test support routines.
43 */
44
45void test_cat(
46  char *file,
47  int   offset_arg,
48  int   length
49);
50
51void test_write(
52  char   *file,
53  off_t  offset,
54  char  *buffer
55);
56
57void test_extend(
58  char *file,
59  off_t new_len
60);
61
62void IMFS_dump( void );
63int IMFS_memfile_maximum_size( void );
64
65/*
66 *  dump_statbuf
67 */
68
69void dump_statbuf( struct stat *buf )
70{
71  int         major1;
72  int         minor1;
73  int         major2;
74  int         minor2;
75
76  rtems_filesystem_split_dev_t( buf->st_dev, major1, minor1 );
77  rtems_filesystem_split_dev_t( buf->st_rdev, major2, minor2 );
78
79  printf( "....st_dev     (0x%x:0x%x)\n", major1, minor1 );
80  printf( "....st_ino     %" PRIxino_t "  may vary by small amount\n", buf->st_ino );
81  printf( "....mode  = %08o\n", (unsigned int) buf->st_mode );
82  printf( "....nlink = %d\n", buf->st_nlink );
83
84  printf( "....uid = %d\n", buf->st_uid );
85  printf( "....gid = %d\n", buf->st_gid );
86
87  printf( "....atime = %s", ctime(&buf->st_atime) );
88  printf( "....mtime = %s", ctime(&buf->st_mtime) );
89  printf( "....ctime = %s", ctime(&buf->st_ctime) );
90
91  printf( "....st_blksize %" PRIxblksize_t "\n", buf->st_blksize );
92  printf( "....st_blocks  %" PRIxblkcnt_t "\n", buf->st_blocks );
93}
94
95void stat_a_file(
96  const char *file
97)
98{
99  int         status;
100  struct stat statbuf;
101
102  rtems_test_assert( file );
103
104  printf( "stat( %s ) returned ", file );
105  fflush( stdout );
106
107  status = stat( file, &statbuf );
108
109  if ( status == -1 ) {
110    printf( ": %s\n", strerror( errno ) );
111  } else {
112    puts("");
113    dump_statbuf( &statbuf );
114  }
115
116}
117
118
119/*
120 *  Main entry point of the test
121 */
122
123#if defined(__rtems__)
124int test_main(void)
125#else
126int main(
127  int argc,
128  char **argv
129)
130#endif
131{
132  int               status;
133  size_t            max_size;
134  int               fd;
135  int               i;
136  struct stat       buf;
137  char              buffer[128];
138  FILE             *file;
139  time_t            atime1;
140  time_t            mtime1;
141  time_t            ctime1;
142  time_t            atime2;
143  time_t            mtime2;
144  time_t            ctime2;
145  rtems_status_code rtems_status;
146  rtems_time_of_day time;
147
148  printf( "\n\n*** FILE TEST 1 ***\n" );
149
150  /*
151   *  Grab the maximum size of an in-memory file.
152   */
153
154  max_size = IMFS_memfile_maximum_size();
155
156  build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
157  rtems_status = rtems_clock_set( &time );
158
159  /*
160   *  Dump an empty file system
161   */
162
163  IMFS_dump();
164
165  /*
166   *  Simple stat() of /dev/console.
167   */
168
169  puts( "stat of /dev/console" );
170  status = stat( "/dev/console", &buf );
171  rtems_test_assert( !status );
172
173  dump_statbuf( &buf );
174
175  /*
176   *  Exercise mkdir() and some path evaluation.
177   */
178
179  puts( "" );
180  puts( "mkdir /dev/tty" );
181  status = mkdir( "/dev/tty", S_IRWXU );
182  rtems_test_assert( !status );
183
184  puts( "" );
185  puts( "mkdir /usr" );
186  status = mkdir( "/usr", S_IRWXU );
187  rtems_test_assert( !status );
188  puts( "mkdir /etc" );
189  status = mkdir( "/etc", S_IRWXU );
190  rtems_test_assert( !status );
191
192  puts( "mkdir /tmp" );
193  status = mkdir( "/tmp", S_IRWXU );
194  rtems_test_assert( !status );
195
196  /* this tests the ".." path in path name evaluation */
197  puts( "mkdir /tmp/.." );
198  status = mkdir( "/tmp/..", S_IRWXU );
199  rtems_test_assert( status == -1 );
200  rtems_test_assert( errno == EEXIST );
201
202  /* now check out trailing separators */
203  puts( "mkdir /tmp/" );
204  status = mkdir( "/tmp/", S_IRWXU );
205  rtems_test_assert( status == -1 );
206  rtems_test_assert( errno == EEXIST );
207
208  /* try to make a directory under a non-existent subdirectory */
209  puts( "mkdir /j/j1" );
210  status = mkdir( "/j/j1", S_IRWXU );
211  rtems_test_assert( status == -1 );
212  rtems_test_assert( errno == ENOENT );
213
214  /* this tests the ability to make a directory in the current one */
215  puts( "mkdir tmp" );
216  status = mkdir( "tmp", S_IRWXU );
217  rtems_test_assert( status == -1 );
218  rtems_test_assert( errno == EEXIST );
219
220  /* test rtems_filesystem_evaluate_path by sending NULL path */
221  status = chdir( NULL );
222  rtems_test_assert( status == -1 );
223  rtems_test_assert( errno == EFAULT );
224
225  /*
226   *  Now switch gears and exercise rmdir().
227   */
228
229  puts( "" );
230  puts( "rmdir /usr" );
231  status = rmdir( "/usr" );
232  rtems_test_assert( !status );
233
234  puts( "rmdir /dev" );
235  status = rmdir( "/dev" );
236  rtems_test_assert( status == -1 );
237  rtems_test_assert( errno ==  ENOTEMPTY);
238
239  puts( "rmdir /fred" );
240  status = rmdir ("/fred");
241  rtems_test_assert (status == -1);
242  rtems_test_assert( errno == ENOENT );
243
244  puts( "mknod /dev/test_console" );
245  status = mknod( "/dev/test_console", S_IFCHR, 0LL );
246  rtems_test_assert( !status );
247
248  puts( "mknod /dev/tty/S3" );
249  status = mknod( "/dev/tty/S3", S_IFCHR, 0xFF00000080LL );
250  rtems_test_assert( !status );
251
252  puts ("mknod /etc/passwd");
253  status = mknod( "/etc/passwd", (S_IFREG | S_IRWXU), 0LL );
254  rtems_test_assert( !status );
255
256  puts( "mkdir /tmp/my_dir");
257  status = mkdir( "/tmp/my_dir", S_IRWXU );
258  rtems_test_assert( status == 0 );
259
260  puts("mkfifo /c/my_dir" );
261  status = mkfifo( "/c/my_dir", S_IRWXU );
262  rtems_test_assert( status == -1 );
263
264  /*
265   *  Try to make a directory under a file -- ERROR
266   */
267
268  puts( "mkdir /etc/passwd/j" );
269  status = mkdir( "/etc/passwd/j", S_IRWXU );
270  rtems_test_assert( status == -1 );
271  rtems_test_assert( errno == ENOTDIR );
272
273  /*
274   *  Simple open failure case on non-existent file
275   */
276
277  puts( "open /tmp/joel - should fail with ENOENT" );
278  fd = open( "/tmp/joel", O_RDONLY );
279  rtems_test_assert( fd == -1 );
280  rtems_test_assert( errno == ENOENT );
281
282  /*
283   *  Simple open case where the file is created.
284   */
285
286  puts( "open /tmp/j" );
287  fd = open( "/tmp/j", O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO );
288  rtems_test_assert( fd != -1 );
289  printf( "open returned file descriptor %d\n", fd );
290
291  puts( "close /tmp/j" );
292  status = close( fd );
293  rtems_test_assert( !status );
294
295  puts( "close /tmp/j again" );
296  status = close( fd );
297  rtems_test_assert( status == -1 );
298
299  puts( "unlink /tmp/j" );
300  status = unlink( "/tmp/j" );
301  rtems_test_assert( !status );
302
303  puts( "unlink /tmp" );
304  status = unlink( "/tmp" );
305  rtems_test_assert( status );
306
307  /*
308   *  Simple open failure. Trying to create an existing file.
309   */
310
311  puts("create and close /tmp/tom");
312  fd = open( "/tmp/tom", O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO );
313  rtems_test_assert( fd != -1 );
314  status = close( fd );
315  rtems_test_assert( status == 0 );
316
317  puts("Attempt to recreate /tmp/tom");
318  fd = open( "/tmp/tom", O_CREAT | O_EXCL, S_IRWXU|S_IRWXG|S_IRWXO );
319  rtems_test_assert( fd == -1 );
320  rtems_test_assert( errno == EEXIST );
321
322  puts("create /tmp/john");
323  fd = open( "/tmp/john", O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO );
324  rtems_test_assert( fd != -1 );
325
326  puts("tcdrain /tmp/john" );
327  status = tcdrain( fd );
328  rtems_test_assert( status == 0 );
329
330  /*
331   *  Test simple write to a file at offset 0
332   */
333
334  puts( "mknod /tmp/joel" );
335  status = mknod( "/tmp/joel", (S_IFREG | S_IRWXU), 0LL );
336  test_write( "/tmp/joel", 0, "the first write!!!\n" );
337  test_cat( "/tmp/joel", 0, 0 );
338
339  /*
340   *  Test simple write to a file at a non-0 offset in the first block
341   */
342
343  status = unlink( "/tmp/joel" );
344  rtems_test_assert( !status );
345
346  status = mknod( "/tmp/joel", (S_IFREG | S_IRWXU), 0LL );
347  rtems_test_assert( !status );
348
349  test_write( "/tmp/joel", 10, "the first write!!!\n" );
350  test_cat( "/tmp/joel", 0, 0 );
351  stat_a_file( "/tmp/joel" );
352
353  /*
354   *  Test simple write to a file at a non-0 offset in the second block.  Then
355   *  try to read from various offsets and lengths.
356   */
357
358  puts("unlink /tmp/joel");
359  status = unlink( "/tmp/joel" );
360  rtems_test_assert( !status );
361
362  /* Test a failure path */
363
364  puts( "unlink /tmp/joel" );
365  status = unlink( "/tmp/joel" );
366  rtems_test_assert( status == -1 );
367
368  puts( "mknod /tmp/joel");
369  status = mknod( "/tmp/joel", (S_IFREG | S_IRWXU), 0LL );
370  rtems_test_assert( !status );
371
372  test_write( "/tmp/joel", 514, "the first write!!!\n" );
373  test_write( "/tmp/joel", 1, test_write_buffer );
374  test_write( "/tmp/joel", 63, test_write_buffer );
375  test_cat( "/tmp/joel", 0, 1 );
376  test_cat( "/tmp/joel", 1, 1 );
377  test_cat( "/tmp/joel", 490, 1 );
378  test_cat( "/tmp/joel", 512, 1 );
379  test_cat( "/tmp/joel", 513, 1 );
380  test_cat( "/tmp/joel", 514, 1 );
381  test_cat( "/tmp/joel", 520, 1 );
382  test_cat( "/tmp/joel", 1, 1024 );
383
384  /*
385   *  Read from a much longer file so we can descend into doubly and
386   *  triply indirect blocks.
387   */
388
389  if ( max_size < (size_t) 300 * 1024 ) {
390    test_extend( "/tmp/joel", max_size - 1 );
391    test_cat( "/tmp/joel", max_size / 2, 1024 );
392  } else {
393    printf( "Skipping maximum file size test since max_size is %zu bytes\n", max_size );
394    puts("That is likely to be bigger than the available RAM on many targets." );
395  }
396
397  stat_a_file( "/tmp/joel" );
398
399  /*
400   *  Now try to use a FILE * descriptor
401   *
402   *  /tmp/j should not exist at this point.
403   */
404
405  puts( "stat of /tmp/j" );
406  errno = 0;
407  status = stat( "/tmp/j", &buf );
408  printf( "stat(/tmp/j) returned %d (errno=%d)\n", status, errno );
409  dump_statbuf( &buf );
410
411  puts( "fopen of /tmp/j" );
412  file = fopen( "/tmp/j", "w+" );
413  rtems_test_assert( file );
414
415  puts( "fprintf to /tmp/j" );
416  for (i=1 ; i<=5 ; i++) {
417    status = fprintf( file, "This is call %d to fprintf\n", i );
418    rtems_test_assert( status );
419    printf( "(%d) %d characters written to the file\n", i, status );
420  }
421
422  fflush( file );
423
424  status = stat( "/tmp/j", &buf );
425  rtems_test_assert( !status );
426  dump_statbuf( &buf );
427  atime2 = buf.st_atime;
428  mtime2 = buf.st_mtime;
429  ctime2 = buf.st_ctime;
430
431
432  status = rtems_task_wake_after( rtems_clock_get_ticks_per_second() );
433  rewind( file );
434  while ( fgets(buffer, 128, file) )
435    printf( "%s", buffer );
436
437  /*
438   * Verify only atime changed for a read.
439   */
440  status = stat( "/tmp/j", &buf );
441  rtems_test_assert( !status );
442  dump_statbuf( &buf );
443  atime1 = buf.st_atime;
444  mtime1 = buf.st_mtime;
445  ctime1 = buf.st_ctime;
446  rtems_test_assert( atime1 != atime2);
447  rtems_test_assert( mtime1 == mtime2);
448  rtems_test_assert( ctime1 == ctime2);
449
450  IMFS_dump();
451
452  unlink( "/tmp/joel" );
453
454  /*
455   *  Now truncate a file
456   */
457
458  status = rtems_task_wake_after( rtems_clock_get_ticks_per_second() );
459  puts( "truncate /tmp/j to length of 40" );
460  status = truncate( "/tmp/j", 40 );
461  rtems_test_assert( !status );
462
463  /*
464   * Verify truncate changed only atime.
465   */
466  status = stat( "/tmp/j", &buf );
467  rtems_test_assert( !status );
468  dump_statbuf( &buf );
469  atime2 = buf.st_atime;
470  mtime2 = buf.st_mtime;
471  ctime2 = buf.st_ctime;
472  rtems_test_assert( atime1 != atime2);
473  rtems_test_assert( mtime1 == mtime2);
474  rtems_test_assert( ctime1 == ctime2);
475
476  IMFS_dump();
477
478  /* try to truncate the console and see what happens */
479  status = truncate( "/dev/console", 40 );
480  rtems_test_assert( status == 0 );
481
482  puts( "truncate /tmp/j to length of 0" );
483  status = truncate( "/tmp/j", 0 );
484  rtems_test_assert( !status );
485
486  puts( "truncate /tmp to length of 0 should fail with EISDIR\n");
487  status = truncate( "/tmp", 0 );
488  rtems_test_assert( status == -1 );
489  printf( "%d: %s\n", errno, strerror( errno ) );
490  rtems_test_assert( errno == EISDIR );
491
492  IMFS_dump();
493
494  status = truncate( "/tmp/fred", 10 );
495  rtems_test_assert( status == -1);
496
497  rtems_status = rtems_io_register_name( "/dev/console", 0, 0 );
498
499  test_case_reopen_append();
500
501  printf( "*** END OF FILE TEST 1 ***\n" );
502  rtems_test_exit( 0 );
503}
504
505/*
506 *  Open/Create a File and write to it
507 *
508 *  Test case submitted by Andrew Bythell <abythell@nortelnetworks.com>.
509 *
510 */
511
512void test_file (char *filename, char *mode);
513
514void test_case_reopen_append(void)
515{
516  printf ("Writing First File\n");
517  test_file ("/one.txt", "a");
518  test_file ("/one.txt", "a");
519
520  /* but not the second time - this will insert junk.
521     the number of ^@'s seems to equal the number of
522     actual characters in the file */
523
524  printf ("Writing Second File\n");
525  test_file ("/two.txt", "a");
526  test_file ("/two.txt", "a");
527
528  test_cat( "/one.txt", 0, 1024 );
529  test_cat( "/two.txt", 0, 1024 );
530}
531
532void test_file (char *filename, char *mode)
533{
534  FILE *fp;
535  fp = fopen (filename, mode);
536  if (!fp)
537      perror ("fopen");
538  fprintf (fp, "this is a test line\n");
539  if (fclose (fp))
540      perror ("fclose");
541}
Note: See TracBrowser for help on using the repository browser.