| @@ -1,272 +1,17 @@ | | | @@ -1,272 +1,17 @@ |
1 | $NetBSD: patch-compat_fts.c,v 1.4 2015/03/26 14:16:12 sevan Exp $ | | 1 | $NetBSD: patch-compat_fts.c,v 1.5 2015/03/26 19:59:53 sevan Exp $ |
2 | | | 2 | |
3 | "We always use FTS_NOCHDIR, so delete the directory changing code. | | 3 | Fix build under Solaris 10. |
4 | This not only simplifies matters, but also helps operating systems | | | |
5 | lacking dirfd(3), for example Solaris 10." | | | |
6 | | | 4 | |
7 | --- compat_fts.c.orig 2015-03-26 04:03:30.000000000 +0000 | | 5 | --- compat_fts.c.orig 2015-03-13 12:38:38.000000000 +0000 |
8 | +++ compat_fts.c | | 6 | +++ compat_fts.c 2015-03-19 08:22:11.000000000 +0000 |
9 | @@ -60,7 +60,6 @@ static size_t fts_maxarglen(char * cons | | 7 | @@ -76,6 +76,10 @@ |
10 | static void fts_padjust(FTS *, FTSENT *); | | 8 | |
11 | static int fts_palloc(FTS *, size_t); | | 9 | #define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) |
12 | static unsigned short fts_stat(FTS *, FTSENT *); | | 10 | |
13 | -static int fts_safe_changedir(FTS *, FTSENT *, int, const char *); | | 11 | +#ifdef __sun__ |
14 | | | 12 | +#define dirfd(fd) ((fd)->dd_fd) |
15 | #define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) | | 13 | +#endif |
16 | #ifndef O_DIRECTORY | | 14 | + |
17 | @@ -74,8 +73,6 @@ static int fts_safe_changedir(FTS *, FT | | | |
18 | #define ISSET(opt) (sp->fts_options & (opt)) | | | |
19 | #define SET(opt) (sp->fts_options |= (opt)) | | | |
20 | | | | |
21 | -#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) | | | |
22 | - | | | |
23 | FTS * | | 15 | FTS * |
24 | fts_open(char * const *argv, int options, void *dummy) | | 16 | fts_open(char * const *argv, int options, void *dummy) |
25 | { | | 17 | { |
26 | @@ -146,17 +143,6 @@ fts_open(char * const *argv, int options | | | |
27 | sp->fts_cur->fts_link = root; | | | |
28 | sp->fts_cur->fts_info = FTS_INIT; | | | |
29 | | | | |
30 | - /* | | | |
31 | - * If using chdir(2), grab a file descriptor pointing to dot to ensure | | | |
32 | - * that we can get back here; this could be avoided for some paths, | | | |
33 | - * but almost certainly not worth the effort. Slashes, symbolic links, | | | |
34 | - * and ".." are all fairly nasty problems. Note, if we can't get the | | | |
35 | - * descriptor we run anyway, just more slowly. | | | |
36 | - */ | | | |
37 | - if (!ISSET(FTS_NOCHDIR) && | | | |
38 | - (sp->fts_rfd = open(".", O_RDONLY | O_CLOEXEC)) < 0) | | | |
39 | - SET(FTS_NOCHDIR); | | | |
40 | - | | | |
41 | if (nitems == 0) | | | |
42 | free(parent); | | | |
43 | | | | |
44 | @@ -213,25 +199,13 @@ fts_close(FTS *sp) | | | |
45 | free(p); | | | |
46 | } | | | |
47 | | | | |
48 | - /* Stash the original directory fd if needed. */ | | | |
49 | - rfd = ISSET(FTS_NOCHDIR) ? -1 : sp->fts_rfd; | | | |
50 | - | | | |
51 | /* Free up child linked list, sort array, path buffer, stream ptr.*/ | | | |
52 | if (sp->fts_child) | | | |
53 | fts_lfree(sp->fts_child); | | | |
54 | free(sp->fts_path); | | | |
55 | free(sp); | | | |
56 | | | | |
57 | - /* Return to original directory, checking for error. */ | | | |
58 | - if (rfd != -1) { | | | |
59 | - int saved_errno; | | | |
60 | - error = fchdir(rfd); | | | |
61 | - saved_errno = errno; | | | |
62 | - (void)close(rfd); | | | |
63 | - errno = saved_errno; | | | |
64 | - } | | | |
65 | - | | | |
66 | - return (error); | | | |
67 | + return (0); | | | |
68 | } | | | |
69 | | | | |
70 | /* | | | |
71 | @@ -274,25 +248,11 @@ fts_read(FTS *sp) | | | |
72 | } | | | |
73 | | | | |
74 | /* | | | |
75 | - * Cd to the subdirectory. | | | |
76 | - * | | | |
77 | - * If have already read and now fail to chdir, whack the list | | | |
78 | - * to make the names come out right, and set the parent errno | | | |
79 | - * so the application will eventually get an error condition. | | | |
80 | - * Set the FTS_DONTCHDIR flag so that when we logically change | | | |
81 | - * directories back to the parent we don't do a chdir. | | | |
82 | - * | | | |
83 | * If haven't read do so. If the read fails, fts_build sets | | | |
84 | * FTS_STOP or the fts_info field of the node. | | | |
85 | */ | | | |
86 | if (sp->fts_child) { | | | |
87 | - if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { | | | |
88 | - p->fts_errno = errno; | | | |
89 | - p->fts_flags |= FTS_DONTCHDIR; | | | |
90 | - for (p = sp->fts_child; p; p = p->fts_link) | | | |
91 | - p->fts_accpath = | | | |
92 | - p->fts_parent->fts_accpath; | | | |
93 | - } | | | |
94 | + /* nothing */ | | | |
95 | } else if ((sp->fts_child = fts_build(sp)) == NULL) { | | | |
96 | if (ISSET(FTS_STOP)) | | | |
97 | return (NULL); | | | |
98 | @@ -352,23 +312,6 @@ name: t = sp->fts_path + NAPPEND(p->fts | | | |
99 | /* NUL terminate the pathname. */ | | | |
100 | sp->fts_path[p->fts_pathlen] = '\0'; | | | |
101 | | | | |
102 | - /* | | | |
103 | - * Return to the parent directory. If at a root node or came through | | | |
104 | - * a symlink, go back through the file descriptor. Otherwise, cd up | | | |
105 | - * one directory. | | | |
106 | - */ | | | |
107 | - if (p->fts_level == FTS_ROOTLEVEL) { | | | |
108 | - if (FCHDIR(sp, sp->fts_rfd)) { | | | |
109 | - SET(FTS_STOP); | | | |
110 | - sp->fts_cur = p; | | | |
111 | - return (NULL); | | | |
112 | - } | | | |
113 | - } else if (!(p->fts_flags & FTS_DONTCHDIR) && | | | |
114 | - fts_safe_changedir(sp, p->fts_parent, -1, "..")) { | | | |
115 | - SET(FTS_STOP); | | | |
116 | - sp->fts_cur = p; | | | |
117 | - return (NULL); | | | |
118 | - } | | | |
119 | p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; | | | |
120 | return (sp->fts_cur = p); | | | |
121 | } | | | |
122 | @@ -432,32 +375,6 @@ fts_build(FTS *sp) | | | |
123 | } | | | |
124 | | | | |
125 | /* | | | |
126 | - * If we're going to need to stat anything or we want to descend | | | |
127 | - * and stay in the directory, chdir. If this fails we keep going, | | | |
128 | - * but set a flag so we don't chdir after the post-order visit. | | | |
129 | - * We won't be able to stat anything, but we can still return the | | | |
130 | - * names themselves. Note, that since fts_read won't be able to | | | |
131 | - * chdir into the directory, it will have to return different path | | | |
132 | - * names than before, i.e. "a/b" instead of "b". Since the node | | | |
133 | - * has already been visited in pre-order, have to wait until the | | | |
134 | - * post-order visit to return the error. There is a special case | | | |
135 | - * here, if there was nothing to stat then it's not an error to | | | |
136 | - * not be able to stat. This is all fairly nasty. If a program | | | |
137 | - * needed sorted entries or stat information, they had better be | | | |
138 | - * checking FTS_NS on the returned nodes. | | | |
139 | - */ | | | |
140 | - cderrno = 0; | | | |
141 | - if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { | | | |
142 | - cur->fts_errno = errno; | | | |
143 | - cur->fts_flags |= FTS_DONTCHDIR; | | | |
144 | - descend = 0; | | | |
145 | - cderrno = errno; | | | |
146 | - (void)closedir(dirp); | | | |
147 | - dirp = NULL; | | | |
148 | - } else | | | |
149 | - descend = 1; | | | |
150 | - | | | |
151 | - /* | | | |
152 | * Figure out the max file name length that can be stored in the | | | |
153 | * current path -- the inner loop allocates more path as necessary. | | | |
154 | * We really wouldn't have to do the maxlen calculations here, we | | | |
155 | @@ -468,10 +385,8 @@ fts_build(FTS *sp) | | | |
156 | * each new name into the path. | | | |
157 | */ | | | |
158 | len = NAPPEND(cur); | | | |
159 | - if (ISSET(FTS_NOCHDIR)) { | | | |
160 | - cp = sp->fts_path + len; | | | |
161 | - *cp++ = '/'; | | | |
162 | - } | | | |
163 | + cp = sp->fts_path + len; | | | |
164 | + *cp++ = '/'; | | | |
165 | len++; | | | |
166 | maxlen = sp->fts_pathlen - len; | | | |
167 | | | | |
168 | @@ -518,8 +433,7 @@ mem1: saved_errno = errno; | | | |
169 | /* Did realloc() change the pointer? */ | | | |
170 | if (oldaddr != sp->fts_path) { | | | |
171 | doadjust = 1; | | | |
172 | - if (ISSET(FTS_NOCHDIR)) | | | |
173 | - cp = sp->fts_path + len; | | | |
174 | + cp = sp->fts_path + len; | | | |
175 | } | | | |
176 | maxlen = sp->fts_pathlen - len; | | | |
177 | } | | | |
178 | @@ -542,20 +456,11 @@ mem1: saved_errno = errno; | | | |
179 | return (NULL); | | | |
180 | } | | | |
181 | | | | |
182 | - if (cderrno) { | | | |
183 | - p->fts_info = FTS_NS; | | | |
184 | - p->fts_errno = cderrno; | | | |
185 | - p->fts_accpath = cur->fts_accpath; | | | |
186 | - } else { | | | |
187 | - /* Build a file name for fts_stat to stat. */ | | | |
188 | - if (ISSET(FTS_NOCHDIR)) { | | | |
189 | - p->fts_accpath = p->fts_path; | | | |
190 | - memmove(cp, p->fts_name, p->fts_namelen + 1); | | | |
191 | - } else | | | |
192 | - p->fts_accpath = p->fts_name; | | | |
193 | - /* Stat it. */ | | | |
194 | - p->fts_info = fts_stat(sp, p); | | | |
195 | - } | | | |
196 | + /* Build a file name for fts_stat to stat. */ | | | |
197 | + p->fts_accpath = p->fts_path; | | | |
198 | + memmove(cp, p->fts_name, p->fts_namelen + 1); | | | |
199 | + /* Stat it. */ | | | |
200 | + p->fts_info = fts_stat(sp, p); | | | |
201 | | | | |
202 | /* We walk in directory order so "ls -f" doesn't get upset. */ | | | |
203 | p->fts_link = NULL; | | | |
204 | @@ -581,26 +486,9 @@ mem1: saved_errno = errno; | | | |
205 | * If not changing directories, reset the path back to original | | | |
206 | * state. | | | |
207 | */ | | | |
208 | - if (ISSET(FTS_NOCHDIR)) { | | | |
209 | - if (len == sp->fts_pathlen || nitems == 0) | | | |
210 | - --cp; | | | |
211 | - *cp = '\0'; | | | |
212 | - } | | | |
213 | - | | | |
214 | - /* | | | |
215 | - * If descended after called from fts_children or after called from | | | |
216 | - * fts_read and nothing found, get back. At the root level we use | | | |
217 | - * the saved fd; if one of fts_open()'s arguments is a relative path | | | |
218 | - * to an empty directory, we wind up here with no other way back. If | | | |
219 | - * can't get back, we're done. | | | |
220 | - */ | | | |
221 | - if (descend && !nitems && | | | |
222 | - (cur->fts_level == FTS_ROOTLEVEL ? FCHDIR(sp, sp->fts_rfd) : | | | |
223 | - fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { | | | |
224 | - cur->fts_info = FTS_ERR; | | | |
225 | - SET(FTS_STOP); | | | |
226 | - return (NULL); | | | |
227 | - } | | | |
228 | + if (len == sp->fts_pathlen || nitems == 0) | | | |
229 | + --cp; | | | |
230 | + *cp = '\0'; | | | |
231 | | | | |
232 | /* If didn't find anything, return NULL. */ | | | |
233 | if (!nitems) { | | | |
234 | @@ -771,38 +659,4 @@ fts_maxarglen(char * const *argv) | | | |
235 | return (max + 1); | | | |
236 | } | | | |
237 | | | | |
238 | -/* | | | |
239 | - * Change to dir specified by fd or p->fts_accpath without getting | | | |
240 | - * tricked by someone changing the world out from underneath us. | | | |
241 | - * Assumes p->fts_dev and p->fts_ino are filled in. | | | |
242 | - */ | | | |
243 | -static int | | | |
244 | -fts_safe_changedir(FTS *sp, FTSENT *p, int fd, const char *path) | | | |
245 | -{ | | | |
246 | - int ret, oerrno, newfd; | | | |
247 | - struct stat sb; | | | |
248 | - | | | |
249 | - newfd = fd; | | | |
250 | - if (ISSET(FTS_NOCHDIR)) | | | |
251 | - return (0); | | | |
252 | - if (fd < 0 && (newfd = open(path, O_RDONLY|O_DIRECTORY|O_CLOEXEC)) < 0) | | | |
253 | - return (-1); | | | |
254 | - if (fstat(newfd, &sb)) { | | | |
255 | - ret = -1; | | | |
256 | - goto bail; | | | |
257 | - } | | | |
258 | - if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) { | | | |
259 | - errno = ENOENT; /* disinformation */ | | | |
260 | - ret = -1; | | | |
261 | - goto bail; | | | |
262 | - } | | | |
263 | - ret = fchdir(newfd); | | | |
264 | -bail: | | | |
265 | - oerrno = errno; | | | |
266 | - if (fd < 0) | | | |
267 | - (void)close(newfd); | | | |
268 | - errno = oerrno; | | | |
269 | - return (ret); | | | |
270 | -} | | | |
271 | - | | | |
272 | #endif | | | |