1
/* Return the canonical absolute name of a given file.
2
Copyright (C) 1996 Free Software Foundation, Inc.
3
This file is part of the GNU C Library.
5
The GNU C Library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Library General Public License as
7
published by the Free Software Foundation; either version 2 of the
8
License, or (at your option) any later version.
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
Library General Public License for more details.
15
You should have received a copy of the GNU Library General Public
16
License along with the GNU C Library; see the file COPYING.LIB. If not,
17
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
Boston, MA 02111-1307, USA. */
20
/* I've hacked this file to compile with Jade --jsh */
26
/* AIX requires this to be the first thing in the file. */
28
# define alloca __builtin_alloca
36
# ifndef alloca /* predefined by HP cc +Olibcalls */
52
#include <sys/param.h>
56
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
60
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
63
/* Return the canonical absolute name of file NAME. A canonical name
64
does not contain any `.', `..' components nor any repeated path
65
separators ('/') or symlinks. All path components must exist. If
66
RESOLVED is null, the result is malloc'd; otherwise, if the
67
canonical name is PATH_MAX chars or more, returns null with `errno'
68
set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
69
returns the name in RESOLVED. If the name cannot be resolved and
70
RESOLVED is non-NULL, it contains the path of the first component
71
that cannot be resolved. If the path can be resolved, RESOLVED
72
holds the same value as the value returned. */
74
/* I'll never test errno, so ignore all attempts to set it, in the
75
interests of portability.. */
76
#define __set_errno(err)
79
realpath (const char *name, char *resolved)
81
char *rpath, *dest, *extra_buf = NULL;
82
const char *start, *end, *rpath_limit;
89
path_max = pathconf (name, _PC_PATH_MAX);
94
rpath = resolved ? alloca (path_max) : malloc (path_max);
95
rpath_limit = rpath + path_max;
100
if (!getcwd (rpath, path_max))
105
dest = strchr (rpath, '\0');
113
for (start = end = name; *start; start = end)
118
/* skip sequence of multiple path-separators: */
119
while (*start == '/') ++start;
121
/* find end of path component: */
122
for (end = start; *end && *end != '/'; ++end);
124
if (end - start == 0)
126
else if (strncmp (start, ".", end - start) == 0)
128
else if (strncmp (start, "..", end - start) == 0) {
129
/* back up to previous component, ignore if at root already: */
130
if (dest > rpath + 1)
131
while ((--dest)[-1] != '/');
139
if (dest + (end - start) >= rpath_limit)
143
__set_errno (ENAMETOOLONG);
146
new_size = rpath_limit - rpath;
147
if (end - start + 1 > path_max)
148
new_size += end - start + 1;
150
new_size += path_max;
151
rpath = realloc (rpath, new_size);
152
rpath_limit = rpath + new_size;
157
memcpy (dest, start, end - start);
161
if (lstat (rpath, &st) < 0)
164
if (S_ISLNK (st.st_mode))
166
char *buf = alloca (path_max);
168
if (++num_links > MAXSYMLINKS)
174
n = readlink (rpath, buf, path_max);
180
extra_buf = alloca (path_max);
182
if ((long int) (n + strlen (end)) >= path_max)
184
__set_errno (ENAMETOOLONG);
188
/* careful here, end may be a pointer into extra_buf... */
190
strcpy (extra_buf, buf);
191
name = end = extra_buf;
194
dest = rpath + 1; /* it's an absolute symlink */
196
/* back up to previous component, ignore if at root already: */
197
if (dest > rpath + 1)
198
while ((--dest)[-1] != '/');
204
if (dest > rpath + 1 && dest[-1] == '/')
208
return resolved ? strcpy (resolved, rpath) : rpath;
212
strcpy (resolved, rpath);
218
#endif /* !HAVE_REALPATH */