Merge from coreutils.
[gnulib.git] / m4 / readdir.m4
1 #serial 7
2
3 dnl SunOS's readdir is broken in such a way that rm.c has to add extra code
4 dnl to test whether a NULL return value really means there are no more files
5 dnl in the directory.
6 dnl
7 dnl And the rm from coreutils-5.0 exposes a similar problem when there
8 dnl are 338 or more files in a directory on a Darwin-6.5 system
9 dnl
10 dnl Detect the problem by creating a directory containing 500 files (254 not
11 dnl counting . and .. is the minimum for SunOS, 338 for Darwin) and see
12 dnl if a loop doing `readdir; unlink' removes all of them.
13 dnl
14 dnl Define HAVE_WORKING_READDIR if readdir does *not* have this problem.
15
16 dnl Written by Jim Meyering.
17
18 AC_DEFUN([GL_FUNC_READDIR],
19 [dnl
20 AC_REQUIRE([AC_HEADER_DIRENT])
21 AC_CACHE_CHECK([for working readdir], gl_cv_func_working_readdir,
22   [dnl
23   # Arrange for deletion of the temporary directory this test creates, in
24   # case the test itself fails to delete everything -- as happens on Sunos.
25   ac_clean_files="$ac_clean_files conf-dir"
26
27   AC_TRY_RUN(
28 [#   include <stdio.h>
29 #   include <sys/types.h>
30 #   include <string.h>
31
32 #   ifdef HAVE_DIRENT_H
33 #    include <dirent.h>
34 #    define NLENGTH(direct) (strlen((direct)->d_name))
35 #   else /* not HAVE_DIRENT_H */
36 #    define dirent direct
37 #    define NLENGTH(direct) ((direct)->d_namlen)
38 #    ifdef HAVE_SYS_NDIR_H
39 #     include <sys/ndir.h>
40 #    endif /* HAVE_SYS_NDIR_H */
41 #    ifdef HAVE_SYS_DIR_H
42 #     include <sys/dir.h>
43 #    endif /* HAVE_SYS_DIR_H */
44 #    ifdef HAVE_NDIR_H
45 #     include <ndir.h>
46 #    endif /* HAVE_NDIR_H */
47 #   endif /* HAVE_DIRENT_H */
48
49 #   define DOT_OR_DOTDOT(Basename) \
50      (Basename[0] == '.' && (Basename[1] == '\0' \
51                              || (Basename[1] == '.' && Basename[2] == '\0')))
52
53 /* Don't try to use replacement mkdir; it wouldn't resolve at link time.  */
54 #   undef mkdir
55
56     static void
57     create_N_file_dir (const char *dir, size_t n_files)
58     {
59       unsigned int i;
60
61       if (mkdir (dir, 0700))
62         abort ();
63       if (chdir (dir))
64         abort ();
65
66       for (i = 0; i < n_files; i++)
67         {
68           char file_name[4];
69           FILE *out;
70
71           sprintf (file_name, "%03d", i);
72           out = fopen (file_name, "w");
73           if (!out)
74             abort ();
75           if (fclose (out) == EOF)
76             abort ();
77         }
78
79       if (chdir (".."))
80         abort ();
81     }
82
83     static void
84     remove_dir (const char *dir)
85     {
86       DIR *dirp;
87
88       if (chdir (dir))
89         abort ();
90
91       dirp = opendir (".");
92       if (dirp == NULL)
93         abort ();
94
95       while (1)
96         {
97           struct dirent *dp = readdir (dirp);
98           if (dp == NULL)
99             break;
100
101           if (DOT_OR_DOTDOT (dp->d_name))
102             continue;
103
104           if (unlink (dp->d_name))
105             abort ();
106         }
107       closedir (dirp);
108
109       if (chdir (".."))
110         abort ();
111
112       if (rmdir (dir))
113         exit (1);
114     }
115
116     int
117     main ()
118     {
119       const char *dir = "conf-dir";
120       create_N_file_dir (dir, 500);
121       remove_dir (dir);
122       exit (0);
123     }],
124   gl_cv_func_working_readdir=yes,
125   gl_cv_func_working_readdir=no,
126   gl_cv_func_working_readdir=no)])
127
128   if test $gl_cv_func_working_readdir = yes; then
129     AC_DEFINE(HAVE_WORKING_READDIR, 1,
130       [Define if readdir is found to work properly in some unusual cases. ])
131   fi
132 ])