canonicalize-lgpl.c 10.0 KB

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