X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/59e0d9fe772464b93d835d2a2964457702469a43..7ba935f9833da45a0dbcb06329e3015acee97223:/stdlib/FreeBSD/realpath.c.patch diff --git a/stdlib/FreeBSD/realpath.c.patch b/stdlib/FreeBSD/realpath.c.patch index 603dc2b..2d154b1 100644 --- a/stdlib/FreeBSD/realpath.c.patch +++ b/stdlib/FreeBSD/realpath.c.patch @@ -1,6 +1,12 @@ ---- realpath.c.orig Fri Aug 15 19:22:17 2003 -+++ realpath.c Tue Dec 9 14:36:32 2003 -@@ -40,8 +40,27 @@ +--- realpath.c.orig 2008-04-04 14:39:39.000000000 -0700 ++++ realpath.c 2008-04-04 19:59:19.000000000 -0700 +@@ -35,13 +35,41 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/ + #include "namespace.h" + #include + #include ++#include + + #include #include #include #include @@ -11,26 +17,37 @@ +struct attrs { + u_int32_t len; + attrreference_t name; ++ dev_t dev; + fsobj_type_t type; ++ fsobj_id_t id; + char buf[PATH_MAX]; +}; + -+static struct attrlist alist = { ++#ifndef BUILDING_VARIANT ++__private_extern__ struct attrlist _rp_alist = { + ATTR_BIT_MAP_COUNT, + 0, -+ ATTR_CMN_NAME | ATTR_CMN_OBJTYPE, ++ ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_OBJTYPE | ATTR_CMN_OBJID, + 0, + 0, + 0, + 0, +}; ++#else /* BUILDING_VARIANT */ ++__private_extern__ struct attrlist _rp_alist; ++#endif /* BUILDING_VARIANT */ ++ ++extern char * __private_getcwd(char *, size_t, int); + /* * char *realpath(const char *path, char resolved[PATH_MAX]); * -@@ -52,11 +71,12 @@ +@@ -50,26 +78,67 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/ + * in which case the path which caused trouble is left in (resolved). + */ char * - realpath(const char *path, char resolved[PATH_MAX]) +-realpath(const char *path, char resolved[PATH_MAX]) ++realpath(const char *path, char inresolved[PATH_MAX]) { + struct attrs attrs; struct stat sb; @@ -41,9 +58,78 @@ - int serrno, slen; + int serrno, slen, useattrs, islink; char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; ++ dev_t dev, lastdev; ++ struct statfs sfs; ++ static dev_t rootdev; ++ static int rootdev_inited = 0; ++ ino_t inode; ++ char *resolved; ++ if (path == NULL) { ++ errno = EINVAL; ++ return (NULL); ++ } ++#if __DARWIN_UNIX03 ++ if (*path == 0) { ++ errno = ENOENT; ++ return (NULL); ++ } ++#endif /* __DARWIN_UNIX03 */ ++ /* ++ * Extension to the standard; if inresolved == NULL, allocate memory ++ * (first on the stack, then use strdup()) ++ */ ++ if (!inresolved) { ++ if ((resolved = alloca(PATH_MAX)) == NULL) return (NULL); ++ } else { ++ resolved = inresolved; ++ } ++ if (!rootdev_inited) { ++ rootdev_inited = 1; ++ if (stat("/", &sb) < 0) { ++ return (NULL); ++ } ++ rootdev = sb.st_dev; ++ } serrno = errno; -@@ -127,6 +147,13 @@ + symlinks = 0; + if (path[0] == '/') { + resolved[0] = '/'; + resolved[1] = '\0'; +- if (path[1] == '\0') ++ if (path[1] == '\0') { + return (resolved); ++ } + resolved_len = 1; + left_len = strlcpy(left, path + 1, sizeof(left)); + } else { +- if (getcwd(resolved, PATH_MAX) == NULL) { ++#if !defined(VARIANT_DARWINEXTSN) && __DARWIN_UNIX03 ++ /* 4447159: don't use GETPATH, so this will fail if */ ++ /* if parent directories are not readable, as per POSIX */ ++ if (__private_getcwd(resolved, PATH_MAX, 0) == NULL) ++#else /* VARIANT_DARWINEXTSN || !__DARWIN_UNIX03 */ ++ if (__private_getcwd(resolved, PATH_MAX, 1) == NULL) ++#endif /* !VARIANT_DARWINEXTSN && __DARWIN_UNIX03 */ ++ { + strlcpy(resolved, ".", PATH_MAX); + return (NULL); + } +@@ -80,6 +149,13 @@ realpath(const char *path, char resolved + errno = ENAMETOOLONG; + return (NULL); + } ++ if (resolved_len > 1) { ++ if (stat(resolved, &sb) < 0) { ++ return (NULL); ++ } ++ lastdev = sb.st_dev; ++ } else ++ lastdev = rootdev; + + /* + * Iterate over path components in `left'. +@@ -127,6 +203,13 @@ realpath(const char *path, char resolved } /* @@ -57,32 +143,98 @@ * Append the next path component and lstat() it. If * lstat() fails we still can return successfully if * there are no more path components left. -@@ -136,14 +163,22 @@ +@@ -136,25 +219,87 @@ realpath(const char *path, char resolved errno = ENAMETOOLONG; return (NULL); } - if (lstat(resolved, &sb) != 0) { -+ if (getattrlist(resolved, &alist, &attrs, sizeof(attrs), FSOPT_NOFOLLOW) == 0) { ++ if (getattrlist(resolved, &_rp_alist, &attrs, sizeof(attrs), FSOPT_NOFOLLOW) == 0) { + useattrs = 1; + islink = (attrs.type == VLNK); -+ } else if (errno == EOPNOTSUPP || errno == EINVAL) { -+ if ((useattrs = lstat(resolved, &sb)) == 0) ++ dev = attrs.dev; ++ inode = attrs.id.fid_objno; ++ } else if (errno == ENOTSUP || errno == EINVAL) { ++ if ((useattrs = lstat(resolved, &sb)) == 0) { + islink = S_ISLNK(sb.st_mode); ++ dev = sb.st_dev; ++ inode = sb.st_ino; ++ } + } else + useattrs = -1; + if (useattrs < 0) { ++#if !__DARWIN_UNIX03 if (errno == ENOENT && p == NULL) { errno = serrno; return (resolved); } ++#endif /* !__DARWIN_UNIX03 */ return (NULL); } - if (S_ISLNK(sb.st_mode)) { ++ if (dev != lastdev) { ++ /* ++ * We have crossed a mountpoint. For volumes like UDF ++ * the getattrlist name may not match the actual ++ * mountpoint, so we just copy the mountpoint directly. ++ * (3703138). However, the mountpoint may not be ++ * accessible, as when chroot-ed, so check first. ++ * There may be a file on the chroot-ed volume with ++ * the same name as the mountpoint, so compare device ++ * and inode numbers. ++ */ ++ lastdev = dev; ++ if (statfs(resolved, &sfs) == 0 && lstat(sfs.f_mntonname, &sb) == 0 && dev == sb.st_dev && inode == sb.st_ino) { ++ /* ++ * However, it's possible that the mountpoint ++ * path matches, even though it isn't the real ++ * path in the chroot-ed environment, so check ++ * that each component of the mountpoint ++ * is a directory (and not a symlink) ++ */ ++ char temp[sizeof(sfs.f_mntonname)]; ++ char *cp; ++ int ok = 1; ++ ++ strcpy(temp, sfs.f_mntonname); ++ for(;;) { ++ if ((cp = strrchr(temp, '/')) == NULL) { ++ ok = 0; ++ break; ++ } ++ if (cp <= temp) ++ break; ++ *cp = 0; ++ if (lstat(temp, &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFDIR) { ++ ok = 0; ++ break; ++ } ++ } ++ if (ok) { ++ resolved_len = strlcpy(resolved, sfs.f_mntonname, PATH_MAX); ++ continue; ++ } ++ } ++ /* if we fail, use the other methods. */ ++ } + if (islink) { if (symlinks++ > MAXSYMLINKS) { errno = ELOOP; return (NULL); -@@ -184,7 +219,30 @@ + } + slen = readlink(resolved, symlink, sizeof(symlink) - 1); +- if (slen < 0) ++ if (slen < 0) { + return (NULL); ++ } + symlink[slen] = '\0'; + if (symlink[0] == '/') { + resolved[1] = 0; + resolved_len = 1; ++ lastdev = rootdev; + } else if (resolved_len > 1) { + /* Strip the last path component. */ + resolved[resolved_len - 1] = '\0'; +@@ -184,7 +329,30 @@ realpath(const char *path, char resolved } } left_len = strlcpy(left, symlink, sizeof(left)); @@ -113,3 +265,10 @@ } /* +@@ -193,5 +361,6 @@ realpath(const char *path, char resolved + */ + if (resolved_len > 1 && resolved[resolved_len - 1] == '/') + resolved[resolved_len - 1] = '\0'; ++ if (!inresolved) resolved = strdup(resolved); + return (resolved); + }