source: rtems/c/src/tests/psxtests/psxstat/test.c @ 3fe8f44b

Last change on this file since 3fe8f44b was 3fe8f44b, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 7, 2001 at 11:59:26 PM

2001-11-07 Jennifer Averett <jennifer@…>

Reported by Ibragimov Ilya <ibr@…> and tracked as PR63.

  • psxstat/test.c: Fix test ENOTDIR to correspond to chdir() change. Since we check permissions before evaluating enough to see if it a regular file or directory, this hack is needed to make the regular file executable.
  • Property mode set to 100644
File size: 17.8 KB
Line 
1/*
2 *  This test exercises stat() via fstat() and generates as many of the
3 *  path evaluation cases as possible.
4 *
5 *  COPYRIGHT (c) 1989-1999.
6 *  On-Line Applications Research Corporation (OAR).
7 *
8 *  The license and distribution terms for this file may be
9 *  found in the file LICENSE in this distribution or at
10 *  http://www.OARcorp.com/rtems/license.html.
11 *
12 *  $Id$
13 */
14
15#include <tmacros.h>
16#include <assert.h>
17#include <sys/stat.h>
18#include <fcntl.h>
19#include <limits.h>
20#include <stdio.h>
21#include <unistd.h>
22#include <errno.h>
23#include <string.h>
24#include <rtems.h>
25#include <rtems/libio.h>
26
27#define MAXSYMLINK 5   /* There needs to be a better way of getting this. */
28
29
30/*
31 *  List of files which should exist.
32 */
33
34char *Files[] = {
35  "////dir1/\\//file1\\\\//",
36  "/dir1/file2",
37  "/dir1/file3",
38  "/dir1/file4",
39  "/dir1/dir1/file1",
40  "../../..//dir1/./././dir1/ file1",
41  "main.c",
42  0
43};
44
45/*
46 *  List of directories which should exist.
47 */
48
49char *Directories[] = {
50  "/dir1",
51  "/dir2",
52  "/dir3",
53  "/dir4",
54  "/dir1/dir1",
55  "/./././dir1/ dir1",
56  "/./././links", 
57  "///dir1/dir1/../../dir1/../symlinks/////",
58  0
59};
60
61char *Links_to_Dirs[]= {
62  "dir1/dir1/../../links/dir1",
63  "links/dir2",
64  "links/dir3",
65  "links/dir4",
66  "links/dir1_dir1",
67  "links/dir1_ dir1",
68  "links/../links/../links/links",
69  0
70};
71
72char *Links_to_Files[]= {
73  "links/dir1_file1",
74  "links/dir1_file2",
75  "links/dir1_file3",
76  "links/dir1_file4",
77  "links/dir1_dir1_f1",
78  "links/dir1_dir1 f1",
79  0
80};
81
82char *Links_to_dirlinks[]= {
83  "links/links/links/links_dir1",
84  "links//links_dir2",
85  "links//links_dir3",
86  "links//links_dir4",
87  "links//links_dir1_d1",
88  "links//links_dir1 d1",
89  "links//links_links",
90  0
91};
92
93char *Links_to_filelinks[]= {
94  "links///links_d1_file1",
95  "links///links_d1_file2",
96  "links///links_d1_file3",
97  "links///links_d1_file4",
98  "links///links_d1_d1_f1",
99  "links///links_r1_d1 f1",
100  0
101};
102
103char *SymLinks[]= {
104  "/symlinks/a_file_symlink",
105  "/symlinks/a_dir_symlink",
106  "/symlinks/a_link_symlink",
107  "../symlinks/no_file",
108  "/symlinks/a_dir_symlink/a_file_symlink",
109  0
110};
111
112/*
113 *  List of absolute paths to stat.
114 */
115
116char *Good_absolute_paths[] = {
117  "/dev",
118  "////dir1/\\//file1\\\\//",
119  "/dir1/\\\\/file2",
120  "/dir1/file3/////\\\\\\",
121  "/dir1/file4",
122  "/dir1/dir1/file1",
123  "/dir1/dir1/ file1",
124  "/dir1",
125  "/dir2//////\\",
126  "/dir3",
127  "/dir4",
128  "/dir1/dir1",
129  "/dir1/ dir1///\\\\",
130  "/\\/\\/\\/\\/\\/\\/links\\/\\/\\/\\/\\/\\",
131  0
132};
133
134
135char *Bad_paths[] = {
136  "/links/ENAMETOOLONG__________________________",
137  "/dir1/file4/NOTADIR",
138  "/dir1/dir1/EACCES__",
139  0
140};
141
142/*
143 *  List of relative paths to stat.
144 */
145
146char *Good_relative_paths[] = {
147  "dev",
148  "dir1/\\//file1\\\\//",
149  "dir1/\\\\/file2",
150  "dir1/file3/////\\\\\\",
151  "dir1/file4",
152  "dir1/dir1/file1",
153  "dir1/dir1/ file1",
154  "dir1",
155  "dir2//////\\",
156  "dir3",
157  "dir4",
158  "dir1/dir1",
159  "dir1/ dir1///\\\\",
160  "main.c",
161  0
162};
163
164/*
165 *  Do a stat on a single file and report the status.
166 */
167
168void stat_a_file(
169  const char *file
170)
171{
172  int         status;
173  struct stat statbuf;
174  int         major1;
175  int         minor1;
176  int         major2;
177  int         minor2;
178
179
180  assert( file );
181
182  printf( "stat( %s ) returned ", file );
183  fflush( stdout );
184
185  status = stat( file, &statbuf );
186
187  if ( status == -1 ) {
188    printf( ": %s\n", strerror( errno ) );
189  } else {
190
191    rtems_filesystem_split_dev_t( statbuf.st_dev, major1, minor1 );
192    rtems_filesystem_split_dev_t( statbuf.st_rdev, major2, minor2 );
193
194
195    printf("\n\tst_dev     (0x%x:0x%x)\n", major1, minor1 );
196    printf(  "...st_ino     %x\n", (int) statbuf.st_ino );
197    printf(  "...st_mode    %o\n", statbuf.st_mode );
198    printf(  "...st_nlink   %x\n", statbuf.st_nlink );
199    printf(  "...st_uid     %d\n", statbuf.st_uid );
200    printf(  "...st_gid     %d\n", statbuf.st_gid );
201    printf(  "...st_rdev    (0x%x:0x%x)\n", major2, minor2 );
202    printf(  "...st_size    %d\n",(unsigned int) statbuf.st_size );
203    printf(  "...st_atime   %s", ctime( &statbuf.st_atime ) );
204    printf(  "...st_mtime   %s", ctime( &statbuf.st_mtime ) );
205    printf(  "...st_ctime   %s", ctime( &statbuf.st_ctime ) );
206#if defined(__svr4__) && !defined(__PPC__) && !defined(__sun__)
207    printf(  "...st_blksize %x\n", statbuf.st_blksize );
208    printf(  "...st_blocks  %x\n", statbuf.st_blocks );
209#endif
210
211  }
212}
213
214/*
215 *  stat() multiple files at a time
216 */
217
218void stat_multiple_files(
219  char **files
220)
221{
222  int    i;
223
224  i = 0;
225  while ( files[i] ) {
226    stat_a_file( files[i] );
227    i++;
228  }
229}
230
231/*
232 *  chown() multiple files at a time
233 */
234void chown_multiple_files(
235  char **files
236)
237{
238  int    i;
239  uid_t  st_uid;
240  gid_t  st_gid;
241
242  st_uid = geteuid();
243  st_gid = getegid();
244
245  i = 0;
246  while ( files[i] ) {
247    printf("Change group of %s\n", files[i]);
248    chown( files[i], st_uid, (st_gid+1) );
249    stat_a_file( files[i] );
250
251    printf("Change owner of %s\n", files[i]);
252    chown( files[i], (st_uid+1), st_gid );
253    stat_a_file( files[i] );
254    i++;
255  }
256
257}
258
259
260
261/*
262 *  mknod() multiple files at a time
263 */
264
265void make_multiple_files(
266  char **files
267)
268{
269  int    i;
270  int    status;
271
272  i = 0;
273  while ( files[i] ) {
274    printf( "Making file %s\n", files[i] );
275    status = mknod( files[i], ( S_IFREG | S_IROTH|S_IWOTH ), 0LL );
276    assert( !status );
277    i++;
278  }
279  puts( "" );
280}
281
282void make_multiple_bad_files(
283  char **files
284)
285{
286  int    i;
287  int    status;
288
289  i = 0;
290  while ( files[i] ) {
291    printf( "Making file %s ", files[i] );
292    status = mknod( files[i], ( S_IFREG | S_IROTH|S_IWOTH ), 0LL );
293    assert( status );
294    printf( ": %s\n", strerror( errno ) );
295    i++;
296  }
297  puts( "" );
298}
299
300void make_multiple_links(
301  char **existing,
302  char **new
303)
304{
305  int    i;
306  int    status;
307
308  i = 0;
309  while ( new[i] && existing[i] ) {
310    printf( "Making file %s\n", new[i] );
311    status = link( existing[i], new[i] );
312    assert( !status );
313    i++;
314  }
315  puts( "" );
316
317  status = link( "fred", "bob" );
318  assert( status == -1 );
319
320  status = link( existing[1], "doug/bob" );
321  assert( status == -1 );
322}
323
324
325void make_too_many_links()
326{
327  int    i;
328  int    status;
329  char   name [20];
330
331  status = mkdir("/dummy", S_IRWXU );
332  assert( status == 0 );
333
334  for (i=1; i<= LINK_MAX; i++) {
335
336    sprintf(name,"/LinkName%d",i);
337    printf( "Making file %s\n", name );
338    status = link("/dummy" , name );
339    if( i < LINK_MAX )
340       assert( !status );
341    else
342       assert( status == -1 );
343
344  }
345}
346
347
348void make_a_symlink(
349  char *existing,
350  char *new
351)
352{
353  int    status;
354  char   buf[100];
355  int    len;
356
357  memset( buf, 0, 100 );
358
359  printf( "Making file %s\n", new );
360  status = symlink( existing, new );
361  assert( !status );
362
363  printf( "Verify with readlink\n");
364  status = readlink( new, buf, 100 );
365  len = strlen( existing );
366  assert ( status == len );
367
368  status = readlink( new, buf, 3 );
369  len = strlen( existing );
370  if (len < 3 )
371    assert( status == len );
372  else
373    assert( status == 3 );
374
375  status = strcmp( existing, buf );
376  assert( !status );
377}
378
379void make_multiple_symlinks()
380{
381 int  status;
382
383 make_a_symlink( Files[0],             SymLinks[0] );
384 make_a_symlink( Directories[0],       SymLinks[1] );
385 make_a_symlink( Links_to_dirlinks[0], SymLinks[2] );
386 make_a_symlink( "No_File",            SymLinks[3] );
387 make_a_symlink( SymLinks[1],          SymLinks[4] );
388 make_a_symlink( "//links",            "/symlinks/links"  );
389
390 stat_a_file( SymLinks[0] );
391 stat_a_file( SymLinks[1] );
392 stat_a_file( SymLinks[2] );
393 stat_a_file( SymLinks[3] );
394 stat_a_file( SymLinks[4] );
395
396 status = symlink(  "//links", "bob/frank" );
397 assert (status == -1);
398
399}
400/*
401void make_too_many_symlinks()
402{
403  int  i, status;
404  char name1[8];
405
406  for (i=1; i <= MAXSYMLINK; i++) {
407    sprintf( name1, "SymLink%d", i );
408    status = symlink( "/dummy", name1 );
409    if( i < MAXSYMLINK )
410       assert( !status );
411    else
412       assert( status == -1 );
413  }
414}
415*/
416void make_many_symlinks(
417  char  *real_file,
418  int    link_count
419)
420{
421  int  i;
422  char name1[5];
423  char name2[5];
424  char *link_file;
425
426  link_file = real_file;
427  for (i=1; i < link_count; i++) {
428    sprintf( name1, "%d", i );
429    make_a_symlink( link_file, name1 );
430    strcpy( name2, name1 );
431    link_file = name2;
432  }
433
434  for (i=1; i < link_count; i++) {
435    sprintf( name1, "%d", i );
436    stat_a_file( name1 );
437  }
438
439}
440
441/*
442 *  mkdir() multiple directories at a time
443 */
444 
445void make_multiple_directories(
446  char **files
447) 
448{
449  int    i;
450  int    status;
451
452  i = 0; 
453  while ( files[i] ) {
454    printf( "Making directory %s\n", files[i] );
455    status = mkdir( files[i], S_IRWXU );
456    assert( !status );
457    i++;
458  }
459  puts( "" );
460} 
461
462/*
463 * Cause faults.
464 */
465
466
467void Cause_faults()
468{
469  int                                   fd;
470  int                                   status;
471  char                                  longer_name[100];
472  rtems_filesystem_mount_table_entry_t *mt_entry;
473
474  /*
475   * Verify chmod with an invalid type.
476   */
477
478  printf("\n\nPass an invalid mode to chmod should fail with EPERM \n" );
479  status = chmod( Files[0], S_IFREG );
480  assert( status == -1 ); 
481  assert( errno == EPERM );
482
483  /*
484   * Change file to executable then try to chdir to it.
485   */
486
487  status = chmod( Files[0], S_IXUSR );
488  assert( status != -1 );
489
490  printf("chdir to a file should fail with ENOTDIR\n");
491  status = chdir( Files[0] );
492  assert( status == -1 );
493  assert( errno == ENOTDIR );
494
495  /*
496   * Change mode to read/write on a directory.
497   * Verify directory works properly.
498   */
499
500  printf("Verify RWX permission on %s via access\n", Directories[0]);
501  status = access( Directories[0], ( R_OK | W_OK | X_OK )  );
502  assert( status == 0 );
503
504  printf( "chmod of %s to Read/Write\n", Directories[0] );
505  status = chmod( Directories[0], (S_IXGRP | S_IXOTH) );
506  assert( status == 0 );
507
508  printf( "chmod fred should fail with ENOENT\n" );
509  status = chmod( "fred", (S_IXGRP | S_IXOTH) );
510  assert( status == -1 );
511  assert( errno == ENOENT );
512
513  strcpy(longer_name, Directories[0] );
514  strcat(longer_name, "/BADNAME" );
515  printf( "Create under %s should fail with EACCES\n", Directories[0] );
516  status = mkdir( longer_name , S_IRWXU );
517  assert( status == -1 );
518  assert( errno == EACCES );
519
520  printf("chdir to %s should fail with EACCES\n", Directories[4] );
521  status = chdir( Directories[4] );
522  assert( status == -1 );
523  assert( errno == EACCES );
524
525  /*
526   * Check stat with a NULL buffer.
527   */
528
529  printf("Stat with a NULL buffer should fail with EFAULT\n");
530  status = stat( Directories[0], NULL );
531  assert( status == -1 );
532  assert( errno == EFAULT );
533
534  /*
535   * Set current to a directory with no owner permissions.
536   * Verify it works properly.
537   */
538
539  printf( "\n\nchmod of %s to Read/Write\n", Directories[0] );
540  status = chmod( Directories[0], (S_IXGRP | S_IXOTH) );
541  assert( status == 0 );
542
543  printf("mkdir %s should fail with EACCESS\n", longer_name );
544  status = mkdir( longer_name , S_IRWXU );
545  assert( status == -1 );
546  assert( errno == EACCES );
547
548  printf("\n%s Should exist ( access )\n",Directories[0] );
549  status = access( Directories[0], F_OK );
550  assert( status == 0 );
551  printf("\n%s Should have read  permission( access )\n",Directories[0] );
552  status = access( Directories[0], R_OK );
553  assert( status != 0 );
554  printf("\n%s Should have write permission( access )\n",Directories[0] );
555  status = access( Directories[0], W_OK );
556  assert( status != 0 );
557  printf("\n%s Should not have execute permission( access )\n",Directories[0] );
558  status = access( Directories[0], X_OK );
559  assert( status != 0 );
560 
561  printf("\nRestore %s to RWX\n",Directories[0] );
562  status = chmod( Directories[0], S_IRWXU );
563  assert( status == 0 );
564
565  printf("chdir to / \n");
566  status = chdir( "/" );
567  assert( status == 0 );
568
569  /*
570   * Remove one of the directories.
571   * Verify links to the removed directory still work.
572   */
573
574  printf( "Remove %s\n", Directories[5] );
575  status = rmdir( Directories[5] );
576  assert( status == 0 );
577
578  stat_a_file( Directories[5] );
579  status = access( Directories[5], F_OK );
580  assert( status != 0 );
581
582  stat_a_file( Links_to_Dirs[5] );
583  status = readlink( Links_to_Dirs[5], longer_name, 3 );
584  assert( status == -1 );
585  assert( errno == EINVAL );
586
587  stat_a_file( Links_to_dirlinks[5] );
588  printf("Chdir to %s\n", Links_to_Dirs[5] );
589  status = chdir( Links_to_Dirs[5] );
590  assert( status == 0 );
591
592  /*
593   * Verify we cannot move up from a node with no parent node.
594   */
595
596  printf("Chdir to .. should fail with ENOENT\n" );
597  status = chdir( ".." );
598  assert( status == -1 );
599  assert( errno == ENOENT );
600
601  /*
602   * Create a subdirectory under the dangling node.
603   */
604
605  printf("mkdir ../t should fail with ENOENT\n" );
606  status = mkdir( "../t" , S_IRWXU );
607  assert( status == -1 );
608  assert( errno == ENOENT );
609
610  printf("mkdir t\n");
611  status = mkdir( "t" , S_IRWXU );
612  assert( status == 0 );
613
614  printf("chdir to / \n");
615  status = chdir( "/" );
616  assert( status == 0 );
617
618  /*
619   * Check rmdir, rmnod, and unlink
620   */
621
622  printf("rmdir %s should fail with ENOTDIR\n", Links_to_Dirs[5] );
623  status = rmdir( Links_to_Dirs[5] );
624  assert( status == -1 );
625  assert( errno == ENOTDIR );
626
627  printf("unlink %s\n", Links_to_Dirs[5] );
628  status = unlink( Links_to_Dirs[5] );
629  assert( status == 0 );
630
631  printf("unlink %s should fail with ENOTEMPTY\n", Links_to_dirlinks[5] );
632  status = unlink(  Links_to_dirlinks[5] );
633  assert( status == -1 );
634  assert( errno == ENOTEMPTY );
635
636  strcpy( longer_name,  Links_to_dirlinks[5] );
637  strcat( longer_name, "/t");
638  printf("rmdir %s\n", longer_name );
639  status = rmdir( longer_name );
640  assert( status == 0 );
641
642  printf("unlink %s\n", Links_to_Dirs[5]);
643  status = unlink( Links_to_dirlinks[5] );
644  assert( status == 0 );
645
646  status = chdir( Directories[0] );
647  status = mkdir ( "my_mount_point", S_IRWXU );
648  assert( status == 0 );
649
650  printf("Attempting to mount IMFS file system at /dir1/my_mount_point \n");
651  status = mount(
652     &mt_entry,
653     &IMFS_ops,
654     RTEMS_FILESYSTEM_READ_WRITE,
655     NULL,
656     "/dir1/my_mount_point" );
657  assert( status == 0 );
658
659  printf("rmdir /dir1/my_mount_point should fail with EBUSY\n");
660  status = rmdir ("/dir1/my_mount_point" );
661  assert( status == -1 );
662  assert( errno == EBUSY );
663
664  printf( "Unmount /dir1/my_mount_point\n");
665  status = unmount( "/dir1/my_mount_point" );
666  assert( status == 0 );
667
668  /*
669   * Verify write permission is checked.
670   */
671
672  printf("chmod of %s to group and other execute\n", Files[0] );
673  status = chmod (Files[0], (S_IXGRP | S_IXOTH) );
674  assert( status == 0 );
675
676  printf("Open %s for write should fail with EACCES\n", Files[0] );
677  fd = open (Files[0], O_WRONLY); 
678  assert( fd == -1 );
679  assert( errno == EACCES );
680
681  printf("chmod of %s to User Execute and Read\n", Directories[3] );
682  status = chmod (Directories[3], (S_IXUSR | S_IRUSR) );
683  assert( status == 0 );
684  strcpy(longer_name, Directories[3] );
685  strcat(longer_name, "/NewFile" );
686  printf("Mkdir of %s should fail with EACCES\n",longer_name );
687  status = mkdir( longer_name, S_IRWXU );
688  assert( status != 0 );
689  assert( errno == EACCES );
690
691  printf(" Making too many hard links.\n" );
692  make_too_many_links( );
693
694  printf( "pass fstat a null pointer should fail with EFAULT\n");
695  status = fstat( fd, NULL );
696  assert( status == -1 ); 
697  assert( errno == EFAULT);
698
699  /*
700   * The current directory MUST be restored at the end of this test.
701   */
702
703  printf("chdir to / \n");
704  status = chdir( "/" );
705  assert( status == 0 );
706
707}
708
709void Show_Time()
710{
711  rtems_time_of_day time;
712  rtems_status_code status;
713
714  status = rtems_clock_get( RTEMS_CLOCK_GET_TOD, &time );
715  printf(">>>>Current Time: ");
716  print_time( " - rtems_clock_get - ", &time, "\n" );
717}
718
719/*
720 *  main entry point to the test
721 */
722
723#if defined(__rtems__)
724int test_main(void)
725#else
726int main(
727  int    argc,
728  char **argv
729)
730#endif
731{
732  rtems_status_code status;
733  rtems_time_of_day time;
734
735  puts( "\n\n*** STAT TEST 01 ***" );
736
737  build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
738  status = rtems_clock_set( &time );
739
740  /*
741   *  Create the files and directories for the test.
742   */
743  Show_Time();
744
745  make_multiple_directories( Directories );
746  make_multiple_files( Files );
747  make_multiple_links( Directories,    Links_to_Dirs );
748  make_multiple_links( Files,          Links_to_Files );
749
750  status = rtems_task_wake_after( 5 * TICKS_PER_SECOND );
751  make_multiple_links( Links_to_Dirs,  Links_to_dirlinks );
752  status = rtems_task_wake_after( 5 * TICKS_PER_SECOND );
753  make_multiple_links( Links_to_Files, Links_to_filelinks );
754
755  status = rtems_task_wake_after( 5 * TICKS_PER_SECOND );
756
757  /*
758   *  Now go through all the absolute path.
759   */
760
761  puts( "Doing the stat() on all the good absolute paths" );
762  stat_multiple_files( Good_absolute_paths );
763
764  /*
765   *  run through the relative paths.
766   */
767
768  puts( "\nDoing the stat() on all the good relative paths" );
769  stat_multiple_files( Good_relative_paths );
770
771  /*
772   * Change directory and releative paths are now bad.
773   */
774
775  puts("\nchdir to dev");
776  chdir("dev");
777  puts("\nstat relative paths that are now bad");
778  stat_multiple_files( Good_relative_paths );
779
780  /*
781   * Change directory to the link directory and follow links.
782   */
783
784  puts("\nchdir to ../links");
785  chdir("../links");
786  puts("Doing the stat() on good links\n");
787  stat_multiple_files( Links_to_Dirs );
788  stat_multiple_files( Links_to_Files );
789  stat_multiple_files( Links_to_dirlinks  );
790  stat_multiple_files( Links_to_filelinks );
791 
792  /*
793   * Chmod on dir1/dir1.  This allows the error path to be hit.
794   */
795
796  printf( "chmod of %s to Read/Write\n", Directories[4] );
797  chmod( Directories[4], (S_IROTH|S_IWOTH) );
798  puts( "\nDoing the stat() on all the bad paths" );
799
800  stat_multiple_files( Bad_paths );
801  make_multiple_bad_files( Bad_paths );
802
803  printf( "Return %s to RWX\n", Directories[4] );
804  chmod( Directories[4], S_IRWXU );
805
806
807  /*
808   * Check out symbolic links.
809   */
810
811  make_multiple_symlinks();
812  make_many_symlinks( "/symlinks", 10 );
813
814  status = rtems_task_wake_after( 5 * TICKS_PER_SECOND );
815  Cause_faults();
816
817  status = rtems_task_wake_after( 5 * TICKS_PER_SECOND );
818  chown_multiple_files( Files );
819
820  status = rtems_task_wake_after( 5 * TICKS_PER_SECOND );
821  chown_multiple_files( Links_to_Dirs );
822 
823  puts( "\n\n*** END OF STAT TEST 01 ***" );
824  exit(0);
825}
826
827
828
829
830
831
832
Note: See TracBrowser for help on using the repository browser.