]> git.ipfire.org Git - thirdparty/glibc.git/blob - posix/tst-dir.c
Update.
[thirdparty/glibc.git] / posix / tst-dir.c
1 #include <dirent.h>
2 #include <fcntl.h>
3 #include <mcheck.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <sys/stat.h>
9
10
11 /* We expect four arguments:
12 - source directory name
13 - object directory
14 - common object directory
15 - the program name with path
16 */
17 int
18 main (int argc, char *argv[])
19 {
20 const char *srcdir;
21 const char *objdir;
22 const char *common_objdir;
23 const char *progpath;
24 struct stat64 st1;
25 struct stat64 st2;
26 struct stat64 st3;
27 DIR *dir1;
28 DIR *dir2;
29 int result = 0;
30 struct dirent64 *d;
31 struct dirent64 direntbuf;
32 char *objdir_copy1;
33 char *objdir_copy2;
34 char *buf;
35 int fd;
36
37 mtrace ();
38
39 if (argc < 5)
40 {
41 puts ("not enough parameters");
42 exit (1);
43 }
44
45 /* Make parameters available with nicer names. */
46 srcdir = argv[1];
47 objdir = argv[2];
48 common_objdir = argv[3];
49 progpath = argv[4];
50
51 /* First test the current source dir. We cannot really compare the
52 result of `getpwd' with the srcdir string but we have other means. */
53 if (stat64 (".", &st1) < 0)
54 {
55 printf ("cannot stat starting directory: %m\n");
56 exit (1);
57 }
58
59 if (chdir (srcdir) < 0)
60 {
61 printf ("cannot change to source directory: %m\n");
62 exit (1);
63 }
64 if (stat64 (".", &st2) < 0)
65 {
66 printf ("cannot stat source directory: %m\n");
67 exit (1);
68 }
69
70 /* The two last stat64 calls better were for the same directory. */
71 if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
72 {
73 printf ("stat of source directory failed: (%lld,%lld) vs (%lld,%lld)\n",
74 (long long int) st1.st_dev, (long long int) st1.st_ino,
75 (long long int) st2.st_dev, (long long int) st2.st_ino);
76 exit (1);
77 }
78
79 /* Change to the object directory. */
80 if (chdir (objdir) < 0)
81 {
82 printf ("cannot change to object directory: %m\n");
83 exit (1);
84 }
85 if (stat64 (".", &st1) < 0)
86 {
87 printf ("cannot stat object directory: %m\n");
88 exit (1);
89 }
90 /* Is this the same we get as with the full path? */
91 if (stat64 (objdir, &st2) < 0)
92 {
93 printf ("cannot stat object directory with full path: %m\n");
94 exit (1);
95 }
96 if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
97 {
98 printf ("stat of object directory failed: (%lld,%lld) vs (%lld,%lld)\n",
99 (long long int) st1.st_dev, (long long int) st1.st_ino,
100 (long long int) st2.st_dev, (long long int) st2.st_ino);
101 exit (1);
102 }
103
104 objdir_copy1 = getcwd (NULL, 0);
105 if (objdir_copy1 == NULL)
106 {
107 printf ("cannot get current directory name for object directory: %m\n");
108 result = 1;
109 }
110
111 /* First test: this directory must include our program. */
112 if (stat64 (progpath, &st2) < 0)
113 {
114 printf ("cannot stat program: %m\n");
115 exit (1);
116 }
117
118 dir1 = opendir (".");
119 if (dir1 == NULL)
120 {
121 printf ("cannot open object directory: %m\n");
122 exit (1);
123 }
124
125 while ((d = readdir64 (dir1)) != NULL)
126 {
127 #ifdef _DIRENT_HAVE_D_TYPE
128 if (d->d_type != DT_UNKNOWN && d->d_type != DT_REG)
129 continue;
130 #endif
131
132 if (d->d_ino == st2.st_ino)
133 {
134 /* Might be it. Test the device. We could use the st_dev
135 element from st1 but what the heck, do more testing. */
136 if (stat64 (d->d_name, &st3) < 0)
137 {
138 printf ("cannot stat entry from readdir: %m\n");
139 result = 1;
140 d = NULL;
141 break;
142 }
143
144 if (st3.st_dev == st2.st_dev)
145 break;
146 }
147 }
148
149 if (d == NULL)
150 {
151 puts ("haven't found program in object directory");
152 result = 1;
153 }
154
155 /* We leave dir1 open. */
156
157 /* Stat using file descriptor. */
158 if (fstat64 (dirfd (dir1), &st2) < 0)
159 {
160 printf ("cannot fstat object directory: %m\n");
161 result = 1;
162 }
163 if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
164 {
165 printf ("fstat of object directory failed: (%lld,%lld) vs (%lld,%lld)\n",
166 (long long int) st1.st_dev, (long long int) st1.st_ino,
167 (long long int) st2.st_dev, (long long int) st2.st_ino);
168 exit (1);
169 }
170
171 if (chdir ("..") < 0)
172 {
173 printf ("cannot go to common object directory with \"..\": %m\n");
174 exit (1);
175 }
176
177 if (stat64 (".", &st1) < 0)
178 {
179 printf ("cannot stat common object directory: %m\n");
180 exit (1);
181 }
182 /* Is this the same we get as with the full path? */
183 if (stat64 (common_objdir, &st2) < 0)
184 {
185 printf ("cannot stat common object directory with full path: %m\n");
186 exit (1);
187 }
188 if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
189 {
190 printf ("stat of object directory failed: (%lld,%lld) vs (%lld,%lld)\n",
191 (long long int) st1.st_dev, (long long int) st1.st_ino,
192 (long long int) st2.st_dev, (long long int) st2.st_ino);
193 exit (1);
194 }
195
196 /* Stat using file descriptor. */
197 if (fstat64 (dirfd (dir1), &st2) < 0)
198 {
199 printf ("cannot fstat object directory: %m\n");
200 result = 1;
201 }
202
203 dir2 = opendir (common_objdir);
204 if (dir2 == NULL)
205 {
206 printf ("cannot open common object directory: %m\n");
207 exit (1);
208 }
209
210 while ((d = readdir64 (dir2)) != NULL)
211 {
212 #ifdef _DIRENT_HAVE_D_TYPE
213 if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
214 continue;
215 #endif
216
217 if (d->d_ino == st2.st_ino)
218 {
219 /* Might be it. Test the device. We could use the st_dev
220 element from st1 but what the heck, do more testing. */
221 if (stat64 (d->d_name, &st3) < 0)
222 {
223 printf ("cannot stat entry from readdir: %m\n");
224 result = 1;
225 d = NULL;
226 break;
227 }
228
229 if (st3.st_dev == st2.st_dev)
230 break;
231 }
232 }
233
234 /* This better should be the object directory again. */
235 if (fchdir (dirfd (dir1)) < 0)
236 {
237 printf ("cannot fchdir to object directory: %m\n");
238 exit (1);
239 }
240
241 objdir_copy2 = getcwd (NULL, 0);
242 if (objdir_copy2 == NULL)
243 {
244 printf ("cannot get current directory name for object directory: %m\n");
245 result = 1;
246 }
247 if (strcmp (objdir_copy1, objdir_copy2) != 0)
248 {
249 puts ("getcwd returned a different string the second time");
250 result = 1;
251 }
252
253 /* This better should be the common object directory again. */
254 if (fchdir (dirfd (dir2)) < 0)
255 {
256 printf ("cannot fchdir to common object directory: %m\n");
257 exit (1);
258 }
259
260 if (stat64 (".", &st2) < 0)
261 {
262 printf ("cannot stat common object directory: %m\n");
263 exit (1);
264 }
265 if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
266 {
267 printf ("stat of object directory failed: (%lld,%lld) vs (%lld,%lld)\n",
268 (long long int) st1.st_dev, (long long int) st1.st_ino,
269 (long long int) st2.st_dev, (long long int) st2.st_ino);
270 exit (1);
271 }
272
273 buf = (char *) malloc (strlen (objdir_copy1) + 1 + sizeof "tst-dir.XXXXXX");
274 if (buf == NULL)
275 {
276 printf ("cannot allocate buffer: %m");
277 exit (1);
278 }
279
280 stpcpy (stpcpy (stpcpy (buf, objdir_copy1), "/"), "tst-dir.XXXXXX");
281 if (mkdtemp (buf) == NULL)
282 {
283 printf ("cannot create test directory in object directory: %m\n");
284 exit (1);
285 }
286 if (stat64 (buf, &st1) < 0)
287 {
288 printf ("cannot stat new directory \"%s\": %m\n", buf);
289 exit (1);
290 }
291 if (chmod (buf, 0700) < 0)
292 {
293 printf ("cannot change mode of new directory: %m\n");
294 exit (1);
295 }
296
297 /* Try to find the new directory. */
298 rewinddir (dir1);
299 while (readdir64_r (dir1, &direntbuf, &d) == 0)
300 {
301 #ifdef _DIRENT_HAVE_D_TYPE
302 if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
303 continue;
304 #endif
305
306 if (d->d_ino == st1.st_ino)
307 {
308 /* Might be it. Test the device. We could use the st_dev
309 element from st1 but what the heck, do more testing. */
310 size_t len = strlen (objdir) + 1 + _D_EXACT_NAMLEN (d) + 1;
311 char tmpbuf[len];
312
313 stpcpy (stpcpy (stpcpy (tmpbuf, objdir), "/"), d->d_name);
314
315 if (stat64 (tmpbuf, &st3) < 0)
316 {
317 printf ("cannot stat entry from readdir: %m\n");
318 result = 1;
319 d = NULL;
320 break;
321 }
322
323 if (st3.st_dev == st2.st_dev
324 && strcmp (d->d_name, buf + strlen (buf) - 14) == 0)
325 break;
326 }
327 }
328
329 if (d == NULL)
330 {
331 printf ("haven't found new directory \"%s\"\n", buf);
332 exit (1);
333 }
334
335 if (closedir (dir2) < 0)
336 {
337 printf ("closing dir2 failed: %m\n");
338 result = 1;
339 }
340
341 if (chdir (buf)< 0)
342 {
343 printf ("cannot change to new directory: %m\n");
344 exit (1);
345 }
346
347 dir2 = opendir (buf);
348 if (dir2 == NULL)
349 {
350 printf ("cannot open new directory: %m\n");
351 exit (1);
352 }
353
354 if (fstat64 (dirfd (dir2), &st2) < 0)
355 {
356 printf ("cannot fstat new directory \"%s\": %m\n", buf);
357 exit (1);
358 }
359 if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
360 {
361 printf ("stat of new directory failed: (%lld,%lld) vs (%lld,%lld)\n",
362 (long long int) st1.st_dev, (long long int) st1.st_ino,
363 (long long int) st2.st_dev, (long long int) st2.st_ino);
364 exit (1);
365 }
366
367 if (mkdir ("another-dir", 0777) < 0)
368 {
369 printf ("cannot create \"another-dir\": %m\n");
370 exit (1);
371 }
372 fd = open ("and-a-file", O_RDWR | O_CREAT | O_EXCL, 0666);
373 if (fd == -1)
374 {
375 printf ("cannot create \"and-a-file\": %m\n");
376 exit (1);
377 }
378 close (fd);
379
380 /* We now should have a directory and a file in the new directory. */
381 rewinddir (dir2);
382 while (readdir64_r (dir2, &direntbuf, &d) == 0 && d != NULL)
383 {
384 if (strcmp (d->d_name, ".") == 0
385 || strcmp (d->d_name, "..") == 0
386 || strcmp (d->d_name, "another-dir") == 0)
387 {
388 #ifdef _DIRENT_HAVE_D_TYPE
389 if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
390 {
391 printf ("d_type for \"%s\" is wrong\n", d->d_name);
392 result = 1;
393 }
394 #endif
395 if (stat64 (d->d_name, &st3) < 0)
396 {
397 printf ("cannot stat \"%s\" is wrong\n", d->d_name);
398 result = 1;
399 }
400 else if (! S_ISDIR (st3.st_mode))
401 {
402 printf ("\"%s\" is no directory\n", d->d_name);
403 result = 1;
404 }
405 }
406 else if (strcmp (d->d_name, "and-a-file") == 0)
407 {
408 #ifdef _DIRENT_HAVE_D_TYPE
409 if (d->d_type != DT_UNKNOWN && d->d_type != DT_REG)
410 {
411 printf ("d_type for \"%s\" is wrong\n", d->d_name);
412 result = 1;
413 }
414 #endif
415 if (stat64 (d->d_name, &st3) < 0)
416 {
417 printf ("cannot stat \"%s\" is wrong\n", d->d_name);
418 result = 1;
419 }
420 else if (! S_ISREG (st3.st_mode))
421 {
422 printf ("\"%s\" is no regular file\n", d->d_name);
423 result = 1;
424 }
425 }
426 else
427 {
428 printf ("unexpected directory entry \"%s\"\n", d->d_name);
429 result = 1;
430 }
431 }
432
433 /* Free all resources. */
434
435 if (closedir (dir1) < 0)
436 {
437 printf ("closing dir1 failed: %m\n");
438 result = 1;
439 }
440 if (closedir (dir2) < 0)
441 {
442 printf ("second closing dir2 failed: %m\n");
443 result = 1;
444 }
445
446 if (rmdir ("another-dir") < 0)
447 {
448 printf ("cannot remove \"another-dir\": %m\n");
449 result = 1;
450 }
451
452 if (unlink ("and-a-file") < 0)
453 {
454 printf ("cannot remove \"and-a-file\": %m\n");
455 result = 1;
456 }
457
458 if (chdir (srcdir) < 0)
459 {
460 printf ("cannot change back to source directory: %m\n");
461 exit (1);
462 }
463
464 if (rmdir (buf) < 0)
465 {
466 printf ("cannot remove \"%s\": %m\n", buf);
467 result = 1;
468 }
469 free (objdir_copy1);
470 free (objdir_copy2);
471
472 if (result == 0)
473 puts ("all OK");
474
475 return result;
476 }