canonicalize-lgpl.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /* Return the canonical absolute name of a given file.
  2. Copyright (C) 1996-2003, 2005-2008 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 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 General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. #include <config.h>
  15. /* Avoid a clash of our rpl_realpath() function with the prototype in
  16. <stdlib.h> on Solaris 2.5.1. */
  17. #undef realpath
  18. #if !HAVE_CANONICALIZE_FILE_NAME || defined _LIBC
  19. #include <alloca.h>
  20. /* Specification. */
  21. #include "canonicalize.h"
  22. #include <stddef.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #if HAVE_UNISTD_H || defined _LIBC
  26. # include <unistd.h>
  27. #endif
  28. #include <limits.h>
  29. #if HAVE_SYS_PARAM_H || defined _LIBC
  30. # include <sys/param.h>
  31. #endif
  32. #ifndef MAXSYMLINKS
  33. # define MAXSYMLINKS 20
  34. #endif
  35. #include <sys/stat.h>
  36. #include <errno.h>
  37. #ifndef _LIBC
  38. # define __set_errno(e) errno = (e)
  39. # ifndef ENAMETOOLONG
  40. # define ENAMETOOLONG EINVAL
  41. # endif
  42. #endif
  43. #ifdef _LIBC
  44. # include <shlib-compat.h>
  45. #else
  46. # define SHLIB_COMPAT(lib, introduced, obsoleted) 0
  47. # define versioned_symbol(lib, local, symbol, version)
  48. # define compat_symbol(lib, local, symbol, version)
  49. # define weak_alias(local, symbol)
  50. # define __canonicalize_file_name canonicalize_file_name
  51. # define __realpath rpl_realpath
  52. # include "pathmax.h"
  53. # include "malloca.h"
  54. # if HAVE_GETCWD
  55. # ifdef VMS
  56. /* We want the directory in Unix syntax, not in VMS syntax. */
  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 __readlink readlink
  65. /* On systems without symbolic links, call stat() instead of lstat(). */
  66. # if !defined S_ISLNK && !HAVE_READLINK
  67. # define lstat stat
  68. # endif
  69. #endif
  70. /* Return the canonical absolute name of file NAME. A canonical name
  71. does not contain any `.', `..' components nor any repeated path
  72. separators ('/') or symlinks. All path components must exist. If
  73. RESOLVED is null, the result is malloc'd; otherwise, if the
  74. canonical name is PATH_MAX chars or more, returns null with `errno'
  75. set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
  76. returns the name in RESOLVED. If the name cannot be resolved and
  77. RESOLVED is non-NULL, it contains the path of the first component
  78. that cannot be resolved. If the path can be resolved, RESOLVED
  79. holds the same value as the value returned. */
  80. char *
  81. __realpath (const char *name, char *resolved)
  82. {
  83. char *rpath, *dest, *extra_buf = NULL;
  84. const char *start, *end, *rpath_limit;
  85. long int path_max;
  86. #if HAVE_READLINK
  87. int num_links = 0;
  88. #endif
  89. if (name == NULL)
  90. {
  91. /* As per Single Unix Specification V2 we must return an error if
  92. either parameter is a null pointer. We extend this to allow
  93. the RESOLVED parameter to be NULL in case the we are expected to
  94. allocate the room for the return value. */
  95. __set_errno (EINVAL);
  96. return NULL;
  97. }
  98. if (name[0] == '\0')
  99. {
  100. /* As per Single Unix Specification V2 we must return an error if
  101. the name argument points to an empty string. */
  102. __set_errno (ENOENT);
  103. return NULL;
  104. }
  105. #ifdef PATH_MAX
  106. path_max = PATH_MAX;
  107. #else
  108. path_max = pathconf (name, _PC_PATH_MAX);
  109. if (path_max <= 0)
  110. path_max = 1024;
  111. #endif
  112. if (resolved == NULL)
  113. {
  114. rpath = malloc (path_max);
  115. if (rpath == NULL)
  116. {
  117. /* It's easier to set errno to ENOMEM than to rely on the
  118. 'malloc-posix' gnulib module. */
  119. errno = ENOMEM;
  120. return NULL;
  121. }
  122. }
  123. else
  124. rpath = resolved;
  125. rpath_limit = rpath + path_max;
  126. if (name[0] != '/')
  127. {
  128. if (!__getcwd (rpath, path_max))
  129. {
  130. rpath[0] = '\0';
  131. goto error;
  132. }
  133. dest = strchr (rpath, '\0');
  134. }
  135. else
  136. {
  137. rpath[0] = '/';
  138. dest = rpath + 1;
  139. }
  140. for (start = end = name; *start; start = end)
  141. {
  142. #ifdef _LIBC
  143. struct stat64 st;
  144. #else
  145. struct stat st;
  146. #endif
  147. /* Skip sequence of multiple path-separators. */
  148. while (*start == '/')
  149. ++start;
  150. /* Find end of path component. */
  151. for (end = start; *end && *end != '/'; ++end)
  152. /* Nothing. */;
  153. if (end - start == 0)
  154. break;
  155. else if (end - start == 1 && start[0] == '.')
  156. /* nothing */;
  157. else if (end - start == 2 && start[0] == '.' && start[1] == '.')
  158. {
  159. /* Back up to previous component, ignore if at root already. */
  160. if (dest > rpath + 1)
  161. while ((--dest)[-1] != '/');
  162. }
  163. else
  164. {
  165. size_t new_size;
  166. if (dest[-1] != '/')
  167. *dest++ = '/';
  168. if (dest + (end - start) >= rpath_limit)
  169. {
  170. ptrdiff_t dest_offset = dest - rpath;
  171. char *new_rpath;
  172. if (resolved)
  173. {
  174. __set_errno (ENAMETOOLONG);
  175. if (dest > rpath + 1)
  176. dest--;
  177. *dest = '\0';
  178. goto error;
  179. }
  180. new_size = rpath_limit - rpath;
  181. if (end - start + 1 > path_max)
  182. new_size += end - start + 1;
  183. else
  184. new_size += path_max;
  185. new_rpath = (char *) realloc (rpath, new_size);
  186. if (new_rpath == NULL)
  187. {
  188. /* It's easier to set errno to ENOMEM than to rely on the
  189. 'realloc-posix' gnulib module. */
  190. errno = ENOMEM;
  191. goto error;
  192. }
  193. rpath = new_rpath;
  194. rpath_limit = rpath + new_size;
  195. dest = rpath + dest_offset;
  196. }
  197. #ifdef _LIBC
  198. dest = __mempcpy (dest, start, end - start);
  199. #else
  200. memcpy (dest, start, end - start);
  201. dest += end - start;
  202. #endif
  203. *dest = '\0';
  204. #ifdef _LIBC
  205. if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
  206. #else
  207. if (lstat (rpath, &st) < 0)
  208. #endif
  209. goto error;
  210. #if HAVE_READLINK
  211. if (S_ISLNK (st.st_mode))
  212. {
  213. char *buf;
  214. size_t len;
  215. int n;
  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. dest = rpath + 1; /* It's an absolute symlink */
  258. else
  259. /* Back up to previous component, ignore if at root already: */
  260. if (dest > rpath + 1)
  261. while ((--dest)[-1] != '/');
  262. }
  263. #endif
  264. }
  265. }
  266. if (dest > rpath + 1 && dest[-1] == '/')
  267. --dest;
  268. *dest = '\0';
  269. if (extra_buf)
  270. freea (extra_buf);
  271. return resolved ? memcpy (resolved, rpath, dest - rpath + 1) : rpath;
  272. error:
  273. {
  274. int saved_errno = errno;
  275. if (extra_buf)
  276. freea (extra_buf);
  277. if (resolved)
  278. strcpy (resolved, rpath);
  279. else
  280. free (rpath);
  281. errno = saved_errno;
  282. }
  283. return NULL;
  284. }
  285. #ifdef _LIBC
  286. versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
  287. #endif
  288. #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
  289. char *
  290. __old_realpath (const char *name, char *resolved)
  291. {
  292. if (resolved == NULL)
  293. {
  294. __set_errno (EINVAL);
  295. return NULL;
  296. }
  297. return __realpath (name, resolved);
  298. }
  299. compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
  300. #endif
  301. char *
  302. __canonicalize_file_name (const char *name)
  303. {
  304. return __realpath (name, NULL);
  305. }
  306. weak_alias (__canonicalize_file_name, canonicalize_file_name)
  307. #else
  308. /* This declaration is solely to ensure that after preprocessing
  309. this file is never empty. */
  310. typedef int dummy;
  311. #endif