1 /* Return the canonical absolute name of a given file.
2 Copyright (C) 1996-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
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)
24 # define _GL_USE_STDLIB_ALLOC 1
25 # include <libc-config.h>
39 #include <eloop-threshold.h>
43 #include <scratch_buffer.h>
46 # include <shlib-compat.h>
48 # define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
50 # define __canonicalize_file_name canonicalize_file_name
51 # define __realpath realpath
53 # define __faccessat faccessat
54 # if defined _WIN32 && !defined __CYGWIN__
55 # define __getcwd _getcwd
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.
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. */
67 # define __getcwd(buf, max) getcwd (buf, max, 0)
69 # define __getcwd getcwd
72 # define __getcwd(buf, max) getwd (buf)
74 # define __mempcpy mempcpy
75 # define __pathconf pathconf
76 # define __rawmemchr rawmemchr
77 # define __readlink readlink
81 /* Suppress bogus GCC -Wmaybe-uninitialized warnings. */
82 #if defined GCC_LINT || defined lint
83 # define IF_LINT(Code) Code
85 # define IF_LINT(Code) /* empty */
88 #ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
89 # define DOUBLE_SLASH_IS_DISTINCT_ROOT false
92 #if defined _LIBC || !FUNC_REALPATH_WORKS
94 /* Return true if FILE's existence can be shown, false (setting errno)
95 otherwise. Follow symbolic links. */
97 file_accessible (char const *file
)
99 # if defined _LIBC || HAVE_FACCESSAT
100 return __faccessat (AT_FDCWD
, file
, F_OK
, AT_EACCESS
) == 0;
103 return __stat (file
, &st
) == 0 || errno
== EOVERFLOW
;
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
114 static bool _GL_ATTRIBUTE_PURE
115 suffix_requires_dir_check (char const *end
)
117 /* If END does not start with a slash, the suffix is OK. */
118 while (ISSLASH (*end
))
120 /* Two or more slashes act like a single slash. */
123 while (ISSLASH (*end
));
127 default: return false; /* An ordinary file name component is OK. */
128 case '\0': return true; /* Trailing "/" is trouble. */
129 case '.': break; /* Possibly "." or "..". */
131 /* Trailing "/.", or "/.." even if not trailing, is trouble. */
132 if (!*end
|| (*end
== '.' && (!end
[1] || ISSLASH (end
[1]))))
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 "/.". */
144 #if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK
145 static char const dir_suffix
[] = "/";
147 static char const dir_suffix
[] = "/./";
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)]. */
155 dir_check (char *dir
, char *dirend
)
157 strcpy (dirend
, dir_suffix
);
158 return file_accessible (dir
);
165 long int path_max
= PATH_MAX
;
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. */
173 long int path_max
= __pathconf ("/", _PC_PATH_MAX
);
176 return path_max
< 0 ? 1024 : path_max
<= IDX_MAX
? path_max
: IDX_MAX
;
179 /* Act like __realpath (see below), with an additional argument
180 rname_buf that can be used as temporary storage.
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
198 realpath_stk (const char *name
, char *resolved
,
199 struct scratch_buffer
*rname_buf
)
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
);
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
);
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;
233 /* This is always zero for Posix hosts, but can be 2 for MS-Windows
234 and MS-DOS X:/foo/bar file names. */
235 idx_t prefix_len
= FILE_SYSTEM_PREFIX_LEN (name
);
237 if (!IS_ABSOLUTE_FILE_NAME (name
))
239 while (!__getcwd (rname
, rname_buf
->length
))
246 if (!scratch_buffer_grow (rname_buf
))
248 rname
= rname_buf
->data
;
250 dest
= __rawmemchr (rname
, '\0');
252 prefix_len
= FILE_SYSTEM_PREFIX_LEN (rname
);
256 dest
= __mempcpy (rname
, name
, prefix_len
);
258 if (DOUBLE_SLASH_IS_DISTINCT_ROOT
)
260 if (prefix_len
== 0 /* implies ISSLASH (name[0]) */
261 && ISSLASH (name
[1]) && !ISSLASH (name
[2]))
265 start
= name
+ prefix_len
;
268 for ( ; *start
; start
= end
)
270 /* Skip sequence of multiple file name separators. */
271 while (ISSLASH (*start
))
274 /* Find end of component. */
275 for (end
= start
; *end
&& !ISSLASH (*end
); ++end
)
278 /* Length of this file name component; it can be zero if a file
280 idx_t startlen
= end
- start
;
284 else if (startlen
== 1 && start
[0] == '.')
286 else if (startlen
== 2 && start
[0] == '.' && start
[1] == '.')
288 /* Back up to previous component, ignore if at root already. */
289 if (dest
> rname
+ prefix_len
+ 1)
290 for (--dest
; dest
> rname
&& !ISSLASH (dest
[-1]); --dest
)
292 if (DOUBLE_SLASH_IS_DISTINCT_ROOT
293 && dest
== rname
+ 1 && !prefix_len
294 && ISSLASH (*dest
) && !ISSLASH (dest
[1]))
299 if (!ISSLASH (dest
[-1]))
302 while (rname
+ rname_buf
->length
- dest
303 < startlen
+ sizeof dir_suffix
)
305 idx_t dest_offset
= dest
- rname
;
306 if (!scratch_buffer_grow_preserve (rname_buf
))
308 rname
= rname_buf
->data
;
309 dest
= rname
+ dest_offset
;
312 dest
= __mempcpy (dest
, start
, startlen
);
319 buf
= link_buffer
.data
;
320 idx_t bufsize
= link_buffer
.length
;
321 n
= __readlink (rname
, buf
, bufsize
- 1);
324 if (!scratch_buffer_grow (&link_buffer
))
329 if (++num_links
> __eloop_threshold ())
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
))
344 __set_errno (ENOMEM
);
347 while (extra_buffer
.length
<= len
+ n
)
349 if (!scratch_buffer_grow_preserve (&extra_buffer
))
351 extra_buf
= extra_buffer
.data
;
353 if (end_in_extra_buffer
)
354 end
= extra_buf
+ end_idx
;
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
);
359 end_in_extra_buffer
= true;
361 if (IS_ABSOLUTE_FILE_NAME (buf
))
363 idx_t pfxlen
= FILE_SYSTEM_PREFIX_LEN (buf
);
365 dest
= __mempcpy (rname
, buf
, pfxlen
);
366 *dest
++ = '/'; /* It's an absolute symlink */
367 if (DOUBLE_SLASH_IS_DISTINCT_ROOT
)
369 if (ISSLASH (buf
[1]) && !ISSLASH (buf
[2]) && !pfxlen
)
373 /* Install the new prefix to be in effect hereafter. */
378 /* Back up to previous component, ignore if at root
380 if (dest
> rname
+ prefix_len
+ 1)
381 for (--dest
; dest
> rname
&& !ISSLASH (dest
[-1]); --dest
)
383 if (DOUBLE_SLASH_IS_DISTINCT_ROOT
&& dest
== rname
+ 1
384 && ISSLASH (*dest
) && !ISSLASH (dest
[1]) && !prefix_len
)
388 else if (! (suffix_requires_dir_check (end
)
389 ? dir_check (rname
, dest
)
394 if (dest
> rname
+ prefix_len
+ 1 && ISSLASH (dest
[-1]))
396 if (DOUBLE_SLASH_IS_DISTINCT_ROOT
&& dest
== rname
+ 1 && !prefix_len
397 && ISSLASH (*dest
) && !ISSLASH (dest
[1]))
403 if (resolved
!= NULL
)
405 /* Copy the full result on success or partial result if failure was due
406 to the path not existing or not being accessible. */
407 if ((!failed
|| errno
== ENOENT
|| errno
== EACCES
)
408 && dest
- rname
<= get_path_max ())
409 rname
= strcpy (resolved
, rname
);
413 __set_errno (ENAMETOOLONG
);
418 scratch_buffer_free (&extra_buffer
);
419 scratch_buffer_free (&link_buffer
);
421 if (failed
|| rname
== resolved
)
423 scratch_buffer_free (rname_buf
);
424 return failed
? NULL
: resolved
;
427 return scratch_buffer_dupfree (rname_buf
, dest
- rname
);
430 /* Return the canonical absolute name of file NAME. A canonical name
431 does not contain any ".", ".." components nor any repeated file name
432 separators ('/') or symlinks. All file name components must exist. If
433 RESOLVED is null, the result is malloc'd; otherwise, if the
434 canonical name is PATH_MAX chars or more, returns null with 'errno'
435 set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
436 returns the name in RESOLVED. If the name cannot be resolved and
437 RESOLVED is non-NULL, it contains the name of the first component
438 that cannot be resolved. If the name can be resolved, RESOLVED
439 holds the same value as the value returned. */
442 __realpath (const char *name
, char *resolved
)
444 #ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR
445 #warning "GCC might issue a bogus -Wreturn-local-addr warning here."
446 #warning "See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644>."
448 struct scratch_buffer rname_buffer
;
449 return realpath_stk (name
, resolved
, &rname_buffer
);
451 libc_hidden_def (__realpath
)
452 versioned_symbol (libc
, __realpath
, realpath
, GLIBC_2_3
);
453 #endif /* !FUNC_REALPATH_WORKS || defined _LIBC */
456 #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
458 attribute_compat_text_section
459 __old_realpath (const char *name
, char *resolved
)
461 if (resolved
== NULL
)
463 __set_errno (EINVAL
);
467 return __realpath (name
, resolved
);
469 compat_symbol (libc
, __old_realpath
, realpath
, GLIBC_2_0
);
474 __canonicalize_file_name (const char *name
)
476 return __realpath (name
, NULL
);
478 weak_alias (__canonicalize_file_name
, canonicalize_file_name
)