source: rtems/testsuites/psxtests/psxreaddir/test.c

Last change on this file was 5594854, checked in by Joel Sherrill <joel@…>, on 04/07/22 at 15:05:28

testsuites/psxtests/psx[n-z]*: Change license to BSD-2

Updates #3053.

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