]>
Commit | Line | Data |
---|---|---|
8b7b7f75 | 1 | /* Simple test for some fts functions. |
04277e02 | 2 | Copyright (C) 2015-2019 Free Software Foundation, Inc. |
8b7b7f75 MW |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
17 | <http://www.gnu.org/licenses/>. */ | |
18 | ||
19 | #include <sys/types.h> | |
20 | #include <sys/stat.h> | |
21 | #include <fts.h> | |
22 | ||
23 | #include <errno.h> | |
24 | #include <error.h> | |
25 | #include <string.h> | |
26 | #include <stdio.h> | |
27 | #include <stdlib.h> | |
28 | #include <unistd.h> | |
29 | ||
30 | static void prepare (void); | |
31 | static int do_test (void); | |
32 | #define PREPARE(argc, argv) prepare () | |
33 | #define TEST_FUNCTION do_test () | |
34 | #include "../test-skeleton.c" | |
35 | ||
36 | static char *fts_test_dir; | |
37 | ||
38 | static void | |
39 | make_dir (const char *dirname) | |
40 | { | |
41 | char *name; | |
42 | if (asprintf (&name, "%s/%s", fts_test_dir, dirname) < 0) | |
43 | { | |
44 | puts ("out of memory"); | |
45 | exit (1); | |
46 | } | |
47 | ||
48 | if (mkdir (name, 0700) < 0) | |
49 | { | |
50 | printf ("cannot create dir \"%s\": %m\n", name); | |
51 | exit (1); | |
52 | } | |
53 | ||
54 | add_temp_file (name); | |
55 | } | |
56 | ||
57 | static void | |
58 | make_file (const char *filename) | |
59 | { | |
60 | char *name; | |
61 | if (asprintf (&name, "%s/%s", fts_test_dir, filename) < 0) | |
62 | { | |
63 | puts ("out of memory"); | |
64 | exit (1); | |
65 | } | |
66 | ||
67 | int fd = open (name, O_WRONLY | O_CREAT | O_EXCL, 0600); | |
68 | if (fd < 0) | |
69 | { | |
70 | printf ("cannot create file \"%s\": %m\n", name); | |
71 | exit (1); | |
72 | } | |
73 | close (fd); | |
74 | ||
75 | add_temp_file (name); | |
76 | } | |
77 | ||
78 | static void | |
79 | prepare (void) | |
80 | { | |
81 | char *dirbuf; | |
82 | char dir_name[] = "/tst-fts.XXXXXX"; | |
83 | ||
84 | if (asprintf (&dirbuf, "%s%s", test_dir, dir_name) < 0) | |
85 | { | |
86 | puts ("out of memory"); | |
87 | exit (1); | |
88 | } | |
89 | ||
90 | if (mkdtemp (dirbuf) == NULL) | |
91 | { | |
92 | puts ("cannot create temporary directory"); | |
93 | exit (1); | |
94 | } | |
95 | ||
96 | add_temp_file (dirbuf); | |
97 | fts_test_dir = dirbuf; | |
98 | ||
99 | make_file ("12"); | |
100 | make_file ("345"); | |
101 | make_file ("6789"); | |
102 | ||
103 | make_dir ("aaa"); | |
104 | make_file ("aaa/1234"); | |
105 | make_file ("aaa/5678"); | |
106 | ||
107 | make_dir ("bbb"); | |
108 | make_file ("bbb/1234"); | |
109 | make_file ("bbb/5678"); | |
110 | make_file ("bbb/90ab"); | |
111 | } | |
112 | ||
113 | /* Largest name wins, otherwise strcmp. */ | |
114 | static int | |
115 | compare_ents (const FTSENT **ent1, const FTSENT **ent2) | |
116 | { | |
117 | short len1 = (*ent1)->fts_namelen; | |
118 | short len2 = (*ent2)->fts_namelen; | |
119 | if (len1 != len2) | |
120 | return len1 - len2; | |
121 | else | |
122 | { | |
123 | const char *name1 = (*ent1)->fts_name; | |
124 | const char *name2 = (*ent2)->fts_name; | |
125 | return strcmp (name1, name2); | |
126 | } | |
127 | } | |
128 | ||
129 | /* Count the number of files seen as children. */ | |
130 | static int files = 0; | |
131 | ||
132 | static void | |
133 | children (FTS *fts) | |
134 | { | |
135 | FTSENT *child = fts_children (fts, 0); | |
136 | if (child == NULL && errno != 0) | |
137 | { | |
138 | printf ("FAIL: fts_children: %m\n"); | |
139 | exit (1); | |
140 | } | |
141 | ||
142 | while (child != NULL) | |
143 | { | |
144 | short level = child->fts_level; | |
145 | const char *name = child->fts_name; | |
146 | if (child->fts_info == FTS_F || child->fts_info == FTS_NSOK) | |
147 | { | |
148 | files++; | |
149 | printf ("%*s%s\n", 2 * level, "", name); | |
150 | } | |
151 | child = child->fts_link; | |
152 | } | |
153 | } | |
154 | ||
155 | /* Count the number of dirs seen in the test. */ | |
156 | static int dirs = 0; | |
157 | ||
158 | static int | |
159 | do_test (void) | |
160 | { | |
161 | char *paths[2] = { fts_test_dir, NULL }; | |
162 | FTS *fts; | |
163 | fts = fts_open (paths, FTS_LOGICAL, &compare_ents); | |
164 | if (fts == NULL) | |
165 | { | |
166 | printf ("FAIL: fts_open: %m\n"); | |
167 | exit (1); | |
168 | } | |
169 | ||
170 | FTSENT *ent; | |
171 | while ((ent = fts_read (fts)) != NULL) | |
172 | { | |
173 | const char *name = ent->fts_name; | |
174 | short level = ent->fts_level; | |
175 | switch (ent->fts_info) | |
176 | { | |
177 | case FTS_F: | |
178 | /* Don't show anything, children will have on parent dir. */ | |
179 | break; | |
180 | ||
181 | case FTS_D: | |
182 | printf ("%*s%s =>\n", 2 * level, "", name); | |
183 | children (fts); | |
184 | break; | |
185 | ||
186 | case FTS_DP: | |
187 | dirs++; | |
188 | printf ("%*s<= %s\n", 2 * level, "", name); | |
189 | break; | |
190 | ||
191 | case FTS_NS: | |
192 | case FTS_ERR: | |
193 | printf ("FAIL: fts_read ent: %s\n", strerror (ent->fts_errno)); | |
194 | exit (1); | |
195 | break; | |
196 | ||
197 | default: | |
198 | printf ("FAIL: unexpected fts_read ent %s\n", name); | |
199 | exit (1); | |
200 | break; | |
201 | } | |
202 | } | |
203 | /* fts_read returns NULL when done (and clears errno) | |
204 | or when an error occured (with errno set). */ | |
205 | if (errno != 0) | |
206 | { | |
207 | printf ("FAIL: fts_read: %m\n"); | |
208 | exit (1); | |
209 | } | |
210 | ||
211 | if (fts_close (fts) != 0) | |
212 | { | |
213 | printf ("FAIL: fts_close: %m\n"); | |
214 | exit (1); | |
215 | } | |
216 | ||
217 | if (files != 8) | |
218 | { | |
219 | printf ("FAIL: Unexpected number of files: %d\n", files); | |
220 | return 1; | |
221 | } | |
222 | ||
223 | if (dirs != 3) | |
224 | { | |
225 | printf ("FAIL: Unexpected number of dirs: %d\n", dirs); | |
226 | return 1; | |
227 | } | |
228 | ||
229 | puts ("PASS"); | |
230 | return 0; | |
231 | } |