source: rtems/testsuites/psxtests/psxreaddir/test.c @ 7bde91b

Last change on this file since 7bde91b was 7bde91b, checked in by Sebastian Huber <sebastian.huber@…>, on Jan 10, 2019 at 8:05:49 AM

Fix format warnings due to ino_t changes

  • Property mode set to 100644
File size: 12.6 KB
Line 
1/**
2 *  @file
3 *
4 *  This is a native test to explore how the readdir() family works.
5 *  Newlib supports the following readdir() family members:
6 *
7 *    closedir()   -
8 *    readdir()    -
9 *    scandir()    -
10 *    opendir()    -
11 *    rewinddir()  -
12 *    telldir()    - BSD not in POSIX
13 *    seekdir()    - BSD not in POSIX
14 *
15 *
16 *  seekdir() takes an offset which is a byte offset.  The Linux
17 *  implementation of this appears to seek to the ((off/DIRENT_SIZE) + 1)
18 *  record where DIRENT_SIZE seems to be 12 bytes.
19 */
20
21/*
22 *  COPYRIGHT (c) 1989-2012.
23 *  On-Line Applications Research Corporation (OAR).
24 *
25 *  The license and distribution terms for this file may be
26 *  found in the file LICENSE in this distribution or at
27 *  http://www.rtems.org/license/LICENSE.
28 */
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#include <stdio.h>
35#include <sys/types.h>
36#include <fcntl.h>
37#include <dirent.h>
38#include <string.h>
39#include <unistd.h>
40#include <errno.h>
41#include <rtems/imfs.h>
42
43const char rtems_test_name[] = "PSXREADDIR";
44
45/* forward declarations to avoid warnings */
46int test_main(void);
47void printdir(DIR *directory);
48void complete_printdir(char *path);
49int select1(const struct dirent *entry);
50int select2(const struct dirent *entry);
51int compare_ascending(const struct dirent **a, const struct dirent **b);
52int compare_descending( const struct dirent **a, const struct dirent **b);
53void test_across_mount(void);
54void test_across_mount(void);
55
56DIR *directory;
57DIR *directory2;
58DIR *directory3;
59DIR *directory_not;
60
61/*
62int scandir ( const char *dirname,
63   struct dirent *** namelist,
64   int (*select) __P((struct dirent *)),
65   int (*dcomp) __P((const struct dirent **, const struct dirent **))
66);
67*/
68
69#if defined(__rtems__)
70#define d_type d_reclen
71#include <pmacros.h>
72#endif
73
74void printdir( DIR *directory )
75{
76  struct dirent *d;
77
78  printf( "%-20s %8s %8s %8s %4s\n",
79     "name", "    inode", " offset", "reclen", " type" );
80  d = readdir(directory);
81
82  while (d) {
83    printf( "%-20s %8" PRIuino_t " %8" PRIdoff_t " %6d   0x%04x\n",
84       d->d_name, d->d_ino, d->d_off, d->d_reclen, d->d_type );
85    d = readdir(directory);
86
87  }
88}
89
90void complete_printdir( char *path )
91{
92  DIR *the_dir;
93  int status;
94
95  the_dir = opendir( path );
96  rtems_test_assert( the_dir );
97
98  printdir( the_dir );
99  status = closedir( the_dir );
100  rtems_test_assert( !status );
101}
102
103char *many_files[] = {
104        "a",
105        "b",
106        "c",
107        "d",
108        "e",
109        "f",
110        "g",
111        "h",
112        "i",
113        "j",
114        "k",
115        "l",
116        "m",
117        "n",
118        "o",
119        "p",
120        "q",
121        "r",
122        "s",
123        "t",
124        "u",
125        "v",
126        "w",
127        "x",
128        "y",
129        "z",
130        "aa",
131        "ab",
132        "ac",
133        "ad",
134        "ae",
135        "af",
136        "ag",
137        "ah",
138        "ai",
139        "aj",
140        "ak",
141        "al",
142        "am",
143        "an",
144        "ao",
145        "ap",
146        "aq",
147        "ar"
148};
149
150char *dnames[] = {
151        "a",
152        "b",
153        "c",
154        "d",
155        "e",
156        "f",
157        "c/y",
158        "c/z",
159        "c/x",
160        "c/y/a3333",
161        "c/y/j123",
162        "END"
163};
164
165int select1 ( const struct dirent *entry )
166{
167   printf("SCANDIR SELECT1 accepts  nodename: %s\n", entry->d_name );
168   return 1;
169}
170
171int select2 ( const struct dirent *entry )
172{
173   if( strcmp( entry->d_name, "y") == 0 ) {
174      printf("SCANDIR SELECT accepted nodename: %s\n", entry->d_name );
175      return 1;
176   }
177   printf("SCANDIR SELECT rejected nodename: %s\n", entry->d_name );
178   return 0;
179}
180
181int compare_ascending(const struct dirent **a, const struct dirent **b )
182{
183   int i;
184
185   i = strcmp (
186      (char *)((struct dirent *)(*a)->d_name),
187      (char *)((struct dirent *)(*b)->d_name)
188   );
189   return i;
190}
191
192int compare_descending( const struct dirent **a, const struct dirent **b )
193{
194   int i;
195
196   i = strcmp (
197      (char *)((const struct dirent *)(*b)->d_name),
198      (char *)((const struct dirent *)(*a)->d_name)
199   );
200
201   return i;
202}
203
204void test_across_mount(void)
205{
206  int status;
207
208  /*
209   * Verify Readdir works correctly over mount points.
210   */
211
212  printf("Validate readdir across mount point\n");
213  rtems_test_assert( mkdir( "/imfs", 0777 ) == 0 );
214  rtems_test_assert( mkdir( "/imfs/should_be_hidden", 0777 ) == 0 );
215  complete_printdir("/imfs" );
216  printf("Attempting to mount IMFS file system at /imfs \n");
217  status = mount(
218    "null",
219    "/imfs",
220    "imfs",
221     RTEMS_FILESYSTEM_READ_WRITE,
222     NULL );
223  rtems_test_assert( status == 0 );
224  printf( "create /imfs/testdir and /imfs/testdir/testsubdir\n");
225
226  status = mkdir( "/imfs/testdir", 0777 );
227  rtems_test_assert( status == 0 );
228  status = mkdir( "/imfs/testdir/testsubdir", 0777 );
229  rtems_test_assert( status == 0 );
230
231  complete_printdir("/imfs" );
232  complete_printdir("/imfs/" );
233  complete_printdir("/imfs/." );
234  complete_printdir("/imfs/testdir" );
235  complete_printdir("/imfs/testdir/.." );
236}
237
238#if defined(__rtems__)
239int test_main(void)
240#else
241int main(
242  int argc,
243  char **argv
244)
245#endif
246{
247  static const char *my_file = "/b/my_file";
248
249  int fd;
250  int i;
251  int status;
252  off_t off;
253  struct dirent *d_not;
254  struct dirent **namelist;
255  struct stat s;
256
257
258  TEST_BEGIN();
259
260  printf( "\nchdir to the root directory\n" );
261  status = chdir( "/" );
262  printf( "chdir() status : %d\n\n", status );
263
264  printf( "\nCreating a series of directories under /\n" );
265  i=0;
266  while ( strcmp(dnames[i], "END") != 0 )
267  {
268     status = mkdir( dnames[i], 0x1c0 );
269     printf("Creating directory: %s      %d %d   ", dnames[i], status, errno );
270     if ( errno == 0 )
271        printf(" Success\n");
272     else
273        printf(" Failure\n");
274
275     i++;
276  }
277
278  /*
279   * Create files under many and open the directory.
280   */
281
282  printf("Create a lot of files\n");
283  status = mkdir( "/many", 0x1c0 );
284  status = chdir( "/many" );
285  for (i = 0; i<44; i++) {
286    printf("Create %s\n", many_files[i]);
287    fd = open (many_files[i], O_CREAT, S_IRWXU);
288    close (fd);
289  }
290  printf("Open /many and print the directory\n");
291  directory_not = opendir( "/many" );
292  printdir ( directory_not );
293  d_not = readdir( directory_not );
294  rtems_test_assert( d_not == 0 );
295
296  printf("open %s\n", my_file);
297  fd = open (my_file, O_CREAT, S_IRWXU);
298  rtems_test_assert( fd != -1 );
299  close (fd);
300
301  printf("scandir a file status: ");
302  status = scandir(
303     my_file,
304     &namelist,
305     select1,
306     NULL
307  );
308  printf("%d\n", status);
309
310  printf("Open /b/new_file\n");
311  fd  = open( "/b/new_file", O_CREAT, S_IRWXU );
312  rtems_test_assert( fd != -1 );
313
314  printf("fcntl F_SETFD should return 0\n");
315  status = fcntl( fd, F_SETFD, 1 );
316  rtems_test_assert( status == 0 );
317
318  printf("fcntl F_SETFD should return 1\n");
319  status = fcntl( fd, F_GETFD, 1 );
320  rtems_test_assert( status == 1 );
321
322  printf("fcntl F_DUPFD should return a file descriptor\n");
323  status = fcntl( fd, F_DUPFD, 0 );
324  rtems_test_assert ( status >= 0 );
325
326  printf("close duplicate should return 0\n");
327  status = close( status );
328  rtems_test_assert ( status == 0 );
329
330  printf("fcntl F_GETFL returns current flags\n");
331  status = fcntl( fd, F_GETFL, 1 );
332  printf("fcntl F_GETFL returned 0x%x\n", status );
333  rtems_test_assert( status != -1 );
334
335  printf("fcntl F_SETFL to add O_APPEND and O_NONBLOCK\n");
336  status = fcntl( fd, F_SETFL, O_APPEND|O_NONBLOCK );
337  rtems_test_assert ( status != -1 );
338
339  printf("fcntl F_GETFL return current flags to see changes\n");
340  status = fcntl( fd, F_GETFL, 1 );
341  printf("fcntl F_GETFL returned 0x%x\n", status );
342  rtems_test_assert( status != -1 );
343
344  printf("fcntl F_GETLK should return -1\n");
345  status = fcntl( fd, F_GETLK, 1 );
346  rtems_test_assert ( status == -1 );
347
348  printf("fcntl F_SETLK should return -1\n");
349  status = fcntl( fd, F_SETLK, 1 );
350  rtems_test_assert ( status == -1 );
351
352  printf("fcntl F_SETLKW should return -1\n");
353  status = fcntl( fd, F_SETLKW, 1 );
354  rtems_test_assert ( status == -1 );
355
356  printf("fcntl F_SETOWN should return -1\n");
357  status = fcntl( fd, F_SETOWN, 1 );
358  rtems_test_assert ( status == -1 );
359
360  printf("fcntl F_GETOWN should return -1\n");
361  status = fcntl( fd, F_GETOWN, 1 );
362  rtems_test_assert ( status == -1 );
363
364  printf("fcntl invalid argument should return -1\n");
365  status = fcntl( fd, 0xb, 1 );
366  printf("Status %d\n",status);
367  rtems_test_assert( status == -1 );
368
369  printf("close should return 0\n");
370  status = close( fd );
371  rtems_test_assert ( status == 0 );
372
373  printf("opendir, readdir and closedir %s\n", my_file);
374#ifdef O_DIRECTORY
375  fd = open( my_file, O_RDONLY );
376  rtems_test_assert( fd >= 0 );
377  directory_not = fdopendir( fd );
378#else
379  directory_not = opendir (my_file);
380#endif
381  rtems_test_assert( directory_not != NULL );
382  d_not = readdir(directory_not);
383  rtems_test_assert( d_not == NULL );
384  status = closedir (directory_not);
385  rtems_test_assert (status == 0);
386
387  printf("opendir, readdir and closedir\n");
388  directory_not = opendir ("/a");
389  rtems_test_assert( directory_not != NULL );
390  d_not = readdir (directory_not);
391  rtems_test_assert( d_not == NULL );
392  status = closedir (directory_not);
393  rtems_test_assert (status == 0);
394
395  printf("chdir to %s\n", my_file);
396  status = chdir (my_file);
397  rtems_test_assert (status == -1);
398
399  printf( "\nPerforming stat of directory /\n");
400  status = stat( "/", &s );
401  printf("status for stat : %d, size of directory: %" PRIdoff_t "\n\n", status, s.st_size);
402
403  puts( "\nOpen and print directory /" );
404  directory = opendir("/");
405  rtems_test_assert( directory );
406  printdir(directory);
407
408  printf("\nmkdir /d/my_dir\n");
409  status = mkdir( "/d/my_dir", 0x1c0 );
410  printf("Open /d/my_dir\n");
411  directory_not = opendir( "/d/my_dir" );
412  rtems_test_assert( directory_not );
413
414  printf( "remove /d/my_dir.\n" );
415  status = rmdir( "/d/my_dir" );
416  rtems_test_assert( status == 0 );
417
418  printf( "close /d/my_dir.\n" );
419  closedir( directory_not );
420
421  printf( "\nOpening directory /c\n" );
422  directory2 = opendir("/c");
423
424  rtems_test_assert( directory2 );
425
426  printdir(directory2);
427  status = closedir( directory2 );
428
429  printf( "\nOpening directory /c/y\n" );
430  directory3 = opendir("/c/y");
431  rtems_test_assert( directory3 );
432  printdir(directory3);
433  status = closedir( directory3 );
434
435  printf( "\nLSEEK to the start of the open directory\n" );
436  lseek( directory->dd_fd, 0, SEEK_SET );
437  printdir(directory);
438
439  lseek( directory->dd_fd, 0, SEEK_CUR );
440
441  lseek( directory->dd_fd, 0, SEEK_END );
442
443  lseek( directory->dd_fd, 0, -99 );
444
445  printf( "\nRewinding directory\n" );
446  rewinddir( directory );
447  printdir(directory);
448
449#if 0
450  /* Newlib's implementation does not check for NULL */
451  printf( "Send rewinddir a NULL pointer\n");
452  rewinddir( NULL );
453#endif
454
455  printf( "\nSeek directory\n" );
456  printf( "telldir() should report only sizeof(struct dirent) increments \n" );
457  printf( "in position. Sizeof(struct dirent): %zd\n",
458                          sizeof(struct dirent) );
459  rewinddir( directory );
460  for( off=0 ; off<=200 ; off=off + sizeof(struct dirent) / 4 ) {
461    seekdir( directory, off );
462    printf(
463       "seeked to %2" PRIdoff_t " -- currently at %2ld\n",
464       off,
465       telldir(directory)
466    );
467  }
468
469  printf( "Send seekdir a NULL pointer\n");
470  seekdir( NULL, off );
471
472  printf( "\nClosing directory\n" );
473  status = closedir( directory );
474
475  printf( "\nSCANDIR TEST\n");
476  printf( "\nselection rule 1\n");
477  printf( "scanning for any entry under directory /c\n\n");
478  status = scandir(
479     "/c",
480     &namelist,
481     select1,
482     NULL
483  );
484  printf("\nscandir status: %d\n", status );
485  for ( i=0; i<status; i++)
486  {
487     printf("Selected Node Name: %s\n", namelist[i]->d_name );
488  }
489
490  printf( "\nselection rule 2\n");
491  printf( "scanning for any entry under directory /c whose name = y\n\n");
492  status = scandir(
493     "/c",
494     &namelist,
495     select2,
496     NULL
497  );
498  printf("\nscandir status: %d\n", status );
499  for ( i=0; i<status; i++)
500  {
501     printf("Selected Node Name: %s\n", namelist[i]->d_name );
502  }
503
504  printf( "\nSCANDIR with sorting\n" );
505  printf( "\nselection rule 1\n");
506  printf( "scanning for any entry under directory /c\n");
507  printf( "sort in ascending order\n\n");
508  status = scandir(
509     "/c",
510     &namelist,
511     select1,
512     compare_ascending
513  );
514  printf("\nscandir status: %d\n", status );
515  for ( i=0; i<status; i++)
516  {
517     printf("Selected and Sorted Node Name: %s\n", namelist[i]->d_name );
518  }
519
520
521  printf( "\nSCANDIR with sorting\n" );
522  printf( "\nselection rule 1\n");
523  printf( "scanning for any entry under directory /c\n");
524  printf( "sort in descending order\n\n");
525  status = scandir(
526     "/c",
527     &namelist,
528     select1,
529     compare_descending
530  );
531  printf("scandir status: %d\n", status );
532  for ( i=0; i<status; i++)
533  {
534     printf("Selected and Sorted Node Name: %s\n", namelist[i]->d_name );
535  }
536
537  printf("unlink %s should return 0\n", my_file);
538  status = unlink( my_file );
539  rtems_test_assert ( status == 0 );
540
541  test_across_mount();
542  TEST_END();
543  rtems_test_exit(0);
544}
Note: See TracBrowser for help on using the repository browser.