canonicalize-lgpl.c 15 KB

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