summaryrefslogtreecommitdiffstats
path: root/contrib/bmake/realpath.c
diff options
context:
space:
mode:
authorsjg <sjg@FreeBSD.org>2013-02-01 22:55:27 +0000
committersjg <sjg@FreeBSD.org>2013-02-01 22:55:27 +0000
commitf817112dff6d3bf2855772b5112bf05748266394 (patch)
tree203f81f05d53b13df9fb85ffa3d26ac6a5f93a55 /contrib/bmake/realpath.c
parent6a1efe1ad9984c8085ef28facb9d7f1cc2f01b6a (diff)
parent69db492ce55c9787def3ba14dca33e52909dd5ca (diff)
downloadFreeBSD-src-f817112dff6d3bf2855772b5112bf05748266394.zip
FreeBSD-src-f817112dff6d3bf2855772b5112bf05748266394.tar.gz
Merge bmake-20130123
Approved by: marcel (mentor)
Diffstat (limited to 'contrib/bmake/realpath.c')
-rw-r--r--contrib/bmake/realpath.c77
1 files changed, 48 insertions, 29 deletions
diff --git a/contrib/bmake/realpath.c b/contrib/bmake/realpath.c
index 1ef2cd8..fbf0335 100644
--- a/contrib/bmake/realpath.c
+++ b/contrib/bmake/realpath.c
@@ -1,5 +1,5 @@
-/* $Id: realpath.c,v 1.2 2010/04/21 17:47:49 sjg Exp $ */
-/* from: $NetBSD: getcwd.c,v 1.45 2007/10/26 19:48:14 christos Exp $ */
+/* $Id: realpath.c,v 1.3 2013/01/25 17:06:09 sjg Exp $ */
+/* from: $NetBSD: getcwd.c,v 1.53 2012/06/21 23:29:23 enami Exp $ */
/*
* Copyright (c) 1989, 1991, 1993, 1995
@@ -52,24 +52,40 @@
# include <unistd.h>
#endif
+#ifndef __restrict
+# define __restrict /* restrict */
+#endif
+
/*
- * char *realpath(const char *path, char resolved[MAXPATHLEN]);
+ * char *realpath(const char *path, char *resolved);
*
* 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(const char *path, char *resolved)
+realpath(const char * __restrict path, char * __restrict resolved)
{
struct stat sb;
- int idx = 0, n, nlnk = 0;
+ int idx = 0, nlnk = 0;
const char *q;
- char *p, wbuf[2][MAXPATHLEN];
+ char *p, wbuf[2][MAXPATHLEN], *fres;
size_t len;
+ ssize_t n;
+
+ /* POSIX sez we must test for this */
+ if (path == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (resolved == NULL) {
+ fres = resolved = malloc(MAXPATHLEN);
+ if (resolved == NULL)
+ return NULL;
+ } else
+ fres = NULL;
- if (!path || !resolved || path == resolved)
- return (NULL);
/*
* Build real path one by one with paying an attention to .,
@@ -82,10 +98,10 @@ realpath(const char *path, char *resolved)
*/
p = resolved;
- if (*path == 0) {
- *p = 0;
+ if (*path == '\0') {
+ *p = '\0';
errno = ENOENT;
- return (NULL);
+ goto out;
}
/* If relative path, start from current working directory. */
@@ -93,8 +109,8 @@ realpath(const char *path, char *resolved)
/* check for resolved pointer to appease coverity */
if (resolved && getcwd(resolved, MAXPATHLEN) == NULL) {
p[0] = '.';
- p[1] = 0;
- return (NULL);
+ p[1] = '\0';
+ goto out;
}
len = strlen(resolved);
if (len > 1)
@@ -106,18 +122,18 @@ loop:
while (*path == '/')
path++;
- if (*path == 0) {
+ if (*path == '\0') {
if (p == resolved)
*p++ = '/';
- *p = 0;
- return (resolved);
+ *p = '\0';
+ return resolved;
}
/* Find the end of this component. */
q = path;
do
q++;
- while (*q != '/' && *q != 0);
+ while (*q != '/' && *q != '\0');
/* Test . or .. */
if (path[0] == '.') {
@@ -129,7 +145,7 @@ loop:
/* Trim the last component. */
if (p != resolved)
while (*--p != '/')
- ;
+ continue;
path = q;
goto loop;
}
@@ -140,39 +156,39 @@ loop:
errno = ENAMETOOLONG;
if (p == resolved)
*p++ = '/';
- *p = 0;
- return (NULL);
+ *p = '\0';
+ goto out;
}
p[0] = '/';
memcpy(&p[1], path,
/* LINTED We know q > path. */
q - path);
- p[1 + q - path] = 0;
+ p[1 + q - path] = '\0';
/*
* If this component is a symlink, toss it and prepend link
* target to unresolved path.
*/
- if (lstat(resolved, &sb) == -1) {
- return (NULL);
- }
+ if (lstat(resolved, &sb) == -1)
+ goto out;
+
if (S_ISLNK(sb.st_mode)) {
if (nlnk++ >= MAXSYMLINKS) {
errno = ELOOP;
- return (NULL);
+ goto out;
}
n = readlink(resolved, wbuf[idx], sizeof(wbuf[0]) - 1);
if (n < 0)
- return (NULL);
+ goto out;
if (n == 0) {
errno = ENOENT;
- return (NULL);
+ goto out;
}
/* Append unresolved path to link target and switch to it. */
if (n + (len = strlen(q)) + 1 > sizeof(wbuf[0])) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto out;
}
memcpy(&wbuf[idx][n], q, len + 1);
path = wbuf[idx];
@@ -185,12 +201,15 @@ loop:
}
if (*q == '/' && !S_ISDIR(sb.st_mode)) {
errno = ENOTDIR;
- return (NULL);
+ goto out;
}
/* Advance both resolved and unresolved path. */
p += 1 + q - path;
path = q;
goto loop;
+out:
+ free(fres);
+ return NULL;
}
#endif
OpenPOWER on IntegriCloud