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
52 # define __strdup strdup
54 # define __faccessat faccessat
55 # if defined _WIN32 && !defined __CYGWIN__
56 # define __getcwd _getcwd
59 /* When building the relocatable program wrapper, use the system's getcwd
60 function, not the gnulib override, otherwise we would get a link error.
64 # if defined VMS && !defined getcwd
65 /* We want the directory in Unix syntax, not in VMS syntax.
66 The gnulib override of 'getcwd' takes 2 arguments; the original VMS
67 'getcwd' takes 3 arguments. */
68 # define __getcwd(buf, max) getcwd (buf, max, 0)
70 # define __getcwd getcwd
73 # define __getcwd(buf, max) getwd (buf)
75 # define __mempcpy mempcpy
76 # define __pathconf pathconf
77 # define __rawmemchr rawmemchr
78 # define __readlink readlink
82 /* Suppress bogus GCC -Wmaybe-uninitialized warnings. */
83 #if defined GCC_LINT || defined lint
84 # define IF_LINT(Code) Code
86 # define IF_LINT(Code) /* empty */
89 #ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
90 # define DOUBLE_SLASH_IS_DISTINCT_ROOT false
93 #if defined _LIBC || !FUNC_REALPATH_WORKS
95 /* Return true if FILE's existence can be shown, false (setting errno)
96 otherwise. Follow symbolic links. */
98 file_accessible (char const *file
)
100 # if defined _LIBC || HAVE_FACCESSAT
101 return __faccessat (AT_FDCWD
, file
, F_OK
, AT_EACCESS
) == 0;
104 return __stat (file
, &st
) == 0 || errno
== EOVERFLOW
;
108 /* True if concatenating END as a suffix to a file name means that the
109 code needs to check that the file name is that of a searchable
110 directory, since the canonicalize_filename_mode_stk code won't
111 check this later anyway when it checks an ordinary file name
112 component within END. END must either be empty, or start with a
115 static bool _GL_ATTRIBUTE_PURE
116 suffix_requires_dir_check (char const *end
)
118 /* If END does not start with a slash, the suffix is OK. */
119 while (ISSLASH (*end
))
121 /* Two or more slashes act like a single slash. */
124 while (ISSLASH (*end
));
128 default: return false; /* An ordinary file name component is OK. */
129 case '\0': return true; /* Trailing "/" is trouble. */
130 case '.': break; /* Possibly "." or "..". */
132 /* Trailing "/.", or "/.." even if not trailing, is trouble. */
133 if (!*end
|| (*end
== '.' && (!end
[1] || ISSLASH (end
[1]))))
140 /* Append this to a file name to test whether it is a searchable directory.
141 On POSIX platforms "/" suffices, but "/./" is sometimes needed on
142 macOS 10.13 <https://bugs.gnu.org/30350>, and should also work on
143 platforms like AIX 7.2 that need at least "/.". */
145 #if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK
146 static char const dir_suffix
[] = "/";
148 static char const dir_suffix
[] = "/./";
151 /* Return true if DIR is a searchable dir, false (setting errno) otherwise.
152 DIREND points to the NUL byte at the end of the DIR string.
153 Store garbage into DIREND[0 .. strlen (dir_suffix)]. */
156 dir_check (char *dir
, char *dirend
)
158 strcpy (dirend
, dir_suffix
);
159 return file_accessible (dir
);
166 long int path_max
= PATH_MAX
;
168 /* The caller invoked realpath with a null RESOLVED, even though
169 PATH_MAX is not defined as a constant. The glibc manual says
170 programs should not do this, and POSIX says the behavior is undefined.
171 Historically, glibc here used the result of pathconf, or 1024 if that
172 failed; stay consistent with this (dubious) historical practice. */
174 long int path_max
= __pathconf ("/", _PC_PATH_MAX
);
177 return path_max
< 0 ? 1024 : path_max
<= IDX_MAX
? path_max
: IDX_MAX
;
180 /* Scratch buffers used by realpath_stk and managed by __realpath. */
183 struct scratch_buffer rname
;
184 struct scratch_buffer extra
;
185 struct scratch_buffer link
;
189 realpath_stk (const char *name
, char *resolved
, struct realpath_bufs
*bufs
)
198 /* As per Single Unix Specification V2 we must return an error if
199 either parameter is a null pointer. We extend this to allow
200 the RESOLVED parameter to be NULL in case the we are expected to
201 allocate the room for the return value. */
202 __set_errno (EINVAL
);
208 /* As per Single Unix Specification V2 we must return an error if
209 the name argument points to an empty string. */
210 __set_errno (ENOENT
);
214 char *rname
= bufs
->rname
.data
;
215 bool end_in_extra_buffer
= false;
218 /* This is always zero for Posix hosts, but can be 2 for MS-Windows
219 and MS-DOS X:/foo/bar file names. */
220 idx_t prefix_len
= FILE_SYSTEM_PREFIX_LEN (name
);
222 if (!IS_ABSOLUTE_FILE_NAME (name
))
224 while (!__getcwd (bufs
->rname
.data
, bufs
->rname
.length
))
231 if (!scratch_buffer_grow (&bufs
->rname
))
233 rname
= bufs
->rname
.data
;
235 dest
= __rawmemchr (rname
, '\0');
237 prefix_len
= FILE_SYSTEM_PREFIX_LEN (rname
);
241 dest
= __mempcpy (rname
, name
, prefix_len
);
243 if (DOUBLE_SLASH_IS_DISTINCT_ROOT
)
245 if (prefix_len
== 0 /* implies ISSLASH (name[0]) */
246 && ISSLASH (name
[1]) && !ISSLASH (name
[2]))
250 start
= name
+ prefix_len
;
253 for ( ; *start
; start
= end
)
255 /* Skip sequence of multiple file name separators. */
256 while (ISSLASH (*start
))
259 /* Find end of component. */
260 for (end
= start
; *end
&& !ISSLASH (*end
); ++end
)
263 /* Length of this file name component; it can be zero if a file
265 idx_t startlen
= end
- start
;
269 else if (startlen
== 1 && start
[0] == '.')
271 else if (startlen
== 2 && start
[0] == '.' && start
[1] == '.')
273 /* Back up to previous component, ignore if at root already. */
274 if (dest
> rname
+ prefix_len
+ 1)
275 for (--dest
; dest
> rname
&& !ISSLASH (dest
[-1]); --dest
)
277 if (DOUBLE_SLASH_IS_DISTINCT_ROOT
278 && dest
== rname
+ 1 && !prefix_len
279 && ISSLASH (*dest
) && !ISSLASH (dest
[1]))
284 if (!ISSLASH (dest
[-1]))
287 while (rname
+ bufs
->rname
.length
- dest
288 < startlen
+ sizeof dir_suffix
)
290 idx_t dest_offset
= dest
- rname
;
291 if (!scratch_buffer_grow_preserve (&bufs
->rname
))
293 rname
= bufs
->rname
.data
;
294 dest
= rname
+ dest_offset
;
297 dest
= __mempcpy (dest
, start
, startlen
);
304 buf
= bufs
->link
.data
;
305 idx_t bufsize
= bufs
->link
.length
;
306 n
= __readlink (rname
, buf
, bufsize
- 1);
309 if (!scratch_buffer_grow (&bufs
->link
))
314 if (++num_links
> __eloop_threshold ())
322 char *extra_buf
= bufs
->extra
.data
;
323 idx_t end_idx
IF_LINT (= 0);
324 if (end_in_extra_buffer
)
325 end_idx
= end
- extra_buf
;
326 size_t len
= strlen (end
);
327 if (INT_ADD_OVERFLOW (len
, n
))
329 __set_errno (ENOMEM
);
332 while (bufs
->extra
.length
<= len
+ n
)
334 if (!scratch_buffer_grow_preserve (&bufs
->extra
))
336 extra_buf
= bufs
->extra
.data
;
338 if (end_in_extra_buffer
)
339 end
= extra_buf
+ end_idx
;
341 /* Careful here, end may be a pointer into extra_buf... */
342 memmove (&extra_buf
[n
], end
, len
+ 1);
343 name
= end
= memcpy (extra_buf
, buf
, n
);
344 end_in_extra_buffer
= true;
346 if (IS_ABSOLUTE_FILE_NAME (buf
))
348 idx_t pfxlen
= FILE_SYSTEM_PREFIX_LEN (buf
);
350 dest
= __mempcpy (rname
, buf
, pfxlen
);
351 *dest
++ = '/'; /* It's an absolute symlink */
352 if (DOUBLE_SLASH_IS_DISTINCT_ROOT
)
354 if (ISSLASH (buf
[1]) && !ISSLASH (buf
[2]) && !pfxlen
)
358 /* Install the new prefix to be in effect hereafter. */
363 /* Back up to previous component, ignore if at root
365 if (dest
> rname
+ prefix_len
+ 1)
366 for (--dest
; dest
> rname
&& !ISSLASH (dest
[-1]); --dest
)
368 if (DOUBLE_SLASH_IS_DISTINCT_ROOT
&& dest
== rname
+ 1
369 && ISSLASH (*dest
) && !ISSLASH (dest
[1]) && !prefix_len
)
373 else if (! (suffix_requires_dir_check (end
)
374 ? dir_check (rname
, dest
)
379 if (dest
> rname
+ prefix_len
+ 1 && ISSLASH (dest
[-1]))
381 if (DOUBLE_SLASH_IS_DISTINCT_ROOT
&& dest
== rname
+ 1 && !prefix_len
382 && ISSLASH (*dest
) && !ISSLASH (dest
[1]))
388 if (resolved
!= NULL
)
390 /* Copy the full result on success or partial result if failure was due
391 to the path not existing or not being accessible. */
392 if ((!failed
|| errno
== ENOENT
|| errno
== EACCES
)
393 && dest
- rname
<= get_path_max ())
395 strcpy (resolved
, rname
);
402 __set_errno (ENAMETOOLONG
);
410 return __strdup (bufs
->rname
.data
);
414 /* Return the canonical absolute name of file NAME. A canonical name
415 does not contain any ".", ".." components nor any repeated file name
416 separators ('/') or symlinks. All file name components must exist. If
417 RESOLVED is null, the result is malloc'd; otherwise, if the
418 canonical name is PATH_MAX chars or more, returns null with 'errno'
419 set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
420 returns the name in RESOLVED. If the name cannot be resolved and
421 RESOLVED is non-NULL, it contains the name of the first component
422 that cannot be resolved. If the name can be resolved, RESOLVED
423 holds the same value as the value returned. */
426 __realpath (const char *name
, char *resolved
)
428 struct realpath_bufs bufs
;
429 scratch_buffer_init (&bufs
.rname
);
430 scratch_buffer_init (&bufs
.extra
);
431 scratch_buffer_init (&bufs
.link
);
432 char *result
= realpath_stk (name
, resolved
, &bufs
);
433 scratch_buffer_free (&bufs
.link
);
434 scratch_buffer_free (&bufs
.extra
);
435 scratch_buffer_free (&bufs
.rname
);
438 libc_hidden_def (__realpath
)
439 versioned_symbol (libc
, __realpath
, realpath
, GLIBC_2_3
);
440 #endif /* !FUNC_REALPATH_WORKS || defined _LIBC */
443 #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
445 attribute_compat_text_section
446 __old_realpath (const char *name
, char *resolved
)
448 if (resolved
== NULL
)
450 __set_errno (EINVAL
);
454 return __realpath (name
, resolved
);
456 compat_symbol (libc
, __old_realpath
, realpath
, GLIBC_2_0
);
461 __canonicalize_file_name (const char *name
)
463 return __realpath (name
, NULL
);
465 weak_alias (__canonicalize_file_name
, canonicalize_file_name
)