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