2 # Check for several getcwd bugs with long file names.
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-2007, 2009-2011 Free Software Foundation, Inc.
10 # This file is free software; the Free Software Foundation
11 # gives unlimited permission to copy and/or distribute it,
12 # with or without modifications, as long as this notice is preserved.
16 AC_DEFUN([gl_FUNC_GETCWD_PATH_MAX],
18 AC_CHECK_DECLS_ONCE([getcwd])
19 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
20 AC_CHECK_HEADERS_ONCE([unistd.h])
21 AC_REQUIRE([gl_PATHMAX_SNIPPET_PREREQ])
22 AC_CACHE_CHECK([whether getcwd handles long file names properly],
23 gl_cv_func_getcwd_path_max,
24 [# Arrange for deletion of the temporary directory this test creates.
25 ac_clean_files="$ac_clean_files confdir3"
26 dnl Please keep this in sync with tests/test-getcwd.c.
40 #include <sys/types.h>
49 # define is_ENAMETOOLONG(x) ((x) == ENAMETOOLONG)
51 # define is_ENAMETOOLONG(x) 0
54 /* Don't get link errors because mkdir is redefined to rpl_mkdir. */
61 /* The length of this name must be 8. */
62 #define DIR_NAME "confdir3"
63 #define DIR_NAME_LEN 8
64 #define DIR_NAME_SIZE (DIR_NAME_LEN + 1)
66 /* The length of "../". */
67 #define DOTDOTSLASH_LEN 3
69 /* Leftover bytes in the buffer, to work around library or OS bugs. */
76 /* The Hurd doesn't define this, so getcwd can't exhibit the bug --
77 at least not on a local file system. And if we were to start worrying
78 about remote file systems, we'd have to enable the wrapper function
79 all of the time, just to be safe. That's not worth the cost. */
81 #elif ((INT_MAX / (DIR_NAME_SIZE / DOTDOTSLASH_LEN + 1) \
82 - DIR_NAME_SIZE - BUF_SLOP) \
84 /* FIXME: Assuming there's a system for which this is true,
85 this should be done in a compile test. */
88 char buf[PATH_MAX * (DIR_NAME_SIZE / DOTDOTSLASH_LEN + 1)
89 + DIR_NAME_SIZE + BUF_SLOP];
90 char *cwd = getcwd (buf, PATH_MAX);
91 size_t initial_cwd_len;
99 cwd_len = initial_cwd_len = strlen (cwd);
103 size_t dotdot_max = PATH_MAX * (DIR_NAME_SIZE / DOTDOTSLASH_LEN);
106 cwd_len += DIR_NAME_SIZE;
107 /* If mkdir or chdir fails, it could be that this system cannot create
108 any file with an absolute name longer than PATH_MAX, such as cygwin.
109 If so, leave fail as 0, because the current working directory can't
110 be too long for getcwd if it can't even be created. For other
111 errors, be pessimistic and consider that as a failure, too. */
112 if (mkdir (DIR_NAME, S_IRWXU) < 0 || chdir (DIR_NAME) < 0)
114 if (! (errno == ERANGE || is_ENAMETOOLONG (errno)))
119 if (PATH_MAX <= cwd_len && cwd_len < PATH_MAX + DIR_NAME_SIZE)
121 c = getcwd (buf, PATH_MAX);
122 if (!c && errno == ENOENT)
127 if (c || ! (errno == ERANGE || is_ENAMETOOLONG (errno)))
134 if (dotdot_max <= cwd_len - initial_cwd_len)
136 if (dotdot_max + DIR_NAME_SIZE < cwd_len - initial_cwd_len)
138 c = getcwd (buf, cwd_len + 1);
141 if (! (errno == ERANGE || errno == ENOENT
142 || is_ENAMETOOLONG (errno)))
147 if (AT_FDCWD || errno == ERANGE || errno == ENOENT)
155 if (c && strlen (c) != cwd_len)
163 /* Leaving behind such a deep directory is not polite.
164 So clean up here, right away, even though the driving
165 shell script would also clean up. */
169 /* Try rmdir first, in case the chdir failed. */
171 for (i = 0; i <= n_chdirs; i++)
173 if (chdir ("..") < 0)
175 if (rmdir (DIR_NAME) != 0)
184 [gl_cv_func_getcwd_path_max=yes],
186 10|11|12) 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.]);;