gnulib: update to 776af40e0
[deliverable/binutils-gdb.git] / gnulib / import / m4 / getcwd-path-max.m4
CommitLineData
9c9d63b1 1# serial 25
6ec2e0f5
SDJ
2# Check for several getcwd bugs with long file names.
3# If so, arrange to compile the wrapper function.
4
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.
8
9c9d63b1 9# Copyright (C) 2003-2007, 2009-2021 Free Software Foundation, Inc.
6ec2e0f5
SDJ
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.
13
14# From Jim Meyering
15
16AC_DEFUN([gl_FUNC_GETCWD_PATH_MAX],
17[
18 AC_CHECK_DECLS_ONCE([getcwd])
19 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
20 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
21 AC_CHECK_HEADERS_ONCE([unistd.h])
22 AC_REQUIRE([gl_PATHMAX_SNIPPET_PREREQ])
23 AC_CACHE_CHECK([whether getcwd handles long file names properly],
c0c3707f 24 [gl_cv_func_getcwd_path_max],
6ec2e0f5
SDJ
25 [# Arrange for deletion of the temporary directory this test creates.
26 ac_clean_files="$ac_clean_files confdir3"
27 dnl Please keep this in sync with tests/test-getcwd.c.
28 AC_RUN_IFELSE(
29 [AC_LANG_SOURCE(
30 [[
31#include <errno.h>
32#include <stdlib.h>
33#if HAVE_UNISTD_H
34# include <unistd.h>
35#else
36# include <direct.h>
37#endif
38#include <string.h>
39#include <limits.h>
40#include <sys/stat.h>
41#include <sys/types.h>
42#include <fcntl.h>
43
44]gl_PATHMAX_SNIPPET[
45
46#ifndef AT_FDCWD
47# define AT_FDCWD 0
48#endif
49#ifdef ENAMETOOLONG
50# define is_ENAMETOOLONG(x) ((x) == ENAMETOOLONG)
51#else
52# define is_ENAMETOOLONG(x) 0
53#endif
54
55/* Use the getcwd function, not any macro. */
56#undef getcwd
57
9c9d63b1 58]GL_MDA_DEFINES[
6ec2e0f5
SDJ
59
60#ifndef S_IRWXU
61# define S_IRWXU 0700
62#endif
63
64/* The length of this name must be 8. */
65#define DIR_NAME "confdir3"
66#define DIR_NAME_LEN 8
67#define DIR_NAME_SIZE (DIR_NAME_LEN + 1)
68
69/* The length of "../". */
70#define DOTDOTSLASH_LEN 3
71
72/* Leftover bytes in the buffer, to work around library or OS bugs. */
73#define BUF_SLOP 20
74
75int
76main ()
77{
78#ifndef PATH_MAX
79 /* The Hurd doesn't define this, so getcwd can't exhibit the bug --
80 at least not on a local file system. And if we were to start worrying
81 about remote file systems, we'd have to enable the wrapper function
82 all of the time, just to be safe. That's not worth the cost. */
83 exit (0);
84#elif ((INT_MAX / (DIR_NAME_SIZE / DOTDOTSLASH_LEN + 1) \
85 - DIR_NAME_SIZE - BUF_SLOP) \
86 <= PATH_MAX)
87 /* FIXME: Assuming there's a system for which this is true,
88 this should be done in a compile test. */
89 exit (0);
90#else
91 char buf[PATH_MAX * (DIR_NAME_SIZE / DOTDOTSLASH_LEN + 1)
92 + DIR_NAME_SIZE + BUF_SLOP];
93 char *cwd = getcwd (buf, PATH_MAX);
94 size_t initial_cwd_len;
95 size_t cwd_len;
96 int fail = 0;
97 size_t n_chdirs = 0;
98
99 if (cwd == NULL)
100 exit (10);
101
102 cwd_len = initial_cwd_len = strlen (cwd);
103
104 while (1)
105 {
106 size_t dotdot_max = PATH_MAX * (DIR_NAME_SIZE / DOTDOTSLASH_LEN);
107 char *c = NULL;
108
109 cwd_len += DIR_NAME_SIZE;
110 /* If mkdir or chdir fails, it could be that this system cannot create
111 any file with an absolute name longer than PATH_MAX, such as cygwin.
112 If so, leave fail as 0, because the current working directory can't
c0c3707f
CB
113 be too long for getcwd if it can't even be created. On Linux with
114 the 9p file system, mkdir fails with error EINVAL when cwd_len gets
115 too long; ignore this failure because the getcwd() system call
116 produces good results whereas the gnulib substitute calls getdents64
117 which fails with error EPROTO.
118 For other errors, be pessimistic and consider that as a failure,
119 too. */
6ec2e0f5
SDJ
120 if (mkdir (DIR_NAME, S_IRWXU) < 0 || chdir (DIR_NAME) < 0)
121 {
122 if (! (errno == ERANGE || is_ENAMETOOLONG (errno)))
c0c3707f
CB
123 #ifdef __linux__
124 if (! (errno == EINVAL))
125 #endif
126 fail = 20;
6ec2e0f5
SDJ
127 break;
128 }
129
130 if (PATH_MAX <= cwd_len && cwd_len < PATH_MAX + DIR_NAME_SIZE)
131 {
132 struct stat sb;
133
134 c = getcwd (buf, PATH_MAX);
135 if (!c && errno == ENOENT)
136 {
137 fail = 11;
138 break;
139 }
140 if (c)
141 {
142 fail = 31;
143 break;
144 }
145 if (! (errno == ERANGE || is_ENAMETOOLONG (errno)))
146 {
147 fail = 21;
148 break;
149 }
150
151 /* Our replacement needs to be able to stat() long ../../paths,
152 so generate a path larger than PATH_MAX to check,
153 avoiding the replacement if we can't stat(). */
154 c = getcwd (buf, cwd_len + 1);
155 if (c && !AT_FDCWD && stat (c, &sb) != 0 && is_ENAMETOOLONG (errno))
156 {
157 fail = 32;
158 break;
159 }
160 }
161
162 if (dotdot_max <= cwd_len - initial_cwd_len)
163 {
164 if (dotdot_max + DIR_NAME_SIZE < cwd_len - initial_cwd_len)
165 break;
166 c = getcwd (buf, cwd_len + 1);
167 if (!c)
168 {
169 if (! (errno == ERANGE || errno == ENOENT
170 || is_ENAMETOOLONG (errno)))
171 {
172 fail = 22;
173 break;
174 }
175 if (AT_FDCWD || errno == ERANGE || errno == ENOENT)
176 {
177 fail = 12;
178 break;
179 }
180 }
181 }
182
183 if (c && strlen (c) != cwd_len)
184 {
185 fail = 23;
186 break;
187 }
188 ++n_chdirs;
189 }
190
191 /* Leaving behind such a deep directory is not polite.
192 So clean up here, right away, even though the driving
193 shell script would also clean up. */
194 {
195 size_t i;
196
197 /* Try rmdir first, in case the chdir failed. */
198 rmdir (DIR_NAME);
199 for (i = 0; i <= n_chdirs; i++)
200 {
201 if (chdir ("..") < 0)
202 break;
203 if (rmdir (DIR_NAME) != 0)
204 break;
205 }
206 }
207
208 exit (fail);
209#endif
210}
211 ]])],
c0c3707f
CB
212 [gl_cv_func_getcwd_path_max=yes],
213 [case $? in
214 10|11|12) gl_cv_func_getcwd_path_max='no, but it is partly working';;
215 31) gl_cv_func_getcwd_path_max='no, it has the AIX bug';;
216 32) gl_cv_func_getcwd_path_max='yes, but with shorter paths';;
217 *) gl_cv_func_getcwd_path_max=no;;
218 esac],
219 [# Cross-compilation guesses:
220 case "$host_os" in
221 aix*) # On AIX, it has the AIX bug.
222 gl_cv_func_getcwd_path_max='guessing no, it has the AIX bug' ;;
223 gnu*) # On Hurd, it is 'yes'.
224 gl_cv_func_getcwd_path_max='guessing yes' ;;
225 linux* | kfreebsd*)
226 # On older Linux+glibc it's 'no, but it is partly working',
227 # on newer Linux+glibc it's 'yes'.
228 # On Linux+musl libc, it's 'no, but it is partly working'.
229 # On kFreeBSD+glibc, it's 'no, but it is partly working'.
230 gl_cv_func_getcwd_path_max='guessing no, but it is partly working' ;;
231 *) # If we don't know, obey --enable-cross-guesses.
232 gl_cv_func_getcwd_path_max="$gl_cross_guess_normal" ;;
233 esac
234 ])
e2fc52e7 235 ])
6ec2e0f5 236])
This page took 0.263655 seconds and 4 git commands to generate.