]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gnulib/import/canonicalize-lgpl.c
Update gnulib
[thirdparty/binutils-gdb.git] / gnulib / import / canonicalize-lgpl.c
CommitLineData
98399780 1/* Return the canonical absolute name of a given file.
dc6c21da 2 Copyright (C) 1996-2022 Free Software Foundation, Inc.
98399780
YQ
3 This file is part of the GNU C Library.
4
9c9d63b1 5 The GNU C Library is free software; you can redistribute it and/or
dc6c21da 6 modify it under the terms of the GNU Lesser General Public
9c9d63b1 7 License as published by the Free Software Foundation; either
dc6c21da 8 version 2.1 of the License, or (at your option) any later version.
98399780 9
9c9d63b1 10 The GNU C Library is distributed in the hope that it will be useful,
98399780 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
9c9d63b1 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
dc6c21da 13 Lesser General Public License for more details.
98399780 14
dc6c21da 15 You should have received a copy of the GNU Lesser General Public
9c9d63b1
PM
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
98399780
YQ
18
19#ifndef _LIBC
4a626d0a
PA
20/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
21 optimizes away the name == NULL test below. */
22# define _GL_ARG_NONNULL(params)
23
9c9d63b1 24# include <libc-config.h>
98399780
YQ
25#endif
26
98399780
YQ
27/* Specification. */
28#include <stdlib.h>
29
9c9d63b1
PM
30#include <errno.h>
31#include <fcntl.h>
98399780 32#include <limits.h>
9c9d63b1
PM
33#include <stdbool.h>
34#include <string.h>
98399780 35#include <sys/stat.h>
9c9d63b1
PM
36#include <unistd.h>
37
38#include <eloop-threshold.h>
39#include <filename.h>
40#include <idx.h>
41#include <intprops.h>
42#include <scratch_buffer.h>
98399780
YQ
43
44#ifdef _LIBC
45# include <shlib-compat.h>
9c9d63b1
PM
46# define GCC_LINT 1
47# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
98399780 48#else
98399780
YQ
49# define __canonicalize_file_name canonicalize_file_name
50# define __realpath realpath
51# include "pathmax.h"
9c9d63b1
PM
52# define __faccessat faccessat
53# if defined _WIN32 && !defined __CYGWIN__
54# define __getcwd _getcwd
55# elif HAVE_GETCWD
98399780
YQ
56# if IN_RELOCWRAPPER
57 /* When building the relocatable program wrapper, use the system's getcwd
58 function, not the gnulib override, otherwise we would get a link error.
59 */
60# undef getcwd
61# endif
c0c3707f
CB
62# if defined VMS && !defined getcwd
63 /* We want the directory in Unix syntax, not in VMS syntax.
64 The gnulib override of 'getcwd' takes 2 arguments; the original VMS
65 'getcwd' takes 3 arguments. */
98399780
YQ
66# define __getcwd(buf, max) getcwd (buf, max, 0)
67# else
68# define __getcwd getcwd
69# endif
70# else
71# define __getcwd(buf, max) getwd (buf)
72# endif
9c9d63b1
PM
73# define __mempcpy mempcpy
74# define __pathconf pathconf
75# define __rawmemchr rawmemchr
98399780 76# define __readlink readlink
dc6c21da
TT
77# if IN_RELOCWRAPPER
78 /* When building the relocatable program wrapper, use the system's memmove
79 function, not the gnulib override, otherwise we would get a link error.
80 */
81# undef memmove
82# endif
98399780
YQ
83#endif
84
9c9d63b1
PM
85/* Suppress bogus GCC -Wmaybe-uninitialized warnings. */
86#if defined GCC_LINT || defined lint
87# define IF_LINT(Code) Code
88#else
89# define IF_LINT(Code) /* empty */
98399780
YQ
90#endif
91
9c9d63b1
PM
92#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
93# define DOUBLE_SLASH_IS_DISTINCT_ROOT false
4c62b19f
PA
94#endif
95
9c9d63b1
PM
96#if defined _LIBC || !FUNC_REALPATH_WORKS
97
98/* Return true if FILE's existence can be shown, false (setting errno)
99 otherwise. Follow symbolic links. */
100static bool
101file_accessible (char const *file)
102{
103# if defined _LIBC || HAVE_FACCESSAT
104 return __faccessat (AT_FDCWD, file, F_OK, AT_EACCESS) == 0;
105# else
106 struct stat st;
dc6c21da 107 return stat (file, &st) == 0 || errno == EOVERFLOW;
9c9d63b1
PM
108# endif
109}
49e4877c 110
9c9d63b1
PM
111/* True if concatenating END as a suffix to a file name means that the
112 code needs to check that the file name is that of a searchable
113 directory, since the canonicalize_filename_mode_stk code won't
114 check this later anyway when it checks an ordinary file name
115 component within END. END must either be empty, or start with a
116 slash. */
117
118static bool _GL_ATTRIBUTE_PURE
119suffix_requires_dir_check (char const *end)
49e4877c 120{
9c9d63b1
PM
121 /* If END does not start with a slash, the suffix is OK. */
122 while (ISSLASH (*end))
123 {
124 /* Two or more slashes act like a single slash. */
125 do
126 end++;
127 while (ISSLASH (*end));
128
129 switch (*end++)
130 {
131 default: return false; /* An ordinary file name component is OK. */
132 case '\0': return true; /* Trailing "/" is trouble. */
133 case '.': break; /* Possibly "." or "..". */
134 }
135 /* Trailing "/.", or "/.." even if not trailing, is trouble. */
136 if (!*end || (*end == '.' && (!end[1] || ISSLASH (end[1]))))
137 return true;
138 }
139
140 return false;
141}
142
143/* Append this to a file name to test whether it is a searchable directory.
144 On POSIX platforms "/" suffices, but "/./" is sometimes needed on
145 macOS 10.13 <https://bugs.gnu.org/30350>, and should also work on
146 platforms like AIX 7.2 that need at least "/.". */
147
dc6c21da 148# if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK
9c9d63b1 149static char const dir_suffix[] = "/";
dc6c21da 150# else
9c9d63b1 151static char const dir_suffix[] = "/./";
dc6c21da 152# endif
9c9d63b1
PM
153
154/* Return true if DIR is a searchable dir, false (setting errno) otherwise.
155 DIREND points to the NUL byte at the end of the DIR string.
156 Store garbage into DIREND[0 .. strlen (dir_suffix)]. */
157
158static bool
159dir_check (char *dir, char *dirend)
160{
161 strcpy (dirend, dir_suffix);
162 return file_accessible (dir);
49e4877c
PA
163}
164
9c9d63b1
PM
165static idx_t
166get_path_max (void)
167{
168# ifdef PATH_MAX
169 long int path_max = PATH_MAX;
170# else
171 /* The caller invoked realpath with a null RESOLVED, even though
172 PATH_MAX is not defined as a constant. The glibc manual says
173 programs should not do this, and POSIX says the behavior is undefined.
174 Historically, glibc here used the result of pathconf, or 1024 if that
175 failed; stay consistent with this (dubious) historical practice. */
176 int err = errno;
177 long int path_max = __pathconf ("/", _PC_PATH_MAX);
178 __set_errno (err);
179# endif
180 return path_max < 0 ? 1024 : path_max <= IDX_MAX ? path_max : IDX_MAX;
181}
98399780 182
9c9d63b1
PM
183/* Act like __realpath (see below), with an additional argument
184 rname_buf that can be used as temporary storage.
185
186 If GCC_LINT is defined, do not inline this function with GCC 10.1
187 and later, to avoid creating a pointer to the stack that GCC
188 -Wreturn-local-addr incorrectly complains about. See:
189 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644
190 Although the noinline attribute can hurt performance a bit, no better way
191 to pacify GCC is known; even an explicit #pragma does not pacify GCC.
192 When the GCC bug is fixed this workaround should be limited to the
193 broken GCC versions. */
dc6c21da
TT
194# if __GNUC_PREREQ (10, 1)
195# if defined GCC_LINT || defined lint
9c9d63b1 196__attribute__ ((__noinline__))
dc6c21da
TT
197# elif __OPTIMIZE__ && !__NO_INLINE__
198# define GCC_BOGUS_WRETURN_LOCAL_ADDR
199# endif
9c9d63b1 200# endif
9c9d63b1
PM
201static char *
202realpath_stk (const char *name, char *resolved,
203 struct scratch_buffer *rname_buf)
98399780 204{
9c9d63b1
PM
205 char *dest;
206 char const *start;
207 char const *end;
98399780 208 int num_links = 0;
98399780
YQ
209
210 if (name == NULL)
211 {
212 /* As per Single Unix Specification V2 we must return an error if
213 either parameter is a null pointer. We extend this to allow
214 the RESOLVED parameter to be NULL in case the we are expected to
215 allocate the room for the return value. */
216 __set_errno (EINVAL);
217 return NULL;
218 }
219
220 if (name[0] == '\0')
221 {
222 /* As per Single Unix Specification V2 we must return an error if
223 the name argument points to an empty string. */
224 __set_errno (ENOENT);
225 return NULL;
226 }
227
9c9d63b1
PM
228 struct scratch_buffer extra_buffer, link_buffer;
229 scratch_buffer_init (&extra_buffer);
230 scratch_buffer_init (&link_buffer);
231 scratch_buffer_init (rname_buf);
232 char *rname_on_stack = rname_buf->data;
233 char *rname = rname_on_stack;
234 bool end_in_extra_buffer = false;
235 bool failed = true;
98399780
YQ
236
237 /* This is always zero for Posix hosts, but can be 2 for MS-Windows
238 and MS-DOS X:/foo/bar file names. */
9c9d63b1 239 idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
98399780
YQ
240
241 if (!IS_ABSOLUTE_FILE_NAME (name))
242 {
9c9d63b1 243 while (!__getcwd (rname, rname_buf->length))
98399780 244 {
9c9d63b1
PM
245 if (errno != ERANGE)
246 {
247 dest = rname;
248 goto error;
249 }
250 if (!scratch_buffer_grow (rname_buf))
251 goto error_nomem;
252 rname = rname_buf->data;
98399780 253 }
9c9d63b1 254 dest = __rawmemchr (rname, '\0');
98399780 255 start = name;
9c9d63b1 256 prefix_len = FILE_SYSTEM_PREFIX_LEN (rname);
98399780
YQ
257 }
258 else
259 {
9c9d63b1 260 dest = __mempcpy (rname, name, prefix_len);
98399780
YQ
261 *dest++ = '/';
262 if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
263 {
9c9d63b1
PM
264 if (prefix_len == 0 /* implies ISSLASH (name[0]) */
265 && ISSLASH (name[1]) && !ISSLASH (name[2]))
98399780
YQ
266 *dest++ = '/';
267 *dest = '\0';
268 }
269 start = name + prefix_len;
270 }
271
9c9d63b1 272 for ( ; *start; start = end)
98399780 273 {
9c9d63b1 274 /* Skip sequence of multiple file name separators. */
98399780
YQ
275 while (ISSLASH (*start))
276 ++start;
277
9c9d63b1 278 /* Find end of component. */
98399780
YQ
279 for (end = start; *end && !ISSLASH (*end); ++end)
280 /* Nothing. */;
281
9c9d63b1
PM
282 /* Length of this file name component; it can be zero if a file
283 name ends in '/'. */
284 idx_t startlen = end - start;
285
286 if (startlen == 0)
98399780 287 break;
9c9d63b1 288 else if (startlen == 1 && start[0] == '.')
98399780 289 /* nothing */;
9c9d63b1 290 else if (startlen == 2 && start[0] == '.' && start[1] == '.')
98399780
YQ
291 {
292 /* Back up to previous component, ignore if at root already. */
9c9d63b1
PM
293 if (dest > rname + prefix_len + 1)
294 for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
98399780
YQ
295 continue;
296 if (DOUBLE_SLASH_IS_DISTINCT_ROOT
9c9d63b1 297 && dest == rname + 1 && !prefix_len
98399780
YQ
298 && ISSLASH (*dest) && !ISSLASH (dest[1]))
299 dest++;
300 }
301 else
302 {
98399780
YQ
303 if (!ISSLASH (dest[-1]))
304 *dest++ = '/';
305
9c9d63b1
PM
306 while (rname + rname_buf->length - dest
307 < startlen + sizeof dir_suffix)
98399780 308 {
9c9d63b1
PM
309 idx_t dest_offset = dest - rname;
310 if (!scratch_buffer_grow_preserve (rname_buf))
311 goto error_nomem;
312 rname = rname_buf->data;
313 dest = rname + dest_offset;
98399780
YQ
314 }
315
9c9d63b1 316 dest = __mempcpy (dest, start, startlen);
98399780
YQ
317 *dest = '\0';
318
9c9d63b1
PM
319 char *buf;
320 ssize_t n;
321 while (true)
98399780 322 {
9c9d63b1
PM
323 buf = link_buffer.data;
324 idx_t bufsize = link_buffer.length;
325 n = __readlink (rname, buf, bufsize - 1);
326 if (n < bufsize - 1)
327 break;
328 if (!scratch_buffer_grow (&link_buffer))
329 goto error_nomem;
330 }
331 if (0 <= n)
332 {
333 if (++num_links > __eloop_threshold ())
98399780
YQ
334 {
335 __set_errno (ELOOP);
336 goto error;
337 }
338
98399780
YQ
339 buf[n] = '\0';
340
9c9d63b1
PM
341 char *extra_buf = extra_buffer.data;
342 idx_t end_idx IF_LINT (= 0);
343 if (end_in_extra_buffer)
344 end_idx = end - extra_buf;
345 size_t len = strlen (end);
346 if (INT_ADD_OVERFLOW (len, n))
98399780 347 {
9c9d63b1
PM
348 __set_errno (ENOMEM);
349 goto error_nomem;
98399780 350 }
9c9d63b1 351 while (extra_buffer.length <= len + n)
98399780 352 {
9c9d63b1
PM
353 if (!scratch_buffer_grow_preserve (&extra_buffer))
354 goto error_nomem;
355 extra_buf = extra_buffer.data;
98399780 356 }
9c9d63b1
PM
357 if (end_in_extra_buffer)
358 end = extra_buf + end_idx;
98399780
YQ
359
360 /* Careful here, end may be a pointer into extra_buf... */
361 memmove (&extra_buf[n], end, len + 1);
362 name = end = memcpy (extra_buf, buf, n);
9c9d63b1 363 end_in_extra_buffer = true;
98399780
YQ
364
365 if (IS_ABSOLUTE_FILE_NAME (buf))
366 {
9c9d63b1 367 idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
98399780 368
9c9d63b1 369 dest = __mempcpy (rname, buf, pfxlen);
98399780
YQ
370 *dest++ = '/'; /* It's an absolute symlink */
371 if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
372 {
373 if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
374 *dest++ = '/';
375 *dest = '\0';
376 }
377 /* Install the new prefix to be in effect hereafter. */
378 prefix_len = pfxlen;
379 }
380 else
381 {
382 /* Back up to previous component, ignore if at root
383 already: */
9c9d63b1
PM
384 if (dest > rname + prefix_len + 1)
385 for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
98399780 386 continue;
9c9d63b1 387 if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
98399780
YQ
388 && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
389 dest++;
390 }
391 }
9c9d63b1
PM
392 else if (! (suffix_requires_dir_check (end)
393 ? dir_check (rname, dest)
394 : errno == EINVAL))
395 goto error;
98399780
YQ
396 }
397 }
9c9d63b1 398 if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1]))
98399780 399 --dest;
9c9d63b1 400 if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len
98399780
YQ
401 && ISSLASH (*dest) && !ISSLASH (dest[1]))
402 dest++;
9c9d63b1 403 failed = false;
98399780 404
9c9d63b1
PM
405error:
406 *dest++ = '\0';
407 if (resolved != NULL && dest - rname <= get_path_max ())
408 rname = strcpy (resolved, rname);
98399780 409
9c9d63b1
PM
410error_nomem:
411 scratch_buffer_free (&extra_buffer);
412 scratch_buffer_free (&link_buffer);
98399780 413
9c9d63b1
PM
414 if (failed || rname == resolved)
415 {
416 scratch_buffer_free (rname_buf);
417 return failed ? NULL : resolved;
418 }
419
420 return scratch_buffer_dupfree (rname_buf, dest - rname);
98399780 421}
9c9d63b1
PM
422
423/* Return the canonical absolute name of file NAME. A canonical name
424 does not contain any ".", ".." components nor any repeated file name
425 separators ('/') or symlinks. All file name components must exist. If
426 RESOLVED is null, the result is malloc'd; otherwise, if the
427 canonical name is PATH_MAX chars or more, returns null with 'errno'
428 set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
429 returns the name in RESOLVED. If the name cannot be resolved and
430 RESOLVED is non-NULL, it contains the name of the first component
431 that cannot be resolved. If the name can be resolved, RESOLVED
432 holds the same value as the value returned. */
433
434char *
435__realpath (const char *name, char *resolved)
436{
437 #ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR
438 #warning "GCC might issue a bogus -Wreturn-local-addr warning here."
439 #warning "See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644>."
440 #endif
441 struct scratch_buffer rname_buffer;
442 return realpath_stk (name, resolved, &rname_buffer);
443}
444libc_hidden_def (__realpath)
98399780 445versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
dc6c21da
TT
446
447#endif /* defined _LIBC || !FUNC_REALPATH_WORKS */
98399780
YQ
448
449
450#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
451char *
452attribute_compat_text_section
453__old_realpath (const char *name, char *resolved)
454{
455 if (resolved == NULL)
456 {
457 __set_errno (EINVAL);
458 return NULL;
459 }
460
461 return __realpath (name, resolved);
462}
463compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
464#endif
465
466
467char *
468__canonicalize_file_name (const char *name)
469{
470 return __realpath (name, NULL);
471}
472weak_alias (__canonicalize_file_name, canonicalize_file_name)