canonicalize-lgpl.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /* Return the canonical absolute name of a given file.
  2. Copyright (C) 1996-2013 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program 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
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. #ifndef _LIBC
  15. /* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
  16. optimizes away the name == NULL test below. */
  17. # define _GL_ARG_NONNULL(params)
  18. # define _GL_USE_STDLIB_ALLOC 1
  19. # include <config.h>
  20. #endif
  21. #if !HAVE_CANONICALIZE_FILE_NAME || !FUNC_REALPATH_WORKS || defined _LIBC
  22. /* Specification. */
  23. #include <stdlib.h>
  24. #include <alloca.h>
  25. #include <string.h>
  26. #include <unistd.h>
  27. #include <limits.h>
  28. #if HAVE_SYS_PARAM_H || defined _LIBC
  29. # include <sys/param.h>
  30. #endif
  31. #include <sys/stat.h>
  32. #include <errno.h>
  33. #include <stddef.h>
  34. #ifdef _LIBC
  35. # include <shlib-compat.h>
  36. #else
  37. # define SHLIB_COMPAT(lib, introduced, obsoleted) 0
  38. # define versioned_symbol(lib, local, symbol, version) extern int dummy
  39. # define compat_symbol(lib, local, symbol, version)
  40. # define weak_alias(local, symbol)
  41. # define __canonicalize_file_name canonicalize_file_name
  42. # define __realpath realpath
  43. # include "pathmax.h"
  44. # include "malloca.h"
  45. # include "dosname.h"
  46. # if 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. # ifdef VMS
  54. /* We want the directory in Unix syntax, not in VMS syntax. */
  55. # define __getcwd(buf, max) getcwd (buf, max, 0)
  56. # else
  57. # define __getcwd getcwd
  58. # endif
  59. # else
  60. # define __getcwd(buf, max) getwd (buf)
  61. # endif
  62. # define __readlink readlink
  63. # define __set_errno(e) errno = (e)
  64. # ifndef MAXSYMLINKS
  65. # ifdef SYMLOOP_MAX
  66. # define MAXSYMLINKS SYMLOOP_MAX
  67. # else
  68. # define MAXSYMLINKS 20
  69. # endif
  70. # endif
  71. #endif
  72. #ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
  73. # define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
  74. #endif
  75. #if !FUNC_REALPATH_WORKS || defined _LIBC
  76. /* Return the canonical absolute name of file NAME. A canonical name
  77. does not contain any ".", ".." components nor any repeated path
  78. separators ('/') or symlinks. All path components must exist. If
  79. RESOLVED is null, the result is malloc'd; otherwise, if the
  80. canonical name is PATH_MAX chars or more, returns null with 'errno'
  81. set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
  82. returns the name in RESOLVED. If the name cannot be resolved and
  83. RESOLVED is non-NULL, it contains the path of the first component
  84. that cannot be resolved. If the path can be resolved, RESOLVED
  85. holds the same value as the value returned. */
  86. char *
  87. __realpath (const char *name, char *resolved)
  88. {
  89. char *rpath, *dest, *extra_buf = NULL;
  90. const char *start, *end, *rpath_limit;
  91. long int path_max;
  92. int num_links = 0;
  93. size_t prefix_len;
  94. if (name == NULL)
  95. {
  96. /* As per Single Unix Specification V2 we must return an error if
  97. either parameter is a null pointer. We extend this to allow
  98. the RESOLVED parameter to be NULL in case the we are expected to
  99. allocate the room for the return value. */
  100. __set_errno (EINVAL);
  101. return NULL;
  102. }
  103. if (name[0] == '\0')
  104. {
  105. /* As per Single Unix Specification V2 we must return an error if
  106. the name argument points to an empty string. */
  107. __set_errno (ENOENT);
  108. return NULL;
  109. }
  110. #ifdef PATH_MAX
  111. path_max = PATH_MAX;
  112. #else
  113. path_max = pathconf (name, _PC_PATH_MAX);
  114. if (path_max <= 0)
  115. path_max = 8192;
  116. #endif
  117. if (resolved == NULL)
  118. {
  119. rpath = malloc (path_max);
  120. if (rpath == NULL)
  121. {
  122. /* It's easier to set errno to ENOMEM than to rely on the
  123. 'malloc-posix' gnulib module. */
  124. errno = ENOMEM;
  125. return NULL;
  126. }
  127. }
  128. else
  129. rpath = resolved;
  130. rpath_limit = rpath + path_max;
  131. /* This is always zero for Posix hosts, but can be 2 for MS-Windows
  132. and MS-DOS X:/foo/bar file names. */
  133. prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
  134. if (!IS_ABSOLUTE_FILE_NAME (name))
  135. {
  136. if (!__getcwd (rpath, path_max))
  137. {
  138. rpath[0] = '\0';
  139. goto error;
  140. }
  141. dest = strchr (rpath, '\0');
  142. start = name;
  143. prefix_len = FILE_SYSTEM_PREFIX_LEN (rpath);
  144. }
  145. else
  146. {
  147. dest = rpath;
  148. if (prefix_len)
  149. {
  150. memcpy (rpath, name, prefix_len);
  151. dest += prefix_len;
  152. }
  153. *dest++ = '/';
  154. if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
  155. {
  156. if (ISSLASH (name[1]) && !ISSLASH (name[2]) && !prefix_len)
  157. *dest++ = '/';
  158. *dest = '\0';
  159. }
  160. start = name + prefix_len;
  161. }
  162. for (end = start; *start; start = end)
  163. {
  164. #ifdef _LIBC
  165. struct stat64 st;
  166. #else
  167. struct stat st;
  168. #endif
  169. int n;
  170. /* Skip sequence of multiple path-separators. */
  171. while (ISSLASH (*start))
  172. ++start;
  173. /* Find end of path component. */
  174. for (end = start; *end && !ISSLASH (*end); ++end)
  175. /* Nothing. */;
  176. if (end - start == 0)
  177. break;
  178. else if (end - start == 1 && start[0] == '.')
  179. /* nothing */;
  180. else if (end - start == 2 && start[0] == '.' && start[1] == '.')
  181. {
  182. /* Back up to previous component, ignore if at root already. */
  183. if (dest > rpath + prefix_len + 1)
  184. for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest)
  185. continue;
  186. if (DOUBLE_SLASH_IS_DISTINCT_ROOT
  187. && dest == rpath + 1 && !prefix_len
  188. && ISSLASH (*dest) && !ISSLASH (dest[1]))
  189. dest++;
  190. }
  191. else
  192. {
  193. size_t new_size;
  194. if (!ISSLASH (dest[-1]))
  195. *dest++ = '/';
  196. if (dest + (end - start) >= rpath_limit)
  197. {
  198. ptrdiff_t dest_offset = dest - rpath;
  199. char *new_rpath;
  200. if (resolved)
  201. {
  202. __set_errno (ENAMETOOLONG);
  203. if (dest > rpath + prefix_len + 1)
  204. dest--;
  205. *dest = '\0';
  206. goto error;
  207. }
  208. new_size = rpath_limit - rpath;
  209. if (end - start + 1 > path_max)
  210. new_size += end - start + 1;
  211. else
  212. new_size += path_max;
  213. new_rpath = (char *) realloc (rpath, new_size);
  214. if (new_rpath == NULL)
  215. {
  216. /* It's easier to set errno to ENOMEM than to rely on the
  217. 'realloc-posix' gnulib module. */
  218. errno = ENOMEM;
  219. goto error;
  220. }
  221. rpath = new_rpath;
  222. rpath_limit = rpath + new_size;
  223. dest = rpath + dest_offset;
  224. }
  225. #ifdef _LIBC
  226. dest = __mempcpy (dest, start, end - start);
  227. #else
  228. memcpy (dest, start, end - start);
  229. dest += end - start;
  230. #endif
  231. *dest = '\0';
  232. #ifdef _LIBC
  233. if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
  234. #else
  235. if (lstat (rpath, &st) < 0)
  236. #endif
  237. goto error;
  238. if (S_ISLNK (st.st_mode))
  239. {
  240. char *buf;
  241. size_t len;
  242. if (++num_links > MAXSYMLINKS)
  243. {
  244. __set_errno (ELOOP);
  245. goto error;
  246. }
  247. buf = malloca (path_max);
  248. if (!buf)
  249. {
  250. errno = ENOMEM;
  251. goto error;
  252. }
  253. n = __readlink (rpath, buf, path_max - 1);
  254. if (n < 0)
  255. {
  256. int saved_errno = errno;
  257. freea (buf);
  258. errno = saved_errno;
  259. goto error;
  260. }
  261. buf[n] = '\0';
  262. if (!extra_buf)
  263. {
  264. extra_buf = malloca (path_max);
  265. if (!extra_buf)
  266. {
  267. freea (buf);
  268. errno = ENOMEM;
  269. goto error;
  270. }
  271. }
  272. len = strlen (end);
  273. if ((long int) (n + len) >= path_max)
  274. {
  275. freea (buf);
  276. __set_errno (ENAMETOOLONG);
  277. goto error;
  278. }
  279. /* Careful here, end may be a pointer into extra_buf... */
  280. memmove (&extra_buf[n], end, len + 1);
  281. name = end = memcpy (extra_buf, buf, n);
  282. if (IS_ABSOLUTE_FILE_NAME (buf))
  283. {
  284. size_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
  285. if (pfxlen)
  286. memcpy (rpath, buf, pfxlen);
  287. dest = rpath + pfxlen;
  288. *dest++ = '/'; /* It's an absolute symlink */
  289. if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
  290. {
  291. if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
  292. *dest++ = '/';
  293. *dest = '\0';
  294. }
  295. /* Install the new prefix to be in effect hereafter. */
  296. prefix_len = pfxlen;
  297. }
  298. else
  299. {
  300. /* Back up to previous component, ignore if at root
  301. already: */
  302. if (dest > rpath + prefix_len + 1)
  303. for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest)
  304. continue;
  305. if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
  306. && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
  307. dest++;
  308. }
  309. }
  310. else if (!S_ISDIR (st.st_mode) && *end != '\0')
  311. {
  312. __set_errno (ENOTDIR);
  313. goto error;
  314. }
  315. }
  316. }
  317. if (dest > rpath + prefix_len + 1 && ISSLASH (dest[-1]))
  318. --dest;
  319. if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && !prefix_len
  320. && ISSLASH (*dest) && !ISSLASH (dest[1]))
  321. dest++;
  322. *dest = '\0';
  323. if (extra_buf)
  324. freea (extra_buf);
  325. return rpath;
  326. error:
  327. {
  328. int saved_errno = errno;
  329. if (extra_buf)
  330. freea (extra_buf);
  331. if (resolved == NULL)
  332. free (rpath);
  333. errno = saved_errno;
  334. }
  335. return NULL;
  336. }
  337. versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
  338. #endif /* !FUNC_REALPATH_WORKS || defined _LIBC */
  339. #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
  340. char *
  341. attribute_compat_text_section
  342. __old_realpath (const char *name, char *resolved)
  343. {
  344. if (resolved == NULL)
  345. {
  346. __set_errno (EINVAL);
  347. return NULL;
  348. }
  349. return __realpath (name, resolved);
  350. }
  351. compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
  352. #endif
  353. char *
  354. __canonicalize_file_name (const char *name)
  355. {
  356. return __realpath (name, NULL);
  357. }
  358. weak_alias (__canonicalize_file_name, canonicalize_file_name)
  359. #else
  360. /* This declaration is solely to ensure that after preprocessing
  361. this file is never empty. */
  362. typedef int dummy;
  363. #endif