X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/59e0d9fe772464b93d835d2a2964457702469a43..7c78c5292a74d7cc20fc03e02fbfc976e072f928:/stdlib/FreeBSD/realpath.c.patch diff --git a/stdlib/FreeBSD/realpath.c.patch b/stdlib/FreeBSD/realpath.c.patch index 603dc2b..dd06685 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 2003-08-15 19:22:17.000000000 -0700 ++++ realpath.c 2004-12-04 14:47:52.000000000 -0800 +@@ -35,13 +35,35 @@ + #include "namespace.h" + #include + #include ++#include + + #include #include #include #include @@ -11,14 +17,16 @@ +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 = { + 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, @@ -28,7 +36,7 @@ /* * char *realpath(const char *path, char resolved[PATH_MAX]); * -@@ -52,11 +71,12 @@ +@@ -52,13 +74,25 @@ char * realpath(const char *path, char resolved[PATH_MAX]) { @@ -41,9 +49,35 @@ - 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; ++ 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] == '/') { +@@ -80,6 +114,12 @@ + 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 +167,13 @@ } /* @@ -57,7 +91,7 @@ * 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,14 +183,72 @@ errno = ENAMETOOLONG; return (NULL); } @@ -65,9 +99,14 @@ + if (getattrlist(resolved, &alist, &attrs, sizeof(attrs), FSOPT_NOFOLLOW) == 0) { + useattrs = 1; + islink = (attrs.type == VLNK); ++ dev = attrs.dev; ++ inode = attrs.id.fid_objno; + } else if (errno == EOPNOTSUPP || errno == EINVAL) { -+ if ((useattrs = lstat(resolved, &sb)) == 0) ++ 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) { @@ -78,11 +117,64 @@ 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[MNAMELEN]; ++ 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 @@ +@@ -155,6 +260,7 @@ + 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 +290,30 @@ } } left_len = strlcpy(left, symlink, sizeof(left));