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