.
[coreutils.git] / m4 / readdir.m4
blobd2b1a557e121dca3b90dbaf10d4bc5d2001ae518
1 #serial 1
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 Detect the problem by creating a directory containing 300 files (254 not
8 dnl counting . and .. is the minimum) and see if a loop doing `readdir; unlink'
9 dnl removes all of them.
10 dnl
11 dnl Define HAVE_WORKING_READDIR if readdir does *not* have this problem.
13 dnl Written by Jim Meyering.
15 AC_DEFUN(jm_FUNC_READDIR,
16 [dnl
17 AC_REQUIRE([AC_HEADER_DIRENT])
18 AC_CHECK_HEADERS(string.h)
19 AC_CACHE_CHECK([for working readdir], jm_cv_func_working_readdir,
20   [dnl
21   # Arrange for deletion of the temporary directory this test creates, in
22   # case the test itself fails to delete everything -- as happens on Sunos.
23   ac_clean_files="$ac_clean_files conf-dir"
25   AC_TRY_RUN(
26   changequote(<<, >>)dnl
27   <<
28 #   include <stdio.h>
29 #   include <sys/types.h>
30 #   if HAVE_STRING_H
31 #    include <string.h>
32 #   endif
34 #   ifdef HAVE_DIRENT_H
35 #    include <dirent.h>
36 #    define NLENGTH(direct) (strlen((direct)->d_name))
37 #   else /* not HAVE_DIRENT_H */
38 #    define dirent direct
39 #    define NLENGTH(direct) ((direct)->d_namlen)
40 #    ifdef HAVE_SYS_NDIR_H
41 #     include <sys/ndir.h>
42 #    endif /* HAVE_SYS_NDIR_H */
43 #    ifdef HAVE_SYS_DIR_H
44 #     include <sys/dir.h>
45 #    endif /* HAVE_SYS_DIR_H */
46 #    ifdef HAVE_NDIR_H
47 #     include <ndir.h>
48 #    endif /* HAVE_NDIR_H */
49 #   endif /* HAVE_DIRENT_H */
51 #   define DOT_OR_DOTDOT(Basename) \
52      (Basename[0] == '.' && (Basename[1] == '\0' \
53                              || (Basename[1] == '.' && Basename[2] == '\0')))
55     static void
56     create_300_file_dir (const char *dir)
57     {
58       int i;
60       if (mkdir (dir, 0700))
61         abort ();
62       if (chdir (dir))
63         abort ();
65       for (i = 0; i < 300; i++)
66         {
67           char file_name[4];
68           FILE *out;
70           sprintf (file_name, "%03d", i);
71           out = fopen (file_name, "w");
72           if (!out)
73             abort ();
74           if (fclose (out) == EOF)
75             abort ();
76         }
78       if (chdir (".."))
79         abort ();
80     }
82     static void
83     remove_dir (const char *dir)
84     {
85       DIR *dirp;
87       if (chdir (dir))
88         abort ();
90       dirp = opendir (".");
91       if (dirp == NULL)
92         abort ();
94       while (1)
95         {
96           struct dirent *dp = readdir (dirp);
97           if (dp == NULL)
98             break;
100           if (DOT_OR_DOTDOT (dp->d_name))
101             continue;
103           if (unlink (dp->d_name))
104             abort ();
105         }
106       closedir (dirp);
108       if (chdir (".."))
109         abort ();
111       if (rmdir (dir))
112         exit (1);
113     }
115     int
116     main ()
117     {
118       const char *dir = "conf-dir";
119       create_300_file_dir (dir);
120       remove_dir (dir);
121       exit (0);
122     }
123   >>,
124   changequote([, ])dnl
125   jm_cv_func_working_readdir=yes,
126   jm_cv_func_working_readdir=no,
127   jm_cv_func_working_readdir=no)])
129   if test x = y; then
130     dnl This code is deliberately never run via ./configure.
131     dnl FIXME: this is a gross hack to make autoheader put an entry
132     dnl for this HAVE_-prefixed symbol in config.h.in.
133     AC_CHECK_FUNCS(WORKING_READDIR)
134   fi
137   if test $jm_cv_func_working_readdir = yes; then
138     ac_kludge=HAVE_WORKING_READDIR
139     AC_DEFINE_UNQUOTED($ac_kludge)
140   fi