canonicalize-lgpl.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /* Return the canonical absolute name of a given file.
  2. Copyright (C) 1996-2012 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. # define _GL_USE_STDLIB_ALLOC 1
  16. # include <config.h>
  17. #endif
  18. #if !HAVE_CANONICALIZE_FILE_NAME || !FUNC_REALPATH_WORKS || defined _LIBC
  19. /* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
  20. optimizes away the name == NULL test below. */
  21. #define _GL_ARG_NONNULL(params)
  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. # if HAVE_GETCWD
  46. # if IN_RELOCWRAPPER
  47. /* When building the relocatable program wrapper, use the system's getcwd
  48. function, not the gnulib override, otherwise we would get a link error.
  49. */
  50. # undef getcwd
  51. # endif
  52. # ifdef VMS
  53. /* We want the directory in Unix syntax, not in VMS syntax. */
  54. # define __getcwd(buf, max) getcwd (buf, max, 0)
  55. # else
  56. # define __getcwd getcwd
  57. # endif
  58. # else
  59. # define __getcwd(buf, max) getwd (buf)
  60. # endif
  61. # define __readlink readlink
  62. # define __set_errno(e) errno = (e)
  63. # ifndef MAXSYMLINKS
  64. # ifdef SYMLOOP_MAX
  65. # define MAXSYMLINKS SYMLOOP_MAX
  66. # else
  67. # define MAXSYMLINKS 20
  68. # endif
  69. # endif
  70. #endif
  71. #ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
  72. # define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
  73. #endif
  74. #if !FUNC_REALPATH_WORKS || defined _LIBC
  75. /* Return the canonical absolute name of file NAME. A canonical name
  76. does not contain any ".", ".." components nor any repeated path
  77. separators ('/') or symlinks. All path components must exist. If
  78. RESOLVED is null, the result is malloc'd; otherwise, if the
  79. canonical name is PATH_MAX chars or more, returns null with 'errno'
  80. set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
  81. returns the name in RESOLVED. If the name cannot be resolved and
  82. RESOLVED is non-NULL, it contains the path of the first component
  83. that cannot be resolved. If the path can be resolved, RESOLVED
  84. holds the same value as the value returned. */
  85. char *
  86. __realpath (const char *name, char *resolved)
  87. {
  88. char *rpath, *dest, *extra_buf = NULL;
  89. const char *start, *end, *rpath_limit;
  90. long int path_max;
  91. int num_links = 0;
  92. if (name == NULL)
  93. {
  94. /* As per Single Unix Specification V2 we must return an error if
  95. either parameter is a null pointer. We extend this to allow
  96. the RESOLVED parameter to be NULL in case the we are expected to
  97. allocate the room for the return value. */
  98. __set_errno (EINVAL);
  99. return NULL;
  100. }
  101. if (name[0] == '\0')
  102. {
  103. /* As per Single Unix Specification V2 we must return an error if
  104. the name argument points to an empty string. */
  105. __set_errno (ENOENT);
  106. return NULL;
  107. }
  108. #ifdef PATH_MAX
  109. path_max = PATH_MAX;
  110. #else
  111. path_max = pathconf (name, _PC_PATH_MAX);
  112. if (path_max <= 0)
  113. path_max = 8192;
  114. #endif
  115. if (resolved == NULL)
  116. {
  117. rpath = malloc (path_max);
  118. if (rpath == NULL)
  119. {
  120. /* It's easier to set errno to ENOMEM than to rely on the
  121. 'malloc-posix' gnulib module. */
  122. errno = ENOMEM;
  123. return NULL;
  124. }
  125. }
  126. else
  127. rpath = resolved;
  128. rpath_limit = rpath + path_max;
  129. if (name[0] != '/')
  130. {
  131. if (!__getcwd (rpath, path_max))
  132. {
  133. rpath[0] = '\0';
  134. goto error;
  135. }
  136. dest = strchr (rpath, '\0');
  137. }
  138. else
  139. {
  140. rpath[0] = '/';
  141. dest = rpath + 1;
  142. if (DOUBLE_SLASH_IS_DISTINCT_ROOT && name[1] == '/')
  143. *dest++ = '/';
  144. }
  145. for (start = end = name; *start; start = end)
  146. {
  147. #ifdef _LIBC
  148. struct stat64 st;
  149. #else
  150. struct stat st;
  151. #endif
  152. int n;
  153. /* Skip sequence of multiple path-separators. */
  154. while (*start == '/')
  155. ++start;
  156. /* Find end of path component. */
  157. for (end = start; *end && *end != '/'; ++end)
  158. /* Nothing. */;
  159. if (end - start == 0)
  160. break;
  161. else if (end - start == 1 && start[0] == '.')
  162. /* nothing */;
  163. else if (end - start == 2 && start[0] == '.' && start[1] == '.')
  164. {
  165. /* Back up to previous component, ignore if at root already. */
  166. if (dest > rpath + 1)
  167. while ((--dest)[-1] != '/');
  168. if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
  169. && *dest == '/')
  170. dest++;
  171. }
  172. else
  173. {
  174. size_t new_size;
  175. if (dest[-1] != '/')
  176. *dest++ = '/';
  177. if (dest + (end - start) >= rpath_limit)
  178. {
  179. ptrdiff_t dest_offset = dest - rpath;
  180. char *new_rpath;
  181. if (resolved)
  182. {
  183. __set_errno (ENAMETOOLONG);
  184. if (dest > rpath + 1)
  185. dest--;
  186. *dest = '\0';
  187. goto error;
  188. }
  189. new_size = rpath_limit - rpath;
  190. if (end - start + 1 > path_max)
  191. new_size += end - start + 1;
  192. else
  193. new_size += path_max;
  194. new_rpath = (char *) realloc (rpath, new_size);
  195. if (new_rpath == NULL)
  196. {
  197. /* It's easier to set errno to ENOMEM than to rely on the
  198. 'realloc-posix' gnulib module. */
  199. errno = ENOMEM;
  200. goto error;
  201. }
  202. rpath = new_rpath;
  203. rpath_limit = rpath + new_size;
  204. dest = rpath + dest_offset;
  205. }
  206. #ifdef _LIBC
  207. dest = __mempcpy (dest, start, end - start);
  208. #else
  209. memcpy (dest, start, end - start);
  210. dest += end - start;
  211. #endif
  212. *dest = '\0';
  213. #ifdef _LIBC
  214. if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
  215. #else
  216. if (lstat (rpath, &st) < 0)
  217. #endif
  218. goto error;
  219. if (S_ISLNK (st.st_mode))
  220. {
  221. char *buf;
  222. size_t len;
  223. if (++num_links > MAXSYMLINKS)
  224. {
  225. __set_errno (ELOOP);
  226. goto error;
  227. }
  228. buf = malloca (path_max);
  229. if (!buf)
  230. {
  231. errno = ENOMEM;
  232. goto error;
  233. }
  234. n = __readlink (rpath, buf, path_max - 1);
  235. if (n < 0)
  236. {
  237. int saved_errno = errno;
  238. freea (buf);
  239. errno = saved_errno;
  240. goto error;
  241. }
  242. buf[n] = '\0';
  243. if (!extra_buf)
  244. {
  245. extra_buf = malloca (path_max);
  246. if (!extra_buf)
  247. {
  248. freea (buf);
  249. errno = ENOMEM;
  250. goto error;
  251. }
  252. }
  253. len = strlen (end);
  254. if ((long int) (n + len) >= path_max)
  255. {
  256. freea (buf);
  257. __set_errno (ENAMETOOLONG);
  258. goto error;
  259. }
  260. /* Careful here, end may be a pointer into extra_buf... */
  261. memmove (&extra_buf[n], end, len + 1);
  262. name = end = memcpy (extra_buf, buf, n);
  263. if (buf[0] == '/')
  264. {
  265. dest = rpath + 1; /* It's an absolute symlink */
  266. if (DOUBLE_SLASH_IS_DISTINCT_ROOT && buf[1] == '/')
  267. *dest++ = '/';
  268. }
  269. else
  270. {
  271. /* Back up to previous component, ignore if at root
  272. already: */
  273. if (dest > rpath + 1)
  274. while ((--dest)[-1] != '/');
  275. if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
  276. && *dest == '/')
  277. dest++;
  278. }
  279. }
  280. else if (!S_ISDIR (st.st_mode) && *end != '\0')
  281. {
  282. __set_errno (ENOTDIR);
  283. goto error;
  284. }
  285. }
  286. }
  287. if (dest > rpath + 1 && dest[-1] == '/')
  288. --dest;
  289. if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && *dest == '/')
  290. dest++;
  291. *dest = '\0';
  292. if (extra_buf)
  293. freea (extra_buf);
  294. return rpath;
  295. error:
  296. {
  297. int saved_errno = errno;
  298. if (extra_buf)
  299. freea (extra_buf);
  300. if (resolved == NULL)
  301. free (rpath);
  302. errno = saved_errno;
  303. }
  304. return NULL;
  305. }
  306. versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
  307. #endif /* !FUNC_REALPATH_WORKS || defined _LIBC */
  308. #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
  309. char *
  310. attribute_compat_text_section
  311. __old_realpath (const char *name, char *resolved)
  312. {
  313. if (resolved == NULL)
  314. {
  315. __set_errno (EINVAL);
  316. return NULL;
  317. }
  318. return __realpath (name, resolved);
  319. }
  320. compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
  321. #endif
  322. char *
  323. __canonicalize_file_name (const char *name)
  324. {
  325. return __realpath (name, NULL);
  326. }
  327. weak_alias (__canonicalize_file_name, canonicalize_file_name)
  328. #else
  329. /* This declaration is solely to ensure that after preprocessing
  330. this file is never empty. */
  331. typedef int dummy;
  332. #endif