summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1997-03-11 11:37:59 +0000
committerpeter <peter@FreeBSD.org>1997-03-11 11:37:59 +0000
commitbb2b65bb1cc28ad6ffb0a8ab803ddd9943de91da (patch)
treead41fd2b3398760ffefb779e1db7a0f3e078e00a /lib/libc
parent724b89cfd3fcf9531a8abee51d88f8722ab252a9 (diff)
downloadFreeBSD-src-bb2b65bb1cc28ad6ffb0a8ab803ddd9943de91da.zip
FreeBSD-src-bb2b65bb1cc28ad6ffb0a8ab803ddd9943de91da.tar.gz
merge from Lite2 - realpath() now shares a lot of code with getcwd()
and is now in the same file.
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/getcwd.c162
-rw-r--r--lib/libc/stdlib/realpath.3125
-rw-r--r--lib/libc/stdlib/realpath.c158
3 files changed, 158 insertions, 287 deletions
diff --git a/lib/libc/gen/getcwd.c b/lib/libc/gen/getcwd.c
index dfa482a..c067d11 100644
--- a/lib/libc/gen/getcwd.c
+++ b/lib/libc/gen/getcwd.c
@@ -1,7 +1,10 @@
/*
- * Copyright (c) 1989, 1991, 1993
+ * Copyright (c) 1989, 1991, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -32,19 +35,22 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)getcwd.c 8.1 (Berkeley) 6/4/93";
+static char sccsid[] = "@(#)getcwd.c 8.5 (Berkeley) 2/7/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <sys/stat.h>
-#include <errno.h>
#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+static char *getcwd_physical __P((char *, size_t));
+
#define ISDOT(dp) \
(dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
(dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
@@ -54,6 +60,154 @@ getcwd(pt, size)
char *pt;
size_t size;
{
+ char *pwd;
+ size_t pwdlen;
+ dev_t dev;
+ ino_t ino;
+ struct stat s;
+
+ /* Check $PWD -- if it's right, it's fast. */
+ if ((pwd = getenv("PWD")) != NULL && pwd[0] == '/' && !stat(pwd, &s)) {
+ dev = s.st_dev;
+ ino = s.st_ino;
+ if (!stat(".", &s) && dev == s.st_dev && ino == s.st_ino) {
+ pwdlen = strlen(pwd);
+ if (size != 0) {
+ if (pwdlen + 1 > size) {
+ errno = ERANGE;
+ return (NULL);
+ }
+ } else if ((pt = malloc(pwdlen + 1)) == NULL)
+ return (NULL);
+ memmove(pt, pwd, pwdlen);
+ pt[pwdlen] = '\0';
+ return (pt);
+ }
+ }
+
+ return (getcwd_physical(pt, size));
+}
+
+/*
+ * 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).
+ */
+char *
+realpath(path, resolved)
+ const char *path;
+ char *resolved;
+{
+ struct stat sb;
+ int fd, n, rootd, serrno;
+ char *p, *q, wbuf[MAXPATHLEN];
+
+ /* Save the starting point. */
+ if ((fd = open(".", O_RDONLY)) < 0) {
+ (void)strcpy(resolved, ".");
+ return (NULL);
+ }
+
+ /*
+ * 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';
+loop:
+ q = strrchr(resolved, '/');
+ if (q != NULL) {
+ p = q + 1;
+ if (q == resolved)
+ q = "/";
+ else {
+ do {
+ --q;
+ } while (q > resolved && *q == '/');
+ q[1] = '\0';
+ q = resolved;
+ }
+ if (chdir(q) < 0)
+ goto err1;
+ } else
+ p = resolved;
+
+ /* Deal with the last component. */
+ if (*p != '\0' && lstat(p, &sb) == 0) {
+ if (S_ISLNK(sb.st_mode)) {
+ n = readlink(p, resolved, MAXPATHLEN);
+ if (n < 0)
+ goto err1;
+ resolved[n] = '\0';
+ goto loop;
+ }
+ if (S_ISDIR(sb.st_mode)) {
+ if (chdir(p) < 0)
+ goto err1;
+ p = "";
+ }
+ }
+
+ /*
+ * Save the last component name and get the full pathname of
+ * the current directory.
+ */
+ (void)strcpy(wbuf, p);
+
+ /*
+ * Call the inernal internal version of getcwd which
+ * does a physical search rather than using the $PWD short-cut
+ */
+ if (getcwd_physical(resolved, MAXPATHLEN) == 0)
+ goto err1;
+
+ /*
+ * 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')
+ rootd = 1;
+ else
+ rootd = 0;
+
+ if (*wbuf) {
+ if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) {
+ errno = ENAMETOOLONG;
+ goto err1;
+ }
+ if (rootd == 0)
+ (void)strcat(resolved, "/");
+ (void)strcat(resolved, wbuf);
+ }
+
+ /* Go back to where we came from. */
+ if (fchdir(fd) < 0) {
+ serrno = errno;
+ goto err2;
+ }
+
+ /* It's okay if the close fails, what's an fd more or less? */
+ (void)close(fd);
+ return (resolved);
+
+err1: serrno = errno;
+ (void)fchdir(fd);
+err2: (void)close(fd);
+ errno = serrno;
+ return (NULL);
+}
+
+static char *
+getcwd_physical(pt, size)
+ char *pt;
+ size_t size;
+{
register struct dirent *dp;
register DIR *dir;
register dev_t dev;
@@ -94,7 +248,7 @@ getcwd(pt, size)
/*
* Allocate bytes (1024 - malloc space) for the string of "../"'s.
* Should always be enough (it's 340 levels). If it's not, allocate
- * as necessary. Special * case the first stat, it's ".", not "..".
+ * as necessary. Special case the first stat, it's ".", not "..".
*/
if ((up = malloc(upsize = 1024 - 4)) == NULL)
goto err;
diff --git a/lib/libc/stdlib/realpath.3 b/lib/libc/stdlib/realpath.3
deleted file mode 100644
index 83f4a43..0000000
--- a/lib/libc/stdlib/realpath.3
+++ /dev/null
@@ -1,125 +0,0 @@
-.\" Copyright (c) 1994
-.\" The Regents of the University of California. All rights reserved.
-.\"
-.\" This code is derived from software contributed to Berkeley by
-.\" Jan-Simon Pendry.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 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
-.\" SUCH DAMAGE.
-.\"
-.\" @(#)realpath.3 8.2 (Berkeley) 2/16/94
-.\"
-.Dd "February 16, 1994"
-.Dt REALPATH 3
-.Os
-.Sh NAME
-.Nm realpath
-.Nd returns the canonicalized absolute pathname
-.Sh SYNOPSIS
-.Fd #include <sys/param.h>
-.Fd #include <stdlib.h>
-.Ft "char *"
-.Fn realpath "const char *pathname" "char resolvedname[MAXPATHLEN]"
-.Sh DESCRIPTION
-The
-.Fn realpath
-function resolves all symbolic links, extra
-.Dq /
-characters and references to
-.Pa /./
-and
-.Pa /../
-in
-.Fa pathname ,
-and copies the resulting absolute pathname into
-the memory referenced by
-.Fa resolvedname .
-The
-.Fa resolvedname
-argument
-.Em must
-refer to a buffer capable of storing at least
-.Dv MAXPATHLEN
-characters.
-.Pp
-The
-.Fn realpath
-function will resolve both absolute and relative paths
-and return the absolute pathname corresponding to
-.Fa pathname .
-All but the last component of
-.Fa pathname
-must exist when
-.Fn realpath
-is called.
-.Sh "RETURN VALUES"
-The
-.Fn realpath
-function returns
-.Fa resolved_name
-on success.
-If an error occurs,
-.Fn realpath
-returns
-.Dv NULL ,
-and
-.Fa resolved_name
-contains the pathname which caused the problem.
-.Sh ERRORS
-The function
-.Fn realpath
-may fail and set the external variable
-.Va errno
-for any of the errors specified for the library functions
-.Xr chdir 2 ,
-.Xr close 2 ,
-.Xr fchdir 2 ,
-.Xr lstat 2 ,
-.Xr open 2 ,
-.Xr readlink 2
-and
-.Xr getcwd 3 .
-.Sh CAVEATS
-This implementation of
-.Fn realpath
-differs slightly from the Solaris implementation.
-The
-.Bx 4.4
-version always returns absolute pathnames,
-whereas the Solaris implementation will,
-under certain circumstances, return a relative
-.Fa resolved_path
-when given a relative
-.Fa pathname .
-.Sh "SEE ALSO"
-.Xr getcwd 3
-.Sh HISTORY
-The
-.Fn realpath
-function call first appeared in
-.Bx 4.4 .
diff --git a/lib/libc/stdlib/realpath.c b/lib/libc/stdlib/realpath.c
deleted file mode 100644
index 28380d7..0000000
--- a/lib/libc/stdlib/realpath.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 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
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)realpath.c 8.1 (Berkeley) 2/16/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-/*
- * 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).
- */
-char *
-realpath(path, resolved)
- const char *path;
- char *resolved;
-{
- struct stat sb;
- int fd, n, rootd, serrno;
- char *p, *q, wbuf[MAXPATHLEN];
-
- /* Save the starting point. */
- if ((fd = open(".", O_RDONLY)) < 0) {
- (void)strcpy(resolved, ".");
- return (NULL);
- }
-
- /*
- * 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';
-loop:
- q = strrchr(resolved, '/');
- if (q != NULL) {
- p = q + 1;
- if (q == resolved)
- q = "/";
- else {
- do {
- --q;
- } while (q > resolved && *q == '/');
- q[1] = '\0';
- q = resolved;
- }
- if (chdir(q) < 0)
- goto err1;
- } else
- p = resolved;
-
- /* Deal with the last component. */
- if (*p != '\0' && lstat(p, &sb) == 0) {
- if (S_ISLNK(sb.st_mode)) {
- n = readlink(p, resolved, MAXPATHLEN);
- if (n < 0)
- goto err1;
- resolved[n] = '\0';
- goto loop;
- }
- if (S_ISDIR(sb.st_mode)) {
- if (chdir(p) < 0)
- goto err1;
- p = "";
- }
- }
-
- /*
- * Save the last component name and get the full pathname of
- * the current directory.
- */
- (void)strcpy(wbuf, p);
- if (getcwd(resolved, MAXPATHLEN) == 0)
- goto err1;
-
- /*
- * 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')
- rootd = 1;
- else
- rootd = 0;
-
- if (*wbuf) {
- if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) {
- errno = ENAMETOOLONG;
- goto err1;
- }
- if (rootd == 0)
- (void)strcat(resolved, "/");
- (void)strcat(resolved, wbuf);
- }
-
- /* Go back to where we came from. */
- if (fchdir(fd) < 0) {
- serrno = errno;
- goto err2;
- }
-
- /* It's okay if the close fails, what's an fd more or less? */
- (void)close(fd);
- return (resolved);
-
-err1: serrno = errno;
- (void)fchdir(fd);
-err2: (void)close(fd);
- errno = serrno;
- return (NULL);
-}
OpenPOWER on IntegriCloud