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. 4 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. 9 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. 14 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/>. */ 18 19 #ifndef _LIBC 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 24 # include <libc-config.h> 25 #endif 26 27 /* Specification. */ 28 #include <stdlib.h> 29 30 #include <errno.h> 31 #include <fcntl.h> 32 #include <limits.h> 33 #include <stdbool.h> 34 #include <string.h> 35 #include <sys/stat.h> 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> 43 44 #ifdef _LIBC 45 # include <shlib-compat.h> 46 # define GCC_LINT 1 47 # define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) 48 #else 49 # define __canonicalize_file_name canonicalize_file_name 50 # define __realpath realpath 51 # include "pathmax.h" 52 # define __faccessat faccessat 53 # if defined _WIN32 && !defined __CYGWIN__ 54 # define __getcwd _getcwd 55 # elif HAVE_GETCWD 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 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. */ 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 73 # define __mempcpy mempcpy 74 # define __pathconf pathconf 75 # define __rawmemchr rawmemchr 76 # define __readlink readlink 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 83 #endif 84 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 */ 90 #endif 91 92 #ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT 93 # define DOUBLE_SLASH_IS_DISTINCT_ROOT false 94 #endif 95 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. */ 100 static bool 101 file_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; 107 return stat (file, &st) == 0 || errno == EOVERFLOW; 108 # endif 109 } 110 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 118 static bool _GL_ATTRIBUTE_PURE 119 suffix_requires_dir_check (char const *end) 120 { 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 148 # if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK 149 static char const dir_suffix[] = "/"; 150 # else 151 static char const dir_suffix[] = "/./"; 152 # endif 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 158 static bool 159 dir_check (char *dir, char *dirend) 160 { 161 strcpy (dirend, dir_suffix); 162 return file_accessible (dir); 163 } 164 165 static idx_t 166 get_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 } 182 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. */ 194 # if __GNUC_PREREQ (10, 1) 195 # if defined GCC_LINT || defined lint 196 __attribute__ ((__noinline__)) 197 # elif __OPTIMIZE__ && !__NO_INLINE__ 198 # define GCC_BOGUS_WRETURN_LOCAL_ADDR 199 # endif 200 # endif 201 static char * 202 realpath_stk (const char *name, char *resolved, 203 struct scratch_buffer *rname_buf) 204 { 205 char *dest; 206 char const *start; 207 char const *end; 208 int num_links = 0; 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 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; 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. */ 239 idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name); 240 241 if (!IS_ABSOLUTE_FILE_NAME (name)) 242 { 243 while (!__getcwd (rname, rname_buf->length)) 244 { 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; 253 } 254 dest = __rawmemchr (rname, '\0'); 255 start = name; 256 prefix_len = FILE_SYSTEM_PREFIX_LEN (rname); 257 } 258 else 259 { 260 dest = __mempcpy (rname, name, prefix_len); 261 *dest++ = '/'; 262 if (DOUBLE_SLASH_IS_DISTINCT_ROOT) 263 { 264 if (prefix_len == 0 /* implies ISSLASH (name[0]) */ 265 && ISSLASH (name[1]) && !ISSLASH (name[2])) 266 *dest++ = '/'; 267 *dest = '\0'; 268 } 269 start = name + prefix_len; 270 } 271 272 for ( ; *start; start = end) 273 { 274 /* Skip sequence of multiple file name separators. */ 275 while (ISSLASH (*start)) 276 ++start; 277 278 /* Find end of component. */ 279 for (end = start; *end && !ISSLASH (*end); ++end) 280 /* Nothing. */; 281 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) 287 break; 288 else if (startlen == 1 && start[0] == '.') 289 /* nothing */; 290 else if (startlen == 2 && start[0] == '.' && start[1] == '.') 291 { 292 /* Back up to previous component, ignore if at root already. */ 293 if (dest > rname + prefix_len + 1) 294 for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest) 295 continue; 296 if (DOUBLE_SLASH_IS_DISTINCT_ROOT 297 && dest == rname + 1 && !prefix_len 298 && ISSLASH (*dest) && !ISSLASH (dest[1])) 299 dest++; 300 } 301 else 302 { 303 if (!ISSLASH (dest[-1])) 304 *dest++ = '/'; 305 306 while (rname + rname_buf->length - dest 307 < startlen + sizeof dir_suffix) 308 { 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; 314 } 315 316 dest = __mempcpy (dest, start, startlen); 317 *dest = '\0'; 318 319 char *buf; 320 ssize_t n; 321 while (true) 322 { 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 ()) 334 { 335 __set_errno (ELOOP); 336 goto error; 337 } 338 339 buf[n] = '\0'; 340 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)) 347 { 348 __set_errno (ENOMEM); 349 goto error_nomem; 350 } 351 while (extra_buffer.length <= len + n) 352 { 353 if (!scratch_buffer_grow_preserve (&extra_buffer)) 354 goto error_nomem; 355 extra_buf = extra_buffer.data; 356 } 357 if (end_in_extra_buffer) 358 end = extra_buf + end_idx; 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); 363 end_in_extra_buffer = true; 364 365 if (IS_ABSOLUTE_FILE_NAME (buf)) 366 { 367 idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf); 368 369 dest = __mempcpy (rname, buf, pfxlen); 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: */ 384 if (dest > rname + prefix_len + 1) 385 for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest) 386 continue; 387 if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 388 && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len) 389 dest++; 390 } 391 } 392 else if (! (suffix_requires_dir_check (end) 393 ? dir_check (rname, dest) 394 : errno == EINVAL)) 395 goto error; 396 } 397 } 398 if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1])) 399 --dest; 400 if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len 401 && ISSLASH (*dest) && !ISSLASH (dest[1])) 402 dest++; 403 failed = false; 404 405 error: 406 *dest++ = '\0'; 407 if (resolved != NULL && dest - rname <= get_path_max ()) 408 rname = strcpy (resolved, rname); 409 410 error_nomem: 411 scratch_buffer_free (&extra_buffer); 412 scratch_buffer_free (&link_buffer); 413 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); 421 } 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 434 char * 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 } 444 libc_hidden_def (__realpath) 445 versioned_symbol (libc, __realpath, realpath, GLIBC_2_3); 446 447 #endif /* defined _LIBC || !FUNC_REALPATH_WORKS */ 448 449 450 #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3) 451 char * 452 attribute_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 } 463 compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0); 464 #endif 465 466 467 char * 468 __canonicalize_file_name (const char *name) 469 { 470 return __realpath (name, NULL); 471 } 472 weak_alias (__canonicalize_file_name, canonicalize_file_name) 473