2 # Check for several getcwd bugs with long paths.
3 # If so, arrange to compile the wrapper function.
5 # This is necessary for at least GNU libc on linux-2.4.19 and 2.4.20.
6 # I've heard that this is due to a Linux kernel bug, and that it has
7 # been fixed between 2.4.21-pre3 and 2.4.21-pre4. */
9 # Copyright (C) 2003, 2004 Free Software Foundation, Inc.
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 2, or (at your option)
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
21 # You should have received a copy of the GNU General Public License
22 # along with this program; if not, write to the Free Software Foundation,
23 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 AC_DEFUN([gl_FUNC_GETCWD_PATH_MAX],
29 AC_CHECK_DECLS_ONCE(getcwd)
30 AC_CHECK_HEADERS_ONCE(fcntl.h)
31 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
32 AC_CACHE_CHECK([whether getcwd handles long file names properly],
33 gl_cv_func_getcwd_path_max,
34 [# Arrange for deletion of the temporary directory this test creates.
35 ac_clean_files="$ac_clean_files confdir3"
45 #include <sys/types.h>
54 # define is_ENAMETOOLONG(x) ((x) == ENAMETOOLONG)
56 # define is_ENAMETOOLONG(x) 0
59 /* Don't get link errors because mkdir is redefined to rpl_mkdir. */
66 /* The length of this name must be 8. */
67 #define DIR_NAME "confdir3"
68 #define DIR_NAME_LEN 8
69 #define DIR_NAME_SIZE (DIR_NAME_LEN + 1)
71 /* The length of "../". */
72 #define DOTDOTSLASH_LEN 3
74 /* Leftover bytes in the buffer, to work around library or OS bugs. */
81 /* The Hurd doesn't define this, so getcwd can't exhibit the bug --
82 at least not on a local file system. And if we were to start worrying
83 about remote file systems, we'd have to enable the wrapper function
84 all of the time, just to be safe. That's not worth the cost. */
86 #elif ((INT_MAX / (DIR_NAME_SIZE / DOTDOTSLASH_LEN + 1) \
87 - DIR_NAME_SIZE - BUF_SLOP) \
89 /* FIXME: Assuming there's a system for which this is true,
90 this should be done in a compile test. */
93 char buf[PATH_MAX * (DIR_NAME_SIZE / DOTDOTSLASH_LEN + 1)
94 + DIR_NAME_SIZE + BUF_SLOP];
95 char *cwd = getcwd (buf, PATH_MAX);
96 size_t initial_cwd_len;
104 cwd_len = initial_cwd_len = strlen (cwd);
108 size_t dotdot_max = PATH_MAX * (DIR_NAME_SIZE / DOTDOTSLASH_LEN);
111 cwd_len += DIR_NAME_SIZE;
112 /* If mkdir or chdir fails, be pessimistic and consider that
113 as a failure, too. */
114 if (mkdir (DIR_NAME, S_IRWXU) < 0 || chdir (DIR_NAME) < 0)
120 if (PATH_MAX <= cwd_len && cwd_len < PATH_MAX + DIR_NAME_SIZE)
122 c = getcwd (buf, PATH_MAX);
123 if (!c && errno == ENOENT)
128 if (c || ! (errno == ERANGE || is_ENAMETOOLONG (errno)))
135 if (dotdot_max <= cwd_len - initial_cwd_len)
137 if (dotdot_max + DIR_NAME_SIZE < cwd_len - initial_cwd_len)
139 c = getcwd (buf, cwd_len + 1);
142 if (! (errno == ERANGE || errno == ENOENT
143 || is_ENAMETOOLONG (errno)))
148 if (AT_FDCWD || errno == ERANGE || errno == ENOENT)
156 if (c && strlen (c) != cwd_len)
164 /* Leaving behind such a deep directory is not polite.
165 So clean up here, right away, even though the driving
166 shell script would also clean up. */
170 /* Unlink first, in case the chdir failed. */
172 for (i = 0; i <= n_chdirs; i++)
174 if (chdir ("..") < 0)
184 [gl_cv_func_getcwd_path_max=yes],
186 1) gl_cv_func_getcwd_path_max='no, but it is partly working';;
187 *) gl_cv_func_getcwd_path_max=no;;
189 [gl_cv_func_getcwd_path_max=no])
191 case $gl_cv_func_getcwd_path_max in
193 AC_DEFINE([HAVE_PARTLY_WORKING_GETCWD], 1,
194 [Define to 1 if getcwd works, except it sometimes fails when it shouldn't,
195 setting errno to ERANGE, ENAMETOOLONG, or ENOENT. If __GETCWD_PREFIX
196 is not defined, it doesn't matter whether HAVE_PARTLY_WORKING_GETCWD