3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 /* $XFree86: xc/programs/xedit/realpath.c,v 1.4 2000/02/12 20:45:45 dawes Exp $ */
38 #if defined(LIBC_SCCS) && !defined(lint)
39 static char sccsid[] = "@(#)realpath.c 8.1 (Berkeley) 2/16/94";
40 #endif /* LIBC_SCCS and not lint */
42 #include <sys/param.h>
43 #include <sys/types.h>
62 #define MAXPATHLEN 1024
66 #define MAXSYMLINKS 256
70 * char *realpath(const char *path, char resolved_path[MAXPATHLEN]);
72 * Find the real name of path, by removing all ".", ".." and symlink
73 * components. Returns (resolved) on success, or (NULL) on failure,
74 * in which case the path which caused trouble is left in (resolved).
77 realpath(path, resolved)
83 char start[MAXPATHLEN];
88 char *p, *q, wbuf[MAXPATHLEN];
91 /* Save the starting point. */
93 if (getcwd(start, MAXPATHLEN) == NULL) {
94 (void)strcpy(resolved, ".");
98 if ((fd = open(".", O_RDONLY)) < 0) {
99 (void)strcpy(resolved, ".");
105 * Find the dirname and basename from the path to be resolved.
106 * Change directory to the dirname component.
107 * lstat the basename part.
108 * if it is a symlink, read in the value and loop.
109 * if it is a directory, then change to that directory.
110 * get the current directory name and append the basename.
112 (void)strncpy(resolved, path, MAXPATHLEN - 1);
113 resolved[MAXPATHLEN - 1] = '\0';
115 q = strrchr(resolved, '/');
123 } while (q > resolved && *q == '/');
132 /* Deal with the last component. */
133 if (*p != '\0' && lstat(p, &sb) == 0) {
134 if (S_ISLNK(sb.st_mode)) {
135 if (++symlinks > MAXSYMLINKS) {
139 n = readlink(p, resolved, MAXPATHLEN);
145 if (S_ISDIR(sb.st_mode)) {
153 * Save the last component name and get the full pathname of
154 * the current directory.
156 (void)strcpy(wbuf, p);
157 if (getcwd(resolved, MAXPATHLEN) == 0)
161 * Join the two strings together, ensuring that the right thing
162 * happens if the last component is empty, or the dirname is root.
164 if (resolved[0] == '/' && resolved[1] == '\0')
170 if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) {
171 errno = ENAMETOOLONG;
175 (void)strcat(resolved, "/");
176 (void)strcat(resolved, wbuf);
179 /* Go back to where we came from. */
181 if (chdir(start) < 0)
190 /* It's okay if the close fails, what's an fd more or less? */
196 err1: serrno = errno;