summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/recipes-core/fts/fts.bb36
-rw-r--r--meta/recipes-core/fts/fts/fts-header-correctness.patch25
-rw-r--r--meta/recipes-core/fts/fts/fts-uclibc.patch50
-rw-r--r--meta/recipes-core/fts/fts/gcc5.patch1368
-rw-r--r--meta/recipes-core/fts/fts/remove_cdefs.patch69
-rw-r--r--meta/recipes-core/fts/fts/stdint.patch15
6 files changed, 8 insertions, 1555 deletions
diff --git a/meta/recipes-core/fts/fts.bb b/meta/recipes-core/fts/fts.bb
index de9297ebed..02f54086a3 100644
--- a/meta/recipes-core/fts/fts.bb
+++ b/meta/recipes-core/fts/fts.bb
@@ -3,38 +3,18 @@
3 3
4SUMMARY = "POSIX file tree stream operations library" 4SUMMARY = "POSIX file tree stream operations library"
5HOMEPAGE = "https://sites.google.com/a/bostic.com/keithbostic" 5HOMEPAGE = "https://sites.google.com/a/bostic.com/keithbostic"
6LICENSE = "BSD-4-Clause" 6LICENSE = "BSD-3-Clause"
7LIC_FILES_CHKSUM = "file://fts.h;beginline=1;endline=36;md5=2532eddb3d1a21905723a4011ec4e085" 7LIC_FILES_CHKSUM = "file://COPYING;md5=5ffe358174aad383f1b69ce3b53da982"
8SECTION = "libs" 8SECTION = "libs"
9 9
10SRC_URI = "https://sites.google.com/a/bostic.com/keithbostic/files/fts.tar.gz \ 10SRCREV = "944333aed9dc24cfa76cc64bfe70c75d25652753"
11 file://fts-header-correctness.patch \ 11PV = "1.2+git${SRCPV}"
12 file://fts-uclibc.patch \
13 file://remove_cdefs.patch \
14 file://stdint.patch \
15 file://gcc5.patch \
16"
17
18SRC_URI[md5sum] = "120c14715485ec6ced14f494d059d20a"
19SRC_URI[sha256sum] = "3df9b9b5a45aeaf16f33bb84e692a10dc662e22ec8a51748f98767d67fb6f342"
20
21S = "${WORKDIR}/${BPN}"
22 12
23do_configure[noexec] = "1" 13SRC_URI = "git://github.com/voidlinux/musl-fts \
24 14"
25HASHSTYLE_mipsarch = "sysv" 15S = "${WORKDIR}/git"
26HASHSTYLE = "gnu"
27
28VER = "0"
29do_compile () {
30 ${CC} -I${S} -fPIC -shared -Wl,--hash-style=${HASHSTYLE} -o libfts.so.${VER} -Wl,-soname,libfts.so.${VER} ${S}/fts.c
31}
32 16
33do_install() { 17inherit autotools pkgconfig
34 install -Dm755 ${B}/libfts.so.${VER} ${D}${libdir}/libfts.so.${VER}
35 ln -sf libfts.so.${VER} ${D}${libdir}/libfts.so
36 install -Dm644 ${S}/fts.h ${D}${includedir}/fts.h
37}
38# 18#
39# We will skip parsing for non-musl systems 19# We will skip parsing for non-musl systems
40# 20#
diff --git a/meta/recipes-core/fts/fts/fts-header-correctness.patch b/meta/recipes-core/fts/fts/fts-header-correctness.patch
deleted file mode 100644
index c73ddc95d8..0000000000
--- a/meta/recipes-core/fts/fts/fts-header-correctness.patch
+++ /dev/null
@@ -1,25 +0,0 @@
1Included needed headers for compiling with musl
2
3Signed-off-by: Khem Raj <raj.khem@gmail.com>
4Upstream-Status: Inappropriate
5
6--- fts.orig/fts.h
7+++ fts/fts.h
8@@ -38,6 +38,17 @@
9 #ifndef _FTS_H_
10 #define _FTS_H_
11
12+#include <sys/types.h>
13+#include <sys/param.h>
14+#include <sys/stat.h>
15+
16+#include <dirent.h>
17+#include <errno.h>
18+#include <fcntl.h>
19+#include <stdlib.h>
20+#include <string.h>
21+#include <unistd.h>
22+
23 typedef struct {
24 struct _ftsent *fts_cur; /* current node */
25 struct _ftsent *fts_child; /* linked list of children */
diff --git a/meta/recipes-core/fts/fts/fts-uclibc.patch b/meta/recipes-core/fts/fts/fts-uclibc.patch
deleted file mode 100644
index 397654bf51..0000000000
--- a/meta/recipes-core/fts/fts/fts-uclibc.patch
+++ /dev/null
@@ -1,50 +0,0 @@
1Add missing defines for uclibc
2
3Signed-off-by: Khem Raj <raj.khem@gmail.com>
4Upstream-Status: Inappropriate
5
6--- fts.orig/fts.c
7+++ fts/fts.c
8@@ -31,6 +31,10 @@
9 * SUCH DAMAGE.
10 */
11
12+#define alignof(TYPE) ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
13+#define ALIGNBYTES (alignof(long double) - 1)
14+#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES)
15+
16 #if defined(LIBC_SCCS) && !defined(lint)
17 static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
18 #endif /* LIBC_SCCS and not lint */
19@@ -652,10 +656,10 @@
20 if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
21 continue;
22
23- if ((p = fts_alloc(sp, dp->d_name, (int)dp->d_namlen)) == NULL)
24+ if ((p = fts_alloc(sp, dp->d_name, (int)dp->d_reclen)) == NULL)
25 goto mem1;
26- if (dp->d_namlen > maxlen) {
27- if (fts_palloc(sp, (size_t)dp->d_namlen)) {
28+ if (dp->d_reclen > maxlen) {
29+ if (fts_palloc(sp, (size_t)dp->d_reclen)) {
30 /*
31 * No more memory for path or structures. Save
32 * errno, free up the current structure and the
33@@ -675,7 +679,7 @@
34 maxlen = sp->fts_pathlen - sp->fts_cur->fts_pathlen - 1;
35 }
36
37- p->fts_pathlen = len + dp->d_namlen + 1;
38+ p->fts_pathlen = len + dp->d_reclen + 1;
39 p->fts_parent = sp->fts_cur;
40 p->fts_level = level;
41
42@@ -784,7 +788,7 @@
43 /* If user needs stat info, stat buffer already allocated. */
44 sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
45
46-#ifdef DT_WHT
47+#ifdef S_IFWHT
48 /*
49 * Whited-out files don't really exist. However, there's stat(2) file
50 * mask for them, so we set it so that programs (i.e., find) don't have
diff --git a/meta/recipes-core/fts/fts/gcc5.patch b/meta/recipes-core/fts/fts/gcc5.patch
deleted file mode 100644
index f5b948edc0..0000000000
--- a/meta/recipes-core/fts/fts/gcc5.patch
+++ /dev/null
@@ -1,1368 +0,0 @@
1Forward port the sources to be able to compile with c99/gcc5
2
3Signed-off-by: Khem Raj <raj.khem@gmail.com>
4Upstream-Status: Inappropriate
5
6Index: fts/fts.c
7===================================================================
8--- fts.orig/fts.c
9+++ fts/fts.c
10@@ -51,16 +51,6 @@ static char sccsid[] = "@(#)fts.c 8.6 (B
11 #include <string.h>
12 #include <unistd.h>
13
14-static FTSENT *fts_alloc __P(FTS *, char *, int);
15-static FTSENT *fts_build __P(FTS *, int);
16-static void fts_lfree __P(FTSENT *);
17-static void fts_load __P(FTS *, FTSENT *);
18-static size_t fts_maxarglen __P(char * const *);
19-static void fts_padjust __P(FTS *, void *);
20-static int fts_palloc __P(FTS *, size_t);
21-static FTSENT *fts_sort __P(FTS *, FTSENT *, int);
22-static u_short fts_stat __P(FTS *, struct dirent *, FTSENT *, int);
23-
24 #define ISDOT(a) (a[0] == '.' && (!a[1] || a[1] == '.' && !a[2]))
25
26 #define ISSET(opt) (sp->fts_options & opt)
27@@ -73,119 +63,16 @@ static u_short fts_stat __P(FTS *, stru
28 #define BCHILD 1 /* fts_children */
29 #define BNAMES 2 /* fts_children, names only */
30 #define BREAD 3 /* fts_read */
31-
32-FTS *
33-fts_open(argv, options, compar)
34- char * const *argv;
35- register int options;
36- int (*compar)();
37-{
38- register FTS *sp;
39- register FTSENT *p, *root;
40- register int nitems;
41- FTSENT *parent, *tmp;
42- int len;
43-
44- /* Options check. */
45- if (options & ~FTS_OPTIONMASK) {
46- errno = EINVAL;
47- return (NULL);
48- }
49-
50- /* Allocate/initialize the stream */
51- if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
52- return (NULL);
53- memset(sp, 0, sizeof(FTS));
54- sp->fts_compar = compar;
55- sp->fts_options = options;
56-
57- /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
58- if (ISSET(FTS_LOGICAL))
59- SET(FTS_NOCHDIR);
60-
61- /*
62- * Start out with 1K of path space, and enough, in any case,
63- * to hold the user's paths.
64- */
65- if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
66- goto mem1;
67-
68- /* Allocate/initialize root's parent. */
69- if ((parent = fts_alloc(sp, "", 0)) == NULL)
70- goto mem2;
71- parent->fts_level = FTS_ROOTPARENTLEVEL;
72-
73- /* Allocate/initialize root(s). */
74- for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
75- /* Don't allow zero-length paths. */
76- if ((len = strlen(*argv)) == 0) {
77- errno = EINVAL;
78- goto mem3;
79- }
80-
81- p = fts_alloc(sp, *argv, len);
82- p->fts_level = FTS_ROOTLEVEL;
83- p->fts_parent = parent;
84- p->fts_accpath = p->fts_name;
85- p->fts_info = fts_stat(sp, NULL, p, ISSET(FTS_COMFOLLOW));
86-
87- /* Command-line "." and ".." are real directories. */
88- if (p->fts_info == FTS_DOT)
89- p->fts_info = FTS_D;
90-
91- /*
92- * If comparison routine supplied, traverse in sorted
93- * order; otherwise traverse in the order specified.
94- */
95- if (compar) {
96- p->fts_link = root;
97- root = p;
98- } else {
99- p->fts_link = NULL;
100- if (root == NULL)
101- tmp = root = p;
102- else {
103- tmp->fts_link = p;
104- tmp = p;
105- }
106- }
107- }
108- if (compar && nitems > 1)
109- root = fts_sort(sp, root, nitems);
110-
111- /*
112- * Allocate a dummy pointer and make fts_read think that we've just
113- * finished the node before the root(s); set p->fts_info to FTS_INIT
114- * so that everything about the "current" node is ignored.
115- */
116- if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
117- goto mem3;
118- sp->fts_cur->fts_link = root;
119- sp->fts_cur->fts_info = FTS_INIT;
120-
121- /*
122- * If using chdir(2), grab a file descriptor pointing to dot to insure
123- * that we can get back here; this could be avoided for some paths,
124- * but almost certainly not worth the effort. Slashes, symbolic links,
125- * and ".." are all fairly nasty problems. Note, if we can't get the
126- * descriptor we run anyway, just more slowly.
127- */
128- if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0)
129- SET(FTS_NOCHDIR);
130-
131- return (sp);
132-
133-mem3: fts_lfree(root);
134- free(parent);
135-mem2: free(sp->fts_path);
136-mem1: free(sp);
137- return (NULL);
138-}
139+/*
140+ * Special case a root of "/" so that slashes aren't appended which would
141+ * cause paths to be written as "//foo".
142+ */
143+#define NAPPEND(p) \
144+ (p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 && \
145+ p->fts_path[0] == '/' ? 0 : p->fts_pathlen)
146
147 static void
148-fts_load(sp, p)
149- FTS *sp;
150- register FTSENT *p;
151+fts_load(FTS *sp, register FTSENT *p)
152 {
153 register int len;
154 register char *cp;
155@@ -208,332 +95,214 @@ fts_load(sp, p)
156 sp->fts_dev = p->fts_dev;
157 }
158
159-int
160-fts_close(sp)
161- FTS *sp;
162+static void
163+fts_lfree(register FTSENT *head)
164 {
165- register FTSENT *freep, *p;
166- int saved_errno;
167+ register FTSENT *p;
168
169- /*
170- * This still works if we haven't read anything -- the dummy structure
171- * points to the root list, so we step through to the end of the root
172- * list which has a valid parent pointer.
173- */
174- if (sp->fts_cur) {
175- for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
176- freep = p;
177- p = p->fts_link ? p->fts_link : p->fts_parent;
178- free(freep);
179- }
180+ /* Free a linked list of structures. */
181+ while (p = head) {
182+ head = head->fts_link;
183 free(p);
184 }
185+}
186
187- /* Free up child linked list, sort array, path buffer. */
188- if (sp->fts_child)
189- fts_lfree(sp->fts_child);
190- if (sp->fts_array)
191- free(sp->fts_array);
192- free(sp->fts_path);
193+static size_t
194+fts_maxarglen(char * const *argv)
195+{
196+ size_t len, max;
197
198- /* Return to original directory, save errno if necessary. */
199- if (!ISSET(FTS_NOCHDIR)) {
200- saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
201- (void)close(sp->fts_rfd);
202- }
203+ for (max = 0; *argv; ++argv)
204+ if ((len = strlen(*argv)) > max)
205+ max = len;
206+ return (max);
207+}
208
209- /* Free up the stream pointer. */
210- free(sp);
211
212- /* Set errno and return. */
213- if (!ISSET(FTS_NOCHDIR) && saved_errno) {
214- errno = saved_errno;
215- return (-1);
216+/*
217+ * When the path is realloc'd, have to fix all of the pointers in structures
218+ * already returned.
219+ */
220+static void
221+fts_padjust(FTS *sp, void *addr)
222+{
223+ FTSENT *p;
224+
225+#define ADJUST(p) { \
226+ (p)->fts_accpath = \
227+ (char *)addr + ((p)->fts_accpath - (p)->fts_path); \
228+ (p)->fts_path = addr; \
229+}
230+ /* Adjust the current set of children. */
231+ for (p = sp->fts_child; p; p = p->fts_link)
232+ ADJUST(p);
233+
234+ /* Adjust the rest of the tree. */
235+ for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
236+ ADJUST(p);
237+ p = p->fts_link ? p->fts_link : p->fts_parent;
238 }
239- return (0);
240 }
241
242 /*
243- * Special case a root of "/" so that slashes aren't appended which would
244- * cause paths to be written as "//foo".
245+ * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
246+ * Most systems will allow creation of paths much longer than MAXPATHLEN, even
247+ * though the kernel won't resolve them. Add the size (not just what's needed)
248+ * plus 256 bytes so don't realloc the path 2 bytes at a time.
249 */
250-#define NAPPEND(p) \
251- (p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 && \
252- p->fts_path[0] == '/' ? 0 : p->fts_pathlen)
253+static int
254+fts_palloc(FTS *sp, size_t more)
255+{
256+ sp->fts_pathlen += more + 256;
257+ sp->fts_path = realloc(sp->fts_path, (size_t)sp->fts_pathlen);
258+ return (sp->fts_path == NULL);
259+}
260
261-FTSENT *
262-fts_read(sp)
263- register FTS *sp;
264+static FTSENT *
265+fts_alloc(FTS *sp, char *name, register int namelen)
266 {
267- register FTSENT *p, *tmp;
268- register int instr;
269- register char *t;
270- int saved_errno;
271+ register FTSENT *p;
272+ size_t len;
273
274- /* If finished or unrecoverable error, return NULL. */
275- if (sp->fts_cur == NULL || ISSET(FTS_STOP))
276+ /*
277+ * The file name is a variable length array and no stat structure is
278+ * necessary if the user has set the nostat bit. Allocate the FTSENT
279+ * structure, the file name and the stat structure in one chunk, but
280+ * be careful that the stat structure is reasonably aligned. Since the
281+ * fts_name field is declared to be of size 1, the fts_name pointer is
282+ * namelen + 2 before the first possible address of the stat structure.
283+ */
284+ len = sizeof(FTSENT) + namelen;
285+ if (!ISSET(FTS_NOSTAT))
286+ len += sizeof(struct stat) + ALIGNBYTES;
287+ if ((p = malloc(len)) == NULL)
288 return (NULL);
289
290- /* Set current node pointer. */
291- p = sp->fts_cur;
292+ /* Copy the name plus the trailing NULL. */
293+ memmove(p->fts_name, name, namelen + 1);
294
295- /* Save and zero out user instructions. */
296- instr = p->fts_instr;
297+ if (!ISSET(FTS_NOSTAT))
298+ p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
299+ p->fts_namelen = namelen;
300+ p->fts_path = sp->fts_path;
301+ p->fts_errno = 0;
302+ p->fts_flags = 0;
303 p->fts_instr = FTS_NOINSTR;
304+ p->fts_number = 0;
305+ p->fts_pointer = NULL;
306+ return (p);
307+}
308
309- /* Any type of file may be re-visited; re-stat and re-turn. */
310- if (instr == FTS_AGAIN) {
311- p->fts_info = fts_stat(sp, NULL, p, 0);
312- return (p);
313- }
314
315+static u_short
316+fts_stat(FTS *sp, register FTSENT *p, struct dirent *dp, int follow)
317+{
318+ register FTSENT *t;
319+ register dev_t dev;
320+ register ino_t ino;
321+ struct stat *sbp, sb;
322+ int saved_errno;
323+
324+ /* If user needs stat info, stat buffer already allocated. */
325+ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
326+
327+#ifdef S_IFWHT
328 /*
329- * Following a symlink -- SLNONE test allows application to see
330- * SLNONE and recover. If indirecting through a symlink, have
331- * keep a pointer to current location. If unable to get that
332- * pointer, follow fails.
333- */
334- if (instr == FTS_FOLLOW &&
335- (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
336- p->fts_info = fts_stat(sp, NULL, p, 1);
337- if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR))
338- if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) {
339- p->fts_errno = errno;
340- p->fts_info = FTS_ERR;
341- } else
342- p->fts_flags |= FTS_SYMFOLLOW;
343- return (p);
344+ * Whited-out files don't really exist. However, there's stat(2) file
345+ * mask for them, so we set it so that programs (i.e., find) don't have
346+ * to test FTS_W separately from other file types.
347+ */
348+ if (dp != NULL && dp->d_type == DT_WHT) {
349+ memset(sbp, 0, sizeof(struct stat));
350+ sbp->st_mode = S_IFWHT;
351+ return (FTS_W);
352 }
353-
354- /* Directory in pre-order. */
355- if (p->fts_info == FTS_D) {
356- /* If skipped or crossed mount point, do post-order visit. */
357- if (instr == FTS_SKIP ||
358- ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev) {
359- if (p->fts_flags & FTS_SYMFOLLOW)
360- (void)close(p->fts_symfd);
361- if (sp->fts_child) {
362- fts_lfree(sp->fts_child);
363- sp->fts_child = NULL;
364- }
365- p->fts_info = FTS_DP;
366- return (p);
367- }
368-
369- /* Rebuild if only read the names and now traversing. */
370- if (sp->fts_child && sp->fts_options & FTS_NAMEONLY) {
371- sp->fts_options &= ~FTS_NAMEONLY;
372- fts_lfree(sp->fts_child);
373- sp->fts_child = NULL;
374- }
375-
376- /*
377- * Cd to the subdirectory.
378- *
379- * If have already read and now fail to chdir, whack the list
380- * to make the names come out right, and set the parent errno
381- * so the application will eventually get an error condition.
382- * Set the FTS_DONTCHDIR flag so that when we logically change
383- * directories back to the parent we don't do a chdir.
384- *
385- * If haven't read do so. If the read fails, fts_build sets
386- * FTS_STOP or the fts_info field of the node.
387- */
388- if (sp->fts_child) {
389- if (CHDIR(sp, p->fts_accpath)) {
390- p->fts_errno = errno;
391- p->fts_flags |= FTS_DONTCHDIR;
392- for (p = sp->fts_child; p; p = p->fts_link)
393- p->fts_accpath =
394- p->fts_parent->fts_accpath;
395- }
396- } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
397- if (ISSET(FTS_STOP))
398- return (NULL);
399- return (p);
400+#endif
401+
402+ /*
403+ * If doing a logical walk, or application requested FTS_FOLLOW, do
404+ * a stat(2). If that fails, check for a non-existent symlink. If
405+ * fail, set the errno from the stat call.
406+ */
407+ if (ISSET(FTS_LOGICAL) || follow) {
408+ if (stat(p->fts_accpath, sbp)) {
409+ saved_errno = errno;
410+ if (!lstat(p->fts_accpath, sbp)) {
411+ errno = 0;
412+ return (FTS_SLNONE);
413+ }
414+ p->fts_errno = saved_errno;
415+ goto err;
416 }
417- p = sp->fts_child;
418- sp->fts_child = NULL;
419- goto name;
420+ } else if (lstat(p->fts_accpath, sbp)) {
421+ p->fts_errno = errno;
422+err: memset(sbp, 0, sizeof(struct stat));
423+ return (FTS_NS);
424 }
425
426- /* Move to the next node on this level. */
427-next: tmp = p;
428- if (p = p->fts_link) {
429- free(tmp);
430-
431- /*
432- * If reached the top, return to the original directory, and
433- * load the paths for the next root.
434- */
435- if (p->fts_level == FTS_ROOTLEVEL) {
436- if (!ISSET(FTS_NOCHDIR) && FCHDIR(sp, sp->fts_rfd)) {
437- SET(FTS_STOP);
438- return (NULL);
439- }
440- fts_load(sp, p);
441- return (sp->fts_cur = p);
442- }
443-
444+ if (S_ISDIR(sbp->st_mode)) {
445 /*
446- * User may have called fts_set on the node. If skipped,
447- * ignore. If followed, get a file descriptor so we can
448- * get back if necessary.
449+ * Set the device/inode. Used to find cycles and check for
450+ * crossing mount points. Also remember the link count, used
451+ * in fts_build to limit the number of stat calls. It is
452+ * understood that these fields are only referenced if fts_info
453+ * is set to FTS_D.
454 */
455- if (p->fts_instr == FTS_SKIP)
456- goto next;
457- if (p->fts_instr == FTS_FOLLOW) {
458- p->fts_info = fts_stat(sp, NULL, p, 1);
459- if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR))
460- if ((p->fts_symfd =
461- open(".", O_RDONLY, 0)) < 0) {
462- p->fts_errno = errno;
463- p->fts_info = FTS_ERR;
464- } else
465- p->fts_flags |= FTS_SYMFOLLOW;
466- p->fts_instr = FTS_NOINSTR;
467- }
468-
469-name: t = sp->fts_path + NAPPEND(p->fts_parent);
470- *t++ = '/';
471- memmove(t, p->fts_name, p->fts_namelen + 1);
472- return (sp->fts_cur = p);
473- }
474+ dev = p->fts_dev = sbp->st_dev;
475+ ino = p->fts_ino = sbp->st_ino;
476+ p->fts_nlink = sbp->st_nlink;
477
478- /* Move up to the parent node. */
479- p = tmp->fts_parent;
480- free(tmp);
481+ if (ISDOT(p->fts_name))
482+ return (FTS_DOT);
483
484- if (p->fts_level == FTS_ROOTPARENTLEVEL) {
485 /*
486- * Done; free everything up and set errno to 0 so the user
487- * can distinguish between error and EOF.
488+ * Cycle detection is done by brute force when the directory
489+ * is first encountered. If the tree gets deep enough or the
490+ * number of symbolic links to directories is high enough,
491+ * something faster might be worthwhile.
492 */
493- free(p);
494- errno = 0;
495- return (sp->fts_cur = NULL);
496- }
497-
498- /* Nul terminate the pathname. */
499- sp->fts_path[p->fts_pathlen] = '\0';
500-
501- /*
502- * Return to the parent directory. If at a root node or came through
503- * a symlink, go back through the file descriptor. Otherwise, cd up
504- * one directory.
505- */
506- if (p->fts_level == FTS_ROOTLEVEL) {
507- if (!ISSET(FTS_NOCHDIR) && FCHDIR(sp, sp->fts_rfd)) {
508- SET(FTS_STOP);
509- return (NULL);
510- }
511- } else if (p->fts_flags & FTS_SYMFOLLOW) {
512- if (FCHDIR(sp, p->fts_symfd)) {
513- saved_errno = errno;
514- (void)close(p->fts_symfd);
515- errno = saved_errno;
516- SET(FTS_STOP);
517- return (NULL);
518- }
519- (void)close(p->fts_symfd);
520- } else if (!(p->fts_flags & FTS_DONTCHDIR)) {
521- if (CHDIR(sp, "..")) {
522- SET(FTS_STOP);
523- return (NULL);
524- }
525- }
526- p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
527- return (sp->fts_cur = p);
528-}
529-
530-/*
531- * Fts_set takes the stream as an argument although it's not used in this
532- * implementation; it would be necessary if anyone wanted to add global
533- * semantics to fts using fts_set. An error return is allowed for similar
534- * reasons.
535- */
536-/* ARGSUSED */
537-int
538-fts_set(sp, p, instr)
539- FTS *sp;
540- FTSENT *p;
541- int instr;
542-{
543- if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
544- instr != FTS_NOINSTR && instr != FTS_SKIP) {
545- errno = EINVAL;
546- return (1);
547+ for (t = p->fts_parent;
548+ t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
549+ if (ino == t->fts_ino && dev == t->fts_dev) {
550+ p->fts_cycle = t;
551+ return (FTS_DC);
552+ }
553+ return (FTS_D);
554 }
555- p->fts_instr = instr;
556- return (0);
557+ if (S_ISLNK(sbp->st_mode))
558+ return (FTS_SL);
559+ if (S_ISREG(sbp->st_mode))
560+ return (FTS_F);
561+ return (FTS_DEFAULT);
562 }
563
564-FTSENT *
565-fts_children(sp, instr)
566- register FTS *sp;
567- int instr;
568+static FTSENT *
569+fts_sort(FTS *sp, FTSENT *head, register int nitems)
570 {
571- register FTSENT *p;
572- int fd;
573-
574- if (instr && instr != FTS_NAMEONLY) {
575- errno = EINVAL;
576- return (NULL);
577- }
578-
579- /* Set current node pointer. */
580- p = sp->fts_cur;
581-
582- /*
583- * Errno set to 0 so user can distinguish empty directory from
584- * an error.
585- */
586- errno = 0;
587-
588- /* Fatal errors stop here. */
589- if (ISSET(FTS_STOP))
590- return (NULL);
591-
592- /* Return logical hierarchy of user's arguments. */
593- if (p->fts_info == FTS_INIT)
594- return (p->fts_link);
595-
596- /*
597- * If not a directory being visited in pre-order, stop here. Could
598- * allow FTS_DNR, assuming the user has fixed the problem, but the
599- * same effect is available with FTS_AGAIN.
600- */
601- if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
602- return (NULL);
603-
604- /* Free up any previous child list. */
605- if (sp->fts_child)
606- fts_lfree(sp->fts_child);
607-
608- if (instr == FTS_NAMEONLY) {
609- sp->fts_options |= FTS_NAMEONLY;
610- instr = BNAMES;
611- } else
612- instr = BCHILD;
613+ register FTSENT **ap, *p;
614
615 /*
616- * If using chdir on a relative path and called BEFORE fts_read does
617- * its chdir to the root of a traversal, we can lose -- we need to
618- * chdir into the subdirectory, and we don't know where the current
619- * directory is, so we can't get back so that the upcoming chdir by
620- * fts_read will work.
621+ * Construct an array of pointers to the structures and call qsort(3).
622+ * Reassemble the array in the order returned by qsort. If unable to
623+ * sort for memory reasons, return the directory entries in their
624+ * current order. Allocate enough space for the current needs plus
625+ * 40 so don't realloc one entry at a time.
626 */
627- if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
628- ISSET(FTS_NOCHDIR))
629- return (sp->fts_child = fts_build(sp, instr));
630-
631- if ((fd = open(".", O_RDONLY, 0)) < 0)
632- return (NULL);
633- sp->fts_child = fts_build(sp, instr);
634- if (fchdir(fd))
635- return (NULL);
636- (void)close(fd);
637- return (sp->fts_child);
638+ if (nitems > sp->fts_nitems) {
639+ sp->fts_nitems = nitems + 40;
640+ if ((sp->fts_array = realloc(sp->fts_array,
641+ (size_t)(sp->fts_nitems * sizeof(FTSENT *)))) == NULL) {
642+ sp->fts_nitems = 0;
643+ return (head);
644+ }
645+ }
646+ for (ap = sp->fts_array, p = head; p; p = p->fts_link)
647+ *ap++ = p;
648+ qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
649+ for (head = *(ap = sp->fts_array); --nitems; ++ap)
650+ ap[0]->fts_link = ap[1];
651+ ap[0]->fts_link = NULL;
652+ return (head);
653 }
654
655 /*
656@@ -551,9 +320,7 @@ fts_children(sp, instr)
657 * been found, cutting the stat calls by about 2/3.
658 */
659 static FTSENT *
660-fts_build(sp, type)
661- register FTS *sp;
662- int type;
663+fts_build(register FTS *sp, int type)
664 {
665 register struct dirent *dp;
666 register FTSENT *p, *head;
667@@ -716,283 +483,479 @@ mem1: saved_errno = errno;
668 --nlinks;
669 }
670
671- /* We walk in directory order so "ls -f" doesn't get upset. */
672- p->fts_link = NULL;
673- if (head == NULL)
674- head = tail = p;
675- else {
676- tail->fts_link = p;
677- tail = p;
678+ /* We walk in directory order so "ls -f" doesn't get upset. */
679+ p->fts_link = NULL;
680+ if (head == NULL)
681+ head = tail = p;
682+ else {
683+ tail->fts_link = p;
684+ tail = p;
685+ }
686+ ++nitems;
687+ }
688+ (void)closedir(dirp);
689+
690+ /*
691+ * If had to realloc the path, adjust the addresses for the rest
692+ * of the tree.
693+ */
694+ if (adjaddr)
695+ fts_padjust(sp, adjaddr);
696+
697+ /*
698+ * If not changing directories, reset the path back to original
699+ * state.
700+ */
701+ if (ISSET(FTS_NOCHDIR)) {
702+ if (cp - 1 > sp->fts_path)
703+ --cp;
704+ *cp = '\0';
705+ }
706+
707+ /*
708+ * If descended after called from fts_children or after called from
709+ * fts_read and nothing found, get back. At the root level we use
710+ * the saved fd; if one of fts_open()'s arguments is a relative path
711+ * to an empty directory, we wind up here with no other way back. If
712+ * can't get back, we're done.
713+ */
714+ if (descend && (type == BCHILD || !nitems) &&
715+ (cur->fts_level == FTS_ROOTLEVEL ?
716+ FCHDIR(sp, sp->fts_rfd) : CHDIR(sp, ".."))) {
717+ cur->fts_info = FTS_ERR;
718+ SET(FTS_STOP);
719+ return (NULL);
720+ }
721+
722+ /* If didn't find anything, return NULL. */
723+ if (!nitems) {
724+ if (type == BREAD)
725+ cur->fts_info = FTS_DP;
726+ return (NULL);
727+ }
728+
729+ /* Sort the entries. */
730+ if (sp->fts_compar && nitems > 1)
731+ head = fts_sort(sp, head, nitems);
732+ return (head);
733+}
734+
735+
736+FTS *
737+fts_open(char * const *argv, register int options, int (*compar)())
738+{
739+ register FTS *sp;
740+ register FTSENT *p, *root;
741+ register int nitems;
742+ FTSENT *parent, *tmp;
743+ int len;
744+
745+ /* Options check. */
746+ if (options & ~FTS_OPTIONMASK) {
747+ errno = EINVAL;
748+ return (NULL);
749+ }
750+
751+ /* Allocate/initialize the stream */
752+ if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
753+ return (NULL);
754+ memset(sp, 0, sizeof(FTS));
755+ sp->fts_compar = compar;
756+ sp->fts_options = options;
757+
758+ /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
759+ if (ISSET(FTS_LOGICAL))
760+ SET(FTS_NOCHDIR);
761+
762+ /*
763+ * Start out with 1K of path space, and enough, in any case,
764+ * to hold the user's paths.
765+ */
766+ if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
767+ goto mem1;
768+
769+ /* Allocate/initialize root's parent. */
770+ if ((parent = fts_alloc(sp, "", 0)) == NULL)
771+ goto mem2;
772+ parent->fts_level = FTS_ROOTPARENTLEVEL;
773+
774+ /* Allocate/initialize root(s). */
775+ for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
776+ /* Don't allow zero-length paths. */
777+ if ((len = strlen(*argv)) == 0) {
778+ errno = EINVAL;
779+ goto mem3;
780+ }
781+
782+ p = fts_alloc(sp, *argv, len);
783+ p->fts_level = FTS_ROOTLEVEL;
784+ p->fts_parent = parent;
785+ p->fts_accpath = p->fts_name;
786+ p->fts_info = fts_stat(sp, NULL, p, ISSET(FTS_COMFOLLOW));
787+
788+ /* Command-line "." and ".." are real directories. */
789+ if (p->fts_info == FTS_DOT)
790+ p->fts_info = FTS_D;
791+
792+ /*
793+ * If comparison routine supplied, traverse in sorted
794+ * order; otherwise traverse in the order specified.
795+ */
796+ if (compar) {
797+ p->fts_link = root;
798+ root = p;
799+ } else {
800+ p->fts_link = NULL;
801+ if (root == NULL)
802+ tmp = root = p;
803+ else {
804+ tmp->fts_link = p;
805+ tmp = p;
806+ }
807 }
808- ++nitems;
809 }
810- (void)closedir(dirp);
811-
812- /*
813- * If had to realloc the path, adjust the addresses for the rest
814- * of the tree.
815- */
816- if (adjaddr)
817- fts_padjust(sp, adjaddr);
818+ if (compar && nitems > 1)
819+ root = fts_sort(sp, root, nitems);
820
821 /*
822- * If not changing directories, reset the path back to original
823- * state.
824+ * Allocate a dummy pointer and make fts_read think that we've just
825+ * finished the node before the root(s); set p->fts_info to FTS_INIT
826+ * so that everything about the "current" node is ignored.
827 */
828- if (ISSET(FTS_NOCHDIR)) {
829- if (cp - 1 > sp->fts_path)
830- --cp;
831- *cp = '\0';
832- }
833+ if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
834+ goto mem3;
835+ sp->fts_cur->fts_link = root;
836+ sp->fts_cur->fts_info = FTS_INIT;
837
838 /*
839- * If descended after called from fts_children or after called from
840- * fts_read and nothing found, get back. At the root level we use
841- * the saved fd; if one of fts_open()'s arguments is a relative path
842- * to an empty directory, we wind up here with no other way back. If
843- * can't get back, we're done.
844+ * If using chdir(2), grab a file descriptor pointing to dot to insure
845+ * that we can get back here; this could be avoided for some paths,
846+ * but almost certainly not worth the effort. Slashes, symbolic links,
847+ * and ".." are all fairly nasty problems. Note, if we can't get the
848+ * descriptor we run anyway, just more slowly.
849 */
850- if (descend && (type == BCHILD || !nitems) &&
851- (cur->fts_level == FTS_ROOTLEVEL ?
852- FCHDIR(sp, sp->fts_rfd) : CHDIR(sp, ".."))) {
853- cur->fts_info = FTS_ERR;
854- SET(FTS_STOP);
855- return (NULL);
856- }
857+ if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0)
858+ SET(FTS_NOCHDIR);
859
860- /* If didn't find anything, return NULL. */
861- if (!nitems) {
862- if (type == BREAD)
863- cur->fts_info = FTS_DP;
864- return (NULL);
865- }
866+ return (sp);
867
868- /* Sort the entries. */
869- if (sp->fts_compar && nitems > 1)
870- head = fts_sort(sp, head, nitems);
871- return (head);
872+mem3: fts_lfree(root);
873+ free(parent);
874+mem2: free(sp->fts_path);
875+mem1: free(sp);
876+ return (NULL);
877 }
878
879-static u_short
880-fts_stat(sp, dp, p, follow)
881- FTS *sp;
882- register FTSENT *p;
883- struct dirent *dp;
884- int follow;
885+FTSENT *
886+fts_read(register FTS *sp)
887 {
888- register FTSENT *t;
889- register dev_t dev;
890- register ino_t ino;
891- struct stat *sbp, sb;
892+ register FTSENT *p, *tmp;
893+ register int instr;
894+ register char *t;
895 int saved_errno;
896
897- /* If user needs stat info, stat buffer already allocated. */
898- sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
899+ /* If finished or unrecoverable error, return NULL. */
900+ if (sp->fts_cur == NULL || ISSET(FTS_STOP))
901+ return (NULL);
902
903-#ifdef S_IFWHT
904- /*
905- * Whited-out files don't really exist. However, there's stat(2) file
906- * mask for them, so we set it so that programs (i.e., find) don't have
907- * to test FTS_W separately from other file types.
908- */
909- if (dp != NULL && dp->d_type == DT_WHT) {
910- memset(sbp, 0, sizeof(struct stat));
911- sbp->st_mode = S_IFWHT;
912- return (FTS_W);
913+ /* Set current node pointer. */
914+ p = sp->fts_cur;
915+
916+ /* Save and zero out user instructions. */
917+ instr = p->fts_instr;
918+ p->fts_instr = FTS_NOINSTR;
919+
920+ /* Any type of file may be re-visited; re-stat and re-turn. */
921+ if (instr == FTS_AGAIN) {
922+ p->fts_info = fts_stat(sp, NULL, p, 0);
923+ return (p);
924 }
925-#endif
926-
927+
928 /*
929- * If doing a logical walk, or application requested FTS_FOLLOW, do
930- * a stat(2). If that fails, check for a non-existent symlink. If
931- * fail, set the errno from the stat call.
932+ * Following a symlink -- SLNONE test allows application to see
933+ * SLNONE and recover. If indirecting through a symlink, have
934+ * keep a pointer to current location. If unable to get that
935+ * pointer, follow fails.
936 */
937- if (ISSET(FTS_LOGICAL) || follow) {
938- if (stat(p->fts_accpath, sbp)) {
939- saved_errno = errno;
940- if (!lstat(p->fts_accpath, sbp)) {
941- errno = 0;
942- return (FTS_SLNONE);
943- }
944- p->fts_errno = saved_errno;
945- goto err;
946+ if (instr == FTS_FOLLOW &&
947+ (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
948+ p->fts_info = fts_stat(sp, NULL, p, 1);
949+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR))
950+ if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) {
951+ p->fts_errno = errno;
952+ p->fts_info = FTS_ERR;
953+ } else
954+ p->fts_flags |= FTS_SYMFOLLOW;
955+ return (p);
956+ }
957+
958+ /* Directory in pre-order. */
959+ if (p->fts_info == FTS_D) {
960+ /* If skipped or crossed mount point, do post-order visit. */
961+ if (instr == FTS_SKIP ||
962+ ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev) {
963+ if (p->fts_flags & FTS_SYMFOLLOW)
964+ (void)close(p->fts_symfd);
965+ if (sp->fts_child) {
966+ fts_lfree(sp->fts_child);
967+ sp->fts_child = NULL;
968+ }
969+ p->fts_info = FTS_DP;
970+ return (p);
971 }
972- } else if (lstat(p->fts_accpath, sbp)) {
973- p->fts_errno = errno;
974-err: memset(sbp, 0, sizeof(struct stat));
975- return (FTS_NS);
976+
977+ /* Rebuild if only read the names and now traversing. */
978+ if (sp->fts_child && sp->fts_options & FTS_NAMEONLY) {
979+ sp->fts_options &= ~FTS_NAMEONLY;
980+ fts_lfree(sp->fts_child);
981+ sp->fts_child = NULL;
982+ }
983+
984+ /*
985+ * Cd to the subdirectory.
986+ *
987+ * If have already read and now fail to chdir, whack the list
988+ * to make the names come out right, and set the parent errno
989+ * so the application will eventually get an error condition.
990+ * Set the FTS_DONTCHDIR flag so that when we logically change
991+ * directories back to the parent we don't do a chdir.
992+ *
993+ * If haven't read do so. If the read fails, fts_build sets
994+ * FTS_STOP or the fts_info field of the node.
995+ */
996+ if (sp->fts_child) {
997+ if (CHDIR(sp, p->fts_accpath)) {
998+ p->fts_errno = errno;
999+ p->fts_flags |= FTS_DONTCHDIR;
1000+ for (p = sp->fts_child; p; p = p->fts_link)
1001+ p->fts_accpath =
1002+ p->fts_parent->fts_accpath;
1003+ }
1004+ } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
1005+ if (ISSET(FTS_STOP))
1006+ return (NULL);
1007+ return (p);
1008+ }
1009+ p = sp->fts_child;
1010+ sp->fts_child = NULL;
1011+ goto name;
1012 }
1013
1014- if (S_ISDIR(sbp->st_mode)) {
1015+ /* Move to the next node on this level. */
1016+next: tmp = p;
1017+ if (p = p->fts_link) {
1018+ free(tmp);
1019+
1020 /*
1021- * Set the device/inode. Used to find cycles and check for
1022- * crossing mount points. Also remember the link count, used
1023- * in fts_build to limit the number of stat calls. It is
1024- * understood that these fields are only referenced if fts_info
1025- * is set to FTS_D.
1026+ * If reached the top, return to the original directory, and
1027+ * load the paths for the next root.
1028 */
1029- dev = p->fts_dev = sbp->st_dev;
1030- ino = p->fts_ino = sbp->st_ino;
1031- p->fts_nlink = sbp->st_nlink;
1032+ if (p->fts_level == FTS_ROOTLEVEL) {
1033+ if (!ISSET(FTS_NOCHDIR) && FCHDIR(sp, sp->fts_rfd)) {
1034+ SET(FTS_STOP);
1035+ return (NULL);
1036+ }
1037+ fts_load(sp, p);
1038+ return (sp->fts_cur = p);
1039+ }
1040+
1041+ /*
1042+ * User may have called fts_set on the node. If skipped,
1043+ * ignore. If followed, get a file descriptor so we can
1044+ * get back if necessary.
1045+ */
1046+ if (p->fts_instr == FTS_SKIP)
1047+ goto next;
1048+ if (p->fts_instr == FTS_FOLLOW) {
1049+ p->fts_info = fts_stat(sp, NULL, p, 1);
1050+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR))
1051+ if ((p->fts_symfd =
1052+ open(".", O_RDONLY, 0)) < 0) {
1053+ p->fts_errno = errno;
1054+ p->fts_info = FTS_ERR;
1055+ } else
1056+ p->fts_flags |= FTS_SYMFOLLOW;
1057+ p->fts_instr = FTS_NOINSTR;
1058+ }
1059
1060- if (ISDOT(p->fts_name))
1061- return (FTS_DOT);
1062+name: t = sp->fts_path + NAPPEND(p->fts_parent);
1063+ *t++ = '/';
1064+ memmove(t, p->fts_name, p->fts_namelen + 1);
1065+ return (sp->fts_cur = p);
1066+ }
1067
1068+ /* Move up to the parent node. */
1069+ p = tmp->fts_parent;
1070+ free(tmp);
1071+
1072+ if (p->fts_level == FTS_ROOTPARENTLEVEL) {
1073 /*
1074- * Cycle detection is done by brute force when the directory
1075- * is first encountered. If the tree gets deep enough or the
1076- * number of symbolic links to directories is high enough,
1077- * something faster might be worthwhile.
1078+ * Done; free everything up and set errno to 0 so the user
1079+ * can distinguish between error and EOF.
1080 */
1081- for (t = p->fts_parent;
1082- t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
1083- if (ino == t->fts_ino && dev == t->fts_dev) {
1084- p->fts_cycle = t;
1085- return (FTS_DC);
1086- }
1087- return (FTS_D);
1088+ free(p);
1089+ errno = 0;
1090+ return (sp->fts_cur = NULL);
1091 }
1092- if (S_ISLNK(sbp->st_mode))
1093- return (FTS_SL);
1094- if (S_ISREG(sbp->st_mode))
1095- return (FTS_F);
1096- return (FTS_DEFAULT);
1097-}
1098
1099-static FTSENT *
1100-fts_sort(sp, head, nitems)
1101- FTS *sp;
1102- FTSENT *head;
1103- register int nitems;
1104-{
1105- register FTSENT **ap, *p;
1106+ /* Nul terminate the pathname. */
1107+ sp->fts_path[p->fts_pathlen] = '\0';
1108
1109 /*
1110- * Construct an array of pointers to the structures and call qsort(3).
1111- * Reassemble the array in the order returned by qsort. If unable to
1112- * sort for memory reasons, return the directory entries in their
1113- * current order. Allocate enough space for the current needs plus
1114- * 40 so don't realloc one entry at a time.
1115+ * Return to the parent directory. If at a root node or came through
1116+ * a symlink, go back through the file descriptor. Otherwise, cd up
1117+ * one directory.
1118 */
1119- if (nitems > sp->fts_nitems) {
1120- sp->fts_nitems = nitems + 40;
1121- if ((sp->fts_array = realloc(sp->fts_array,
1122- (size_t)(sp->fts_nitems * sizeof(FTSENT *)))) == NULL) {
1123- sp->fts_nitems = 0;
1124- return (head);
1125+ if (p->fts_level == FTS_ROOTLEVEL) {
1126+ if (!ISSET(FTS_NOCHDIR) && FCHDIR(sp, sp->fts_rfd)) {
1127+ SET(FTS_STOP);
1128+ return (NULL);
1129+ }
1130+ } else if (p->fts_flags & FTS_SYMFOLLOW) {
1131+ if (FCHDIR(sp, p->fts_symfd)) {
1132+ saved_errno = errno;
1133+ (void)close(p->fts_symfd);
1134+ errno = saved_errno;
1135+ SET(FTS_STOP);
1136+ return (NULL);
1137+ }
1138+ (void)close(p->fts_symfd);
1139+ } else if (!(p->fts_flags & FTS_DONTCHDIR)) {
1140+ if (CHDIR(sp, "..")) {
1141+ SET(FTS_STOP);
1142+ return (NULL);
1143 }
1144 }
1145- for (ap = sp->fts_array, p = head; p; p = p->fts_link)
1146- *ap++ = p;
1147- qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
1148- for (head = *(ap = sp->fts_array); --nitems; ++ap)
1149- ap[0]->fts_link = ap[1];
1150- ap[0]->fts_link = NULL;
1151- return (head);
1152+ p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
1153+ return (sp->fts_cur = p);
1154 }
1155
1156-static FTSENT *
1157-fts_alloc(sp, name, namelen)
1158- FTS *sp;
1159- char *name;
1160- register int namelen;
1161+/*
1162+ * Fts_set takes the stream as an argument although it's not used in this
1163+ * implementation; it would be necessary if anyone wanted to add global
1164+ * semantics to fts using fts_set. An error return is allowed for similar
1165+ * reasons.
1166+ */
1167+/* ARGSUSED */
1168+int
1169+fts_set(FTS *sp, FTSENT *p, int instr)
1170+{
1171+ if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
1172+ instr != FTS_NOINSTR && instr != FTS_SKIP) {
1173+ errno = EINVAL;
1174+ return (1);
1175+ }
1176+ p->fts_instr = instr;
1177+ return (0);
1178+}
1179+
1180+FTSENT *
1181+fts_children(register FTS *sp, int instr)
1182 {
1183 register FTSENT *p;
1184- size_t len;
1185+ int fd;
1186+
1187+ if (instr && instr != FTS_NAMEONLY) {
1188+ errno = EINVAL;
1189+ return (NULL);
1190+ }
1191+
1192+ /* Set current node pointer. */
1193+ p = sp->fts_cur;
1194
1195 /*
1196- * The file name is a variable length array and no stat structure is
1197- * necessary if the user has set the nostat bit. Allocate the FTSENT
1198- * structure, the file name and the stat structure in one chunk, but
1199- * be careful that the stat structure is reasonably aligned. Since the
1200- * fts_name field is declared to be of size 1, the fts_name pointer is
1201- * namelen + 2 before the first possible address of the stat structure.
1202+ * Errno set to 0 so user can distinguish empty directory from
1203+ * an error.
1204 */
1205- len = sizeof(FTSENT) + namelen;
1206- if (!ISSET(FTS_NOSTAT))
1207- len += sizeof(struct stat) + ALIGNBYTES;
1208- if ((p = malloc(len)) == NULL)
1209+ errno = 0;
1210+
1211+ /* Fatal errors stop here. */
1212+ if (ISSET(FTS_STOP))
1213 return (NULL);
1214
1215- /* Copy the name plus the trailing NULL. */
1216- memmove(p->fts_name, name, namelen + 1);
1217+ /* Return logical hierarchy of user's arguments. */
1218+ if (p->fts_info == FTS_INIT)
1219+ return (p->fts_link);
1220
1221- if (!ISSET(FTS_NOSTAT))
1222- p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
1223- p->fts_namelen = namelen;
1224- p->fts_path = sp->fts_path;
1225- p->fts_errno = 0;
1226- p->fts_flags = 0;
1227- p->fts_instr = FTS_NOINSTR;
1228- p->fts_number = 0;
1229- p->fts_pointer = NULL;
1230- return (p);
1231+ /*
1232+ * If not a directory being visited in pre-order, stop here. Could
1233+ * allow FTS_DNR, assuming the user has fixed the problem, but the
1234+ * same effect is available with FTS_AGAIN.
1235+ */
1236+ if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
1237+ return (NULL);
1238+
1239+ /* Free up any previous child list. */
1240+ if (sp->fts_child)
1241+ fts_lfree(sp->fts_child);
1242+
1243+ if (instr == FTS_NAMEONLY) {
1244+ sp->fts_options |= FTS_NAMEONLY;
1245+ instr = BNAMES;
1246+ } else
1247+ instr = BCHILD;
1248+
1249+ /*
1250+ * If using chdir on a relative path and called BEFORE fts_read does
1251+ * its chdir to the root of a traversal, we can lose -- we need to
1252+ * chdir into the subdirectory, and we don't know where the current
1253+ * directory is, so we can't get back so that the upcoming chdir by
1254+ * fts_read will work.
1255+ */
1256+ if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
1257+ ISSET(FTS_NOCHDIR))
1258+ return (sp->fts_child = fts_build(sp, instr));
1259+
1260+ if ((fd = open(".", O_RDONLY, 0)) < 0)
1261+ return (NULL);
1262+ sp->fts_child = fts_build(sp, instr);
1263+ if (fchdir(fd))
1264+ return (NULL);
1265+ (void)close(fd);
1266+ return (sp->fts_child);
1267 }
1268
1269-static void
1270-fts_lfree(head)
1271- register FTSENT *head;
1272+int
1273+fts_close(FTS *sp)
1274 {
1275- register FTSENT *p;
1276+ register FTSENT *freep, *p;
1277+ int saved_errno;
1278
1279- /* Free a linked list of structures. */
1280- while (p = head) {
1281- head = head->fts_link;
1282+ /*
1283+ * This still works if we haven't read anything -- the dummy structure
1284+ * points to the root list, so we step through to the end of the root
1285+ * list which has a valid parent pointer.
1286+ */
1287+ if (sp->fts_cur) {
1288+ for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
1289+ freep = p;
1290+ p = p->fts_link ? p->fts_link : p->fts_parent;
1291+ free(freep);
1292+ }
1293 free(p);
1294 }
1295-}
1296
1297-/*
1298- * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
1299- * Most systems will allow creation of paths much longer than MAXPATHLEN, even
1300- * though the kernel won't resolve them. Add the size (not just what's needed)
1301- * plus 256 bytes so don't realloc the path 2 bytes at a time.
1302- */
1303-static int
1304-fts_palloc(sp, more)
1305- FTS *sp;
1306- size_t more;
1307-{
1308- sp->fts_pathlen += more + 256;
1309- sp->fts_path = realloc(sp->fts_path, (size_t)sp->fts_pathlen);
1310- return (sp->fts_path == NULL);
1311-}
1312+ /* Free up child linked list, sort array, path buffer. */
1313+ if (sp->fts_child)
1314+ fts_lfree(sp->fts_child);
1315+ if (sp->fts_array)
1316+ free(sp->fts_array);
1317+ free(sp->fts_path);
1318
1319-/*
1320- * When the path is realloc'd, have to fix all of the pointers in structures
1321- * already returned.
1322- */
1323-static void
1324-fts_padjust(sp, addr)
1325- FTS *sp;
1326- void *addr;
1327-{
1328- FTSENT *p;
1329+ /* Return to original directory, save errno if necessary. */
1330+ if (!ISSET(FTS_NOCHDIR)) {
1331+ saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
1332+ (void)close(sp->fts_rfd);
1333+ }
1334
1335-#define ADJUST(p) { \
1336- (p)->fts_accpath = \
1337- (char *)addr + ((p)->fts_accpath - (p)->fts_path); \
1338- (p)->fts_path = addr; \
1339-}
1340- /* Adjust the current set of children. */
1341- for (p = sp->fts_child; p; p = p->fts_link)
1342- ADJUST(p);
1343+ /* Free up the stream pointer. */
1344+ free(sp);
1345
1346- /* Adjust the rest of the tree. */
1347- for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
1348- ADJUST(p);
1349- p = p->fts_link ? p->fts_link : p->fts_parent;
1350+ /* Set errno and return. */
1351+ if (!ISSET(FTS_NOCHDIR) && saved_errno) {
1352+ errno = saved_errno;
1353+ return (-1);
1354 }
1355+ return (0);
1356 }
1357
1358-static size_t
1359-fts_maxarglen(argv)
1360- char * const *argv;
1361-{
1362- size_t len, max;
1363-
1364- for (max = 0; *argv; ++argv)
1365- if ((len = strlen(*argv)) > max)
1366- max = len;
1367- return (max);
1368-}
diff --git a/meta/recipes-core/fts/fts/remove_cdefs.patch b/meta/recipes-core/fts/fts/remove_cdefs.patch
deleted file mode 100644
index c152704d44..0000000000
--- a/meta/recipes-core/fts/fts/remove_cdefs.patch
+++ /dev/null
@@ -1,69 +0,0 @@
1Replace use of macros from sys/cdefs.h since cdefs.h is missing on musl
2
3Signed-off-by: Khem Raj <raj.khem@gmail.com>
4Upstream-Status: Inappropriate
5
6Index: fts/fts.h
7===================================================================
8--- fts.orig/fts.h
9+++ fts/fts.h
10@@ -126,15 +126,21 @@ typedef struct _ftsent {
11 char fts_name[1]; /* file name */
12 } FTSENT;
13
14-#include <sys/cdefs.h>
15+#ifdef __cplusplus
16+extern "C" {
17+#endif
18
19-__BEGIN_DECLS
20-FTSENT *fts_children __P((FTS *, int));
21-int fts_close __P((FTS *));
22-FTS *fts_open __P((char * const *, int,
23- int (*)(const FTSENT **, const FTSENT **)));
24-FTSENT *fts_read __P((FTS *));
25-int fts_set __P((FTS *, FTSENT *, int));
26-__END_DECLS
27+#ifndef __P
28+#define __P
29+#endif
30+FTSENT *fts_children (FTS *p, int opts);
31+int fts_close (FTS *p);
32+FTS *fts_open (char * const * path, int opts,
33+ int (*compfn)(const FTSENT **, const FTSENT **));
34+FTSENT *fts_read (FTS *p);
35+int fts_set (FTS *p, FTSENT *f, int opts);
36
37+#ifdef __cplusplus
38+}
39+#endif
40 #endif /* !_FTS_H_ */
41Index: fts/fts.c
42===================================================================
43--- fts.orig/fts.c
44+++ fts/fts.c
45@@ -50,15 +50,15 @@ static char sccsid[] = "@(#)fts.c 8.6 (B
46 #include <string.h>
47 #include <unistd.h>
48
49-static FTSENT *fts_alloc __P((FTS *, char *, int));
50-static FTSENT *fts_build __P((FTS *, int));
51-static void fts_lfree __P((FTSENT *));
52-static void fts_load __P((FTS *, FTSENT *));
53-static size_t fts_maxarglen __P((char * const *));
54-static void fts_padjust __P((FTS *, void *));
55-static int fts_palloc __P((FTS *, size_t));
56-static FTSENT *fts_sort __P((FTS *, FTSENT *, int));
57-static u_short fts_stat __P((FTS *, struct dirent *, FTSENT *, int));
58+static FTSENT *fts_alloc __P(FTS *, char *, int);
59+static FTSENT *fts_build __P(FTS *, int);
60+static void fts_lfree __P(FTSENT *);
61+static void fts_load __P(FTS *, FTSENT *);
62+static size_t fts_maxarglen __P(char * const *);
63+static void fts_padjust __P(FTS *, void *);
64+static int fts_palloc __P(FTS *, size_t);
65+static FTSENT *fts_sort __P(FTS *, FTSENT *, int);
66+static u_short fts_stat __P(FTS *, struct dirent *, FTSENT *, int);
67
68 #define ISDOT(a) (a[0] == '.' && (!a[1] || a[1] == '.' && !a[2]))
69
diff --git a/meta/recipes-core/fts/fts/stdint.patch b/meta/recipes-core/fts/fts/stdint.patch
deleted file mode 100644
index 89e6097fcb..0000000000
--- a/meta/recipes-core/fts/fts/stdint.patch
+++ /dev/null
@@ -1,15 +0,0 @@
1Include stdint.h for u_* typedefs
2
3Signed-off-by: Khem Raj <raj.khem@gmail.com>
4Upstream-Status: Inappropriate
5
6--- ./fts.c.orig
7+++ ./fts.c
8@@ -46,6 +46,7 @@
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <fts.h>
12+#include <stdint.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>