source: branches/libc-0.6/src/libctests/glibc/posix/tst-dir.c

Last change on this file was 2135, checked in by bird, 20 years ago

libc adjustments / config.

  • Property cvs2svn:cvs-rev set to 1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 14.0 KB
Line 
1/* Copyright (C) 2000-2002 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20#include <dirent.h>
21#include <errno.h>
22#include <fcntl.h>
23#include <mcheck.h>
24#include <stddef.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29#include <sys/stat.h>
30
31#ifndef HAVE_64BIT_FILEIO_TYPES
32#define stat64 stat
33#define fstat64 fstat
34#define dirent64 dirent
35#define readdir64_r readdir_r
36#define readdir64 readdir
37#endif
38#ifdef __EMX__
39#warning fchdir still not implemented?
40#define fchdir(fd) (-1)
41#endif
42
43
44/* We expect four arguments:
45 - source directory name
46 - object directory
47 - common object directory
48 - the program name with path
49*/
50int
51main (int argc, char *argv[])
52{
53 const char *srcdir;
54 const char *objdir;
55 const char *common_objdir;
56 const char *progpath;
57 struct stat64 st1;
58 struct stat64 st2;
59 struct stat64 st3;
60 DIR *dir1;
61 DIR *dir2;
62 int result = 0;
63 struct dirent64 *d;
64 union
65 {
66 struct dirent64 d;
67 char room [offsetof (struct dirent64, d_name[0]) + NAME_MAX + 1];
68 }
69 direntbuf;
70 char *objdir_copy1;
71 char *objdir_copy2;
72 char *buf;
73 int fd;
74
75 mtrace ();
76
77 if (argc < 5)
78 {
79 puts ("not enough parameters");
80 exit (1);
81 }
82
83 /* Make parameters available with nicer names. */
84 srcdir = argv[1];
85 objdir = argv[2];
86 common_objdir = argv[3];
87 progpath = argv[4];
88
89 /* First test the current source dir. We cannot really compare the
90 result of `getpwd' with the srcdir string but we have other means. */
91 if (stat64 (".", &st1) < 0)
92 {
93 printf ("cannot stat starting directory: %m\n");
94 exit (1);
95 }
96
97 if (chdir (srcdir) < 0)
98 {
99 printf ("cannot change to source directory: %m\n");
100 exit (1);
101 }
102 if (stat64 (".", &st2) < 0)
103 {
104 printf ("cannot stat source directory: %m\n");
105 exit (1);
106 }
107
108 /* The two last stat64 calls better were for the same directory. */
109 if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
110 {
111 printf ("stat of source directory failed: (%lld,%lld) vs (%lld,%lld)\n",
112 (long long int) st1.st_dev, (long long int) st1.st_ino,
113 (long long int) st2.st_dev, (long long int) st2.st_ino);
114 exit (1);
115 }
116
117 /* Change to the object directory. */
118 if (chdir (objdir) < 0)
119 {
120 printf ("cannot change to object directory: %m\n");
121 exit (1);
122 }
123 if (stat64 (".", &st1) < 0)
124 {
125 printf ("cannot stat object directory: %m\n");
126 exit (1);
127 }
128 /* Is this the same we get as with the full path? */
129 if (stat64 (objdir, &st2) < 0)
130 {
131 printf ("cannot stat object directory with full path: %m\n");
132 exit (1);
133 }
134 if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
135 {
136 printf ("stat of object directory failed: (%lld,%lld) vs (%lld,%lld)\n",
137 (long long int) st1.st_dev, (long long int) st1.st_ino,
138 (long long int) st2.st_dev, (long long int) st2.st_ino);
139 exit (1);
140 }
141
142 objdir_copy1 = getcwd (NULL, 0);
143 if (objdir_copy1 == NULL)
144 {
145 printf ("cannot get current directory name for object directory: %m\n");
146 result = 1;
147 }
148
149 /* First test: this directory must include our program. */
150 if (stat64 (progpath, &st2) < 0)
151 {
152 printf ("cannot stat program: %m\n");
153 exit (1);
154 }
155
156 dir1 = opendir (".");
157 if (dir1 == NULL)
158 {
159 printf ("cannot open object directory: %m\n");
160 exit (1);
161 }
162
163 while ((d = readdir64 (dir1)) != NULL)
164 {
165#ifdef _DIRENT_HAVE_D_TYPE
166 if (d->d_type != DT_UNKNOWN && d->d_type != DT_REG)
167 continue;
168#endif
169
170 if (d->d_ino == st2.st_ino)
171 {
172 /* Might be it. Test the device. We could use the st_dev
173 element from st1 but what the heck, do more testing. */
174 if (stat64 (d->d_name, &st3) < 0)
175 {
176 printf ("cannot stat entry from readdir: %m\n");
177 result = 1;
178 d = NULL;
179 break;
180 }
181
182 if (st3.st_dev == st2.st_dev)
183 break;
184 }
185 }
186
187 if (d == NULL)
188 {
189 puts ("haven't found program in object directory");
190 result = 1;
191 }
192
193 /* We leave dir1 open. */
194
195 /* Stat using file descriptor. */
196 if (fstat64 (dirfd (dir1), &st2) < 0)
197 {
198 printf ("cannot fstat object directory: %m\n");
199 result = 1;
200 }
201 if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
202 {
203 printf ("fstat of object directory failed: (%lld,%lld) vs (%lld,%lld)\n",
204 (long long int) st1.st_dev, (long long int) st1.st_ino,
205 (long long int) st2.st_dev, (long long int) st2.st_ino);
206 exit (1);
207 }
208
209 if (chdir ("..") < 0)
210 {
211 printf ("cannot go to common object directory with \"..\": %m\n");
212 exit (1);
213 }
214
215 if (stat64 (".", &st1) < 0)
216 {
217 printf ("cannot stat common object directory: %m\n");
218 exit (1);
219 }
220 /* Is this the same we get as with the full path? */
221 if (stat64 (common_objdir, &st2) < 0)
222 {
223 printf ("cannot stat common object directory with full path: %m\n");
224 exit (1);
225 }
226 if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
227 {
228 printf ("stat of object directory failed: (%lld,%lld) vs (%lld,%lld)\n",
229 (long long int) st1.st_dev, (long long int) st1.st_ino,
230 (long long int) st2.st_dev, (long long int) st2.st_ino);
231 exit (1);
232 }
233
234 /* Stat using file descriptor. */
235 if (fstat64 (dirfd (dir1), &st2) < 0)
236 {
237 printf ("cannot fstat object directory: %m\n");
238 result = 1;
239 }
240
241 dir2 = opendir (common_objdir);
242 if (dir2 == NULL)
243 {
244 printf ("cannot open common object directory: %m\n");
245 exit (1);
246 }
247
248 while ((d = readdir64 (dir2)) != NULL)
249 {
250#ifdef _DIRENT_HAVE_D_TYPE
251 if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
252 continue;
253#endif
254
255 if (d->d_ino == st2.st_ino)
256 {
257 /* Might be it. Test the device. We could use the st_dev
258 element from st1 but what the heck, do more testing. */
259 if (stat64 (d->d_name, &st3) < 0)
260 {
261 printf ("cannot stat entry from readdir: %m\n");
262 result = 1;
263 d = NULL;
264 break;
265 }
266
267 if (st3.st_dev == st2.st_dev)
268 break;
269 }
270 }
271
272 /* This better should be the object directory again. */
273 if (fchdir (dirfd (dir1)) < 0)
274 {
275 printf ("cannot fchdir to object directory: %m\n");
276 exit (1);
277 }
278
279 objdir_copy2 = getcwd (NULL, 0);
280 if (objdir_copy2 == NULL)
281 {
282 printf ("cannot get current directory name for object directory: %m\n");
283 result = 1;
284 }
285 if (strcmp (objdir_copy1, objdir_copy2) != 0)
286 {
287 puts ("getcwd returned a different string the second time");
288 result = 1;
289 }
290
291 /* This better should be the common object directory again. */
292 if (fchdir (dirfd (dir2)) < 0)
293 {
294 printf ("cannot fchdir to common object directory: %m\n");
295 exit (1);
296 }
297
298 if (stat64 (".", &st2) < 0)
299 {
300 printf ("cannot stat common object directory: %m\n");
301 exit (1);
302 }
303 if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
304 {
305 printf ("stat of object directory failed: (%lld,%lld) vs (%lld,%lld)\n",
306 (long long int) st1.st_dev, (long long int) st1.st_ino,
307 (long long int) st2.st_dev, (long long int) st2.st_ino);
308 exit (1);
309 }
310
311 buf = (char *) malloc (strlen (objdir_copy1) + 1 + sizeof "tst-dir.XXXXXX");
312 if (buf == NULL)
313 {
314 printf ("cannot allocate buffer: %m");
315 exit (1);
316 }
317
318 stpcpy (stpcpy (stpcpy (buf, objdir_copy1), "/"), "tst-dir.XXXXXX");
319 if (mkdtemp (buf) == NULL)
320 {
321 printf ("cannot create test directory in object directory: %m\n");
322 exit (1);
323 }
324 if (stat64 (buf, &st1) < 0)
325 {
326 printf ("cannot stat new directory \"%s\": %m\n", buf);
327 exit (1);
328 }
329 if (chmod (buf, 0700) < 0)
330 {
331 printf ("cannot change mode of new directory: %m\n");
332 exit (1);
333 }
334
335 /* Try to find the new directory. */
336 rewinddir (dir1);
337 while (readdir64_r (dir1, &direntbuf.d, &d) == 0 && d != NULL)
338 {
339#ifdef _DIRENT_HAVE_D_TYPE
340 if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
341 continue;
342#endif
343
344 if (d->d_ino == st1.st_ino)
345 {
346 /* Might be it. Test the device. We could use the st_dev
347 element from st1 but what the heck, do more testing. */
348 size_t len = strlen (objdir) + 1 + _D_EXACT_NAMLEN (d) + 1;
349 char tmpbuf[len];
350
351 stpcpy (stpcpy (stpcpy (tmpbuf, objdir), "/"), d->d_name);
352
353 if (stat64 (tmpbuf, &st3) < 0)
354 {
355 printf ("cannot stat entry from readdir: %m\n");
356 result = 1;
357 d = NULL;
358 break;
359 }
360
361 if (st3.st_dev == st2.st_dev
362 && strcmp (d->d_name, buf + strlen (buf) - 14) == 0)
363 break;
364 }
365 }
366
367 if (d == NULL)
368 {
369 printf ("haven't found new directory \"%s\"\n", buf);
370 exit (1);
371 }
372
373 if (closedir (dir2) < 0)
374 {
375 printf ("closing dir2 failed: %m\n");
376 result = 1;
377 }
378
379 if (chdir (buf) < 0)
380 {
381 printf ("cannot change to new directory: %m\n");
382 exit (1);
383 }
384
385 dir2 = opendir (buf);
386 if (dir2 == NULL)
387 {
388 printf ("cannot open new directory: %m\n");
389 exit (1);
390 }
391
392 if (fstat64 (dirfd (dir2), &st2) < 0)
393 {
394 printf ("cannot fstat new directory \"%s\": %m\n", buf);
395 exit (1);
396 }
397 if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
398 {
399 printf ("stat of new directory failed: (%lld,%lld) vs (%lld,%lld)\n",
400 (long long int) st1.st_dev, (long long int) st1.st_ino,
401 (long long int) st2.st_dev, (long long int) st2.st_ino);
402 exit (1);
403 }
404
405 if (mkdir ("another-dir", 0777) < 0)
406 {
407 printf ("cannot create \"another-dir\": %m\n");
408 exit (1);
409 }
410 fd = open ("and-a-file", O_RDWR | O_CREAT | O_EXCL, 0666);
411 if (fd == -1)
412 {
413 printf ("cannot create \"and-a-file\": %m\n");
414 exit (1);
415 }
416 close (fd);
417
418 /* Some tests about error reporting. */
419 errno = 0;
420 if (chdir ("and-a-file") >= 0)
421 {
422 printf ("chdir to \"and-a-file\" succeeded\n");
423 exit (1);
424 }
425 if (errno != ENOTDIR)
426 {
427 printf ("chdir to \"and-a-file\" didn't set correct error\n");
428 result = 1;
429 }
430
431 errno = 0;
432 if (chdir ("and-a-file/..") >= 0)
433 {
434 printf ("chdir to \"and-a-file/..\" succeeded\n");
435 exit (1);
436 }
437 if (errno != ENOTDIR)
438 {
439 printf ("chdir to \"and-a-file/..\" didn't set correct error\n");
440 result = 1;
441 }
442
443 errno = 0;
444 if (chdir ("another-dir/../and-a-file") >= 0)
445 {
446 printf ("chdir to \"another-dir/../and-a-file\" succeeded\n");
447 exit (1);
448 }
449 if (errno != ENOTDIR)
450 {
451 printf ("chdir to \"another-dir/../and-a-file\" didn't set correct error\n");
452 result = 1;
453 }
454
455 /* We now should have a directory and a file in the new directory. */
456 rewinddir (dir2);
457 while (readdir64_r (dir2, &direntbuf.d, &d) == 0 && d != NULL)
458 {
459 if (strcmp (d->d_name, ".") == 0
460 || strcmp (d->d_name, "..") == 0
461 || strcmp (d->d_name, "another-dir") == 0)
462 {
463#ifdef _DIRENT_HAVE_D_TYPE
464 if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
465 {
466 printf ("d_type for \"%s\" is wrong\n", d->d_name);
467 result = 1;
468 }
469#endif
470 if (stat64 (d->d_name, &st3) < 0)
471 {
472 printf ("cannot stat \"%s\" is wrong\n", d->d_name);
473 result = 1;
474 }
475 else if (! S_ISDIR (st3.st_mode))
476 {
477 printf ("\"%s\" is no directory\n", d->d_name);
478 result = 1;
479 }
480 }
481 else if (strcmp (d->d_name, "and-a-file") == 0)
482 {
483#ifdef _DIRENT_HAVE_D_TYPE
484 if (d->d_type != DT_UNKNOWN && d->d_type != DT_REG)
485 {
486 printf ("d_type for \"%s\" is wrong\n", d->d_name);
487 result = 1;
488 }
489#endif
490 if (stat64 (d->d_name, &st3) < 0)
491 {
492 printf ("cannot stat \"%s\" is wrong\n", d->d_name);
493 result = 1;
494 }
495 else if (! S_ISREG (st3.st_mode))
496 {
497 printf ("\"%s\" is no regular file\n", d->d_name);
498 result = 1;
499 }
500 }
501 else
502 {
503 printf ("unexpected directory entry \"%s\"\n", d->d_name);
504 result = 1;
505 }
506 }
507
508 if (stat64 ("does-not-exist", &st1) >= 0)
509 {
510 puts ("stat for unexisting file did not fail");
511 result = 1;
512 }
513
514 /* Free all resources. */
515
516 if (closedir (dir1) < 0)
517 {
518 printf ("closing dir1 failed: %m\n");
519 result = 1;
520 }
521 if (closedir (dir2) < 0)
522 {
523 printf ("second closing dir2 failed: %m\n");
524 result = 1;
525 }
526
527 if (rmdir ("another-dir") < 0)
528 {
529 printf ("cannot remove \"another-dir\": %m\n");
530 result = 1;
531 }
532
533 if (unlink ("and-a-file") < 0)
534 {
535 printf ("cannot remove \"and-a-file\": %m\n");
536 result = 1;
537 }
538
539 /* One more test before we leave: mkdir() is supposed to fail with
540 EEXIST if the named file is a symlink. */
541 if (symlink ("a-symlink", "a-symlink") != 0)
542 {
543 printf ("cannot create symlink \"a-symlink\": %m\n");
544 result = 1;
545 }
546 else
547 {
548 if (mkdir ("a-symlink", 0666) == 0)
549 {
550 puts ("can make directory \"a-symlink\"");
551 result = 1;
552 }
553 else if (errno != EEXIST)
554 {
555 puts ("mkdir(\"a-symlink\") does not fail with EEXIST\n");
556 result = 1;
557 }
558 if (unlink ("a-symlink") < 0)
559 {
560 printf ("cannot unlink \"a-symlink\": %m\n");
561 result = 1;
562 }
563 }
564
565 if (chdir (srcdir) < 0)
566 {
567 printf ("cannot change back to source directory: %m\n");
568 exit (1);
569 }
570
571 if (rmdir (buf) < 0)
572 {
573 printf ("cannot remove \"%s\": %m\n", buf);
574 result = 1;
575 }
576 free (objdir_copy1);
577 free (objdir_copy2);
578
579 if (result == 0)
580 puts ("all OK");
581
582 return result;
583}
Note: See TracBrowser for help on using the repository browser.