* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley by
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid
[] = "@(#)realpath.c 8.1 (Berkeley) 2/16/94";
#endif /* LIBC_SCCS and not lint */
* char *realpath(const char *path, char resolved_path[MAXPATHLEN]);
* Find the real name of path, by removing all ".", ".." and symlink
* components. Returns (resolved) on success, or (NULL) on failure,
* in which case the path which caused trouble is left in (resolved).
int fd
, n
, rootd
, serrno
;
char *p
, *q
, wbuf
[MAXPATHLEN
];
/* Save the starting point. */
if ((fd
= open(".", O_RDONLY
)) < 0) {
(void)strcpy(resolved
, ".");
* Find the dirname and basename from the path to be resolved.
* Change directory to the dirname component.
* lstat the basename part.
* if it is a symlink, read in the value and loop.
* if it is a directory, then change to that directory.
* get the current directory name and append the basename.
(void)strncpy(resolved
, path
, MAXPATHLEN
- 1);
resolved
[MAXPATHLEN
- 1] = '\0';
q
= strrchr(resolved
, '/');
} while (q
> resolved
&& *q
== '/');
/* Deal with the last component. */
if (lstat(p
, &sb
) == 0) {
if (S_ISLNK(sb
.st_mode
)) {
n
= readlink(p
, resolved
, MAXPATHLEN
);
if (S_ISDIR(sb
.st_mode
)) {
* Save the last component name and get the full pathname of
if (getcwd(resolved
, MAXPATHLEN
) == 0)
* Join the two strings together, ensuring that the right thing
* happens if the last component is empty, or the dirname is root.
if (resolved
[0] == '/' && resolved
[1] == '\0')
if (strlen(resolved
) + strlen(wbuf
) + rootd
+ 1 > MAXPATHLEN
) {
(void)strcat(resolved
, "/");
(void)strcat(resolved
, wbuf
);
/* Go back to where we came from. */
/* It's okay if the close fails, what's an fd more or less? */