]> git.saurik.com Git - apple/libc.git/blob - stdlib/FreeBSD/realpath.c.patch
603dc2b340f6a218aa7c9162a3e48665a6720264
[apple/libc.git] / stdlib / FreeBSD / realpath.c.patch
1 --- realpath.c.orig Fri Aug 15 19:22:17 2003
2 +++ realpath.c Tue Dec 9 14:36:32 2003
3 @@ -40,8 +40,27 @@
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 +#include <sys/attr.h>
8 +#include <sys/vnode.h>
9 #include "un-namespace.h"
10
11 +struct attrs {
12 + u_int32_t len;
13 + attrreference_t name;
14 + fsobj_type_t type;
15 + char buf[PATH_MAX];
16 +};
17 +
18 +static struct attrlist alist = {
19 + ATTR_BIT_MAP_COUNT,
20 + 0,
21 + ATTR_CMN_NAME | ATTR_CMN_OBJTYPE,
22 + 0,
23 + 0,
24 + 0,
25 + 0,
26 +};
27 +
28 /*
29 * char *realpath(const char *path, char resolved[PATH_MAX]);
30 *
31 @@ -52,11 +71,12 @@
32 char *
33 realpath(const char *path, char resolved[PATH_MAX])
34 {
35 + struct attrs attrs;
36 struct stat sb;
37 char *p, *q, *s;
38 - size_t left_len, resolved_len;
39 + size_t left_len, resolved_len, save_resolved_len;
40 unsigned symlinks;
41 - int serrno, slen;
42 + int serrno, slen, useattrs, islink;
43 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
44
45 serrno = errno;
46 @@ -127,6 +147,13 @@
47 }
48
49 /*
50 + * Save resolved_len, so that we can later null out
51 + * the the appended next_token, and replace with the
52 + * real name (matters on case-insensitive filesystems).
53 + */
54 + save_resolved_len = resolved_len;
55 +
56 + /*
57 * Append the next path component and lstat() it. If
58 * lstat() fails we still can return successfully if
59 * there are no more path components left.
60 @@ -136,14 +163,22 @@
61 errno = ENAMETOOLONG;
62 return (NULL);
63 }
64 - if (lstat(resolved, &sb) != 0) {
65 + if (getattrlist(resolved, &alist, &attrs, sizeof(attrs), FSOPT_NOFOLLOW) == 0) {
66 + useattrs = 1;
67 + islink = (attrs.type == VLNK);
68 + } else if (errno == EOPNOTSUPP || errno == EINVAL) {
69 + if ((useattrs = lstat(resolved, &sb)) == 0)
70 + islink = S_ISLNK(sb.st_mode);
71 + } else
72 + useattrs = -1;
73 + if (useattrs < 0) {
74 if (errno == ENOENT && p == NULL) {
75 errno = serrno;
76 return (resolved);
77 }
78 return (NULL);
79 }
80 - if (S_ISLNK(sb.st_mode)) {
81 + if (islink) {
82 if (symlinks++ > MAXSYMLINKS) {
83 errno = ELOOP;
84 return (NULL);
85 @@ -184,7 +219,30 @@
86 }
87 }
88 left_len = strlcpy(left, symlink, sizeof(left));
89 + } else if (useattrs) {
90 + /*
91 + * attrs already has the real name.
92 + */
93 +
94 + resolved[save_resolved_len] = '\0';
95 + resolved_len = strlcat(resolved, (const char *)&attrs.name + attrs.name.attr_dataoffset, PATH_MAX);
96 + if (resolved_len >= PATH_MAX) {
97 + errno = ENAMETOOLONG;
98 + return (NULL);
99 + }
100 }
101 + /*
102 + * For the case of useattrs == 0, we could scan the directory
103 + * and try to match the inode. There are many problems with
104 + * this: (1) the directory may not be readable, (2) for multiple
105 + * hard links, we would find the first, but not necessarily
106 + * the one specified in the path, (3) we can't try to do
107 + * a case-insensitive search to match the right one in (2),
108 + * because the underlying filesystem may do things like
109 + * decompose composed characters. For most cases, doing
110 + * nothing is the right thing when useattrs == 0, so we punt
111 + * for now.
112 + */
113 }
114
115 /*