1 /* Test the fts function.
2 Copyright 2017-2020 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
29 #define BASE "t-fts.tmp"
30 static char base
[] = BASE
; /* Not const, since argv needs non-const. */
31 static char const base_d
[] = BASE
"/d";
32 static char *const argv
[2] = { base
, 0 };
35 perror_exit (char const *message
, int status
)
41 /* alloc/dealloc to ensure structures initialized appropriately. */
45 static char dir
[] = "./";
46 static char *const curr_dir
[2] = { dir
, 0 };
47 FTS
*ftsp
= fts_open (curr_dir
, FTS_NOSTAT
| FTS_PHYSICAL
| FTS_CWDFD
, 0);
50 if (fts_close (ftsp
) != 0)
51 perror_exit ("fts_close", 9);
54 perror_exit (base
, 10);
57 /* Remove BASE and all files under it. */
62 FTS
*ftsp
= fts_open (argv
, FTS_NOSTAT
| FTS_PHYSICAL
| FTS_CWDFD
, 0);
65 while ((e
= fts_read (ftsp
)))
71 status
= unlinkat (ftsp
->fts_cwd_fd
, e
->fts_accpath
,
75 case FTS_F
: case FTS_NSOK
:
76 status
= unlinkat (ftsp
->fts_cwd_fd
, e
->fts_accpath
, 0);
80 perror_exit (e
->fts_path
, 1);
82 if (fts_close (ftsp
) != 0)
83 perror_exit ("fts_close", 2);
85 else if (errno
!= ENOENT
)
86 perror_exit (base
, 3);
94 char buf
[sizeof BASE
+ 100];
102 /* Create directories BASE, BASE/d, BASE/d/1, BASE/d/2, ..., BASE/d/65536,
103 to stress-test fts. Stop if directory creation fails due to
104 EMFILE or EMLINK problems, or if BASE/d's link count no longer matches the
106 https://bugzilla.kernel.org/show_bug.cgi?id=196405
108 if (mkdir (BASE
, 0777) != 0)
109 perror_exit (base
, 4);
110 if (mkdir (base_d
, 0777) != 0)
111 perror_exit (base_d
, 5);
112 for (i
= 1; i
<= 65536; i
++)
114 sprintf (buf
, "%s/d/%i", base
, i
);
115 if (mkdir (buf
, 0777) != 0)
117 if (errno
== EMFILE
|| errno
== EMLINK
)
120 perror_exit (buf
, 77);
123 if (needles
< i
&& stat (base_d
, &st
) == 0 && st
.st_nlink
!= i
+ 2)
127 /* Create empty files BASE/d/1/needle etc. */
128 for (i
= 1; i
<= needles
; i
++)
131 sprintf (buf
, "%s/d/%d/needle", base
, i
);
132 fd
= open (buf
, O_WRONLY
| O_CREAT
, 0666);
133 if (fd
< 0 || close (fd
) != 0)
134 perror_exit (buf
, 77);
137 /* Use fts to look for the needles. */
138 ftsp
= fts_open (argv
, FTS_SEEDOT
| FTS_NOSTAT
| FTS_PHYSICAL
| FTS_CWDFD
, 0);
140 perror_exit (base
, 6);
141 while ((e
= fts_read (ftsp
)))
142 needles_seen
+= strcmp (e
->fts_name
, "needle") == 0;
143 int fts_read_errno
= errno
;
147 errno
= fts_read_errno
;
148 perror_exit ("fts_read", 7);
150 if (fts_close (ftsp
) != 0)
151 perror_exit (base
, 8);
153 /* Report an error if we did not find the needles. */
154 if (needles_seen
!= needles
)
156 fprintf (stderr
, "%d needles found (should be %d)\n",
157 needles_seen
, needles
);
162 if (stat (base
, &st
) == 0)
164 fprintf (stderr
, "fts could not remove directory\n");