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