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 @@
 
 SUMMARY = "POSIX file tree stream operations library"
 HOMEPAGE = "https://sites.google.com/a/bostic.com/keithbostic"
-LICENSE = "BSD-4-Clause"
-LIC_FILES_CHKSUM = "file://fts.h;beginline=1;endline=36;md5=2532eddb3d1a21905723a4011ec4e085"
+LICENSE = "BSD-3-Clause"
+LIC_FILES_CHKSUM = "file://COPYING;md5=5ffe358174aad383f1b69ce3b53da982"
 SECTION = "libs"
 
-SRC_URI = "https://sites.google.com/a/bostic.com/keithbostic/files/fts.tar.gz \
-           file://fts-header-correctness.patch \
-           file://fts-uclibc.patch \
-           file://remove_cdefs.patch \
-           file://stdint.patch \
-           file://gcc5.patch \
-"
-
-SRC_URI[md5sum] = "120c14715485ec6ced14f494d059d20a"
-SRC_URI[sha256sum] = "3df9b9b5a45aeaf16f33bb84e692a10dc662e22ec8a51748f98767d67fb6f342"
-
-S = "${WORKDIR}/${BPN}"
+SRCREV = "944333aed9dc24cfa76cc64bfe70c75d25652753"
+PV = "1.2+git${SRCPV}"
 
-do_configure[noexec] = "1"
-
-HASHSTYLE_mipsarch = "sysv"
-HASHSTYLE = "gnu"
-
-VER = "0"
-do_compile () {
-    ${CC} -I${S} -fPIC -shared -Wl,--hash-style=${HASHSTYLE} -o libfts.so.${VER} -Wl,-soname,libfts.so.${VER} ${S}/fts.c
-}
+SRC_URI = "git://github.com/voidlinux/musl-fts \
+"
+S = "${WORKDIR}/git"
 
-do_install() {
-    install -Dm755 ${B}/libfts.so.${VER} ${D}${libdir}/libfts.so.${VER}
-    ln -sf libfts.so.${VER} ${D}${libdir}/libfts.so
-    install -Dm644 ${S}/fts.h ${D}${includedir}/fts.h
-}
+inherit autotools pkgconfig
 #
 # We will skip parsing for non-musl systems
 #
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 @@
-Included needed headers for compiling with musl
-
-Signed-off-by: Khem Raj <raj.khem@gmail.com>
-Upstream-Status: Inappropriate
-
---- fts.orig/fts.h
-+++ fts/fts.h
-@@ -38,6 +38,17 @@
- #ifndef	_FTS_H_
- #define	_FTS_H_
- 
-+#include <sys/types.h>
-+#include <sys/param.h>
-+#include <sys/stat.h>
-+
-+#include <dirent.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <unistd.h>
-+
- typedef struct {
- 	struct _ftsent *fts_cur;	/* current node */
- 	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 @@
-Add missing defines for uclibc
-
-Signed-off-by: Khem Raj <raj.khem@gmail.com>
-Upstream-Status: Inappropriate
-
---- fts.orig/fts.c
-+++ fts/fts.c
-@@ -31,6 +31,10 @@
-  * SUCH DAMAGE.
-  */
- 
-+#define	alignof(TYPE)   ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
-+#define	ALIGNBYTES	(alignof(long double) - 1)
-+#define	ALIGN(p)	(((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES) 
-+
- #if defined(LIBC_SCCS) && !defined(lint)
- static char sccsid[] = "@(#)fts.c	8.6 (Berkeley) 8/14/94";
- #endif /* LIBC_SCCS and not lint */
-@@ -652,10 +656,10 @@
- 		if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
- 			continue;
- 
--		if ((p = fts_alloc(sp, dp->d_name, (int)dp->d_namlen)) == NULL)
-+		if ((p = fts_alloc(sp, dp->d_name, (int)dp->d_reclen)) == NULL)
- 			goto mem1;
--		if (dp->d_namlen > maxlen) {
--			if (fts_palloc(sp, (size_t)dp->d_namlen)) {
-+		if (dp->d_reclen > maxlen) {
-+			if (fts_palloc(sp, (size_t)dp->d_reclen)) {
- 				/*
- 				 * No more memory for path or structures.  Save
- 				 * errno, free up the current structure and the
-@@ -675,7 +679,7 @@
- 			maxlen = sp->fts_pathlen - sp->fts_cur->fts_pathlen - 1;
- 		}
- 
--		p->fts_pathlen = len + dp->d_namlen + 1;
-+		p->fts_pathlen = len + dp->d_reclen + 1;
- 		p->fts_parent = sp->fts_cur;
- 		p->fts_level = level;
- 
-@@ -784,7 +788,7 @@
- 	/* If user needs stat info, stat buffer already allocated. */
- 	sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
- 
--#ifdef DT_WHT
-+#ifdef S_IFWHT
- 	/*
- 	 * Whited-out files don't really exist.  However, there's stat(2) file
- 	 * 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 @@
-Forward port the sources to be able to compile with c99/gcc5
-
-Signed-off-by: Khem Raj <raj.khem@gmail.com>
-Upstream-Status: Inappropriate
-
-Index: fts/fts.c
-===================================================================
---- fts.orig/fts.c
-+++ fts/fts.c
-@@ -51,16 +51,6 @@ static char sccsid[] = "@(#)fts.c	8.6 (B
- #include <string.h>
- #include <unistd.h>
- 
--static FTSENT	*fts_alloc __P(FTS *, char *, int);
--static FTSENT	*fts_build __P(FTS *, int);
--static void	 fts_lfree __P(FTSENT *);
--static void	 fts_load __P(FTS *, FTSENT *);
--static size_t	 fts_maxarglen __P(char * const *);
--static void	 fts_padjust __P(FTS *, void *);
--static int	 fts_palloc __P(FTS *, size_t);
--static FTSENT	*fts_sort __P(FTS *, FTSENT *, int);
--static u_short	 fts_stat __P(FTS *, struct dirent *, FTSENT *, int);
--
- #define	ISDOT(a)	(a[0] == '.' && (!a[1] || a[1] == '.' && !a[2]))
- 
- #define	ISSET(opt)	(sp->fts_options & opt)
-@@ -73,119 +63,16 @@ static u_short	 fts_stat __P(FTS *, stru
- #define	BCHILD		1		/* fts_children */
- #define	BNAMES		2		/* fts_children, names only */
- #define	BREAD		3		/* fts_read */
--
--FTS *
--fts_open(argv, options, compar)
--	char * const *argv;
--	register int options;
--	int (*compar)();
--{
--	register FTS *sp;
--	register FTSENT *p, *root;
--	register int nitems;
--	FTSENT *parent, *tmp;
--	int len;
--
--	/* Options check. */
--	if (options & ~FTS_OPTIONMASK) {
--		errno = EINVAL;
--		return (NULL);
--	}
--
--	/* Allocate/initialize the stream */
--	if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
--		return (NULL);
--	memset(sp, 0, sizeof(FTS));
--	sp->fts_compar = compar;
--	sp->fts_options = options;
--
--	/* Logical walks turn on NOCHDIR; symbolic links are too hard. */
--	if (ISSET(FTS_LOGICAL))
--		SET(FTS_NOCHDIR);
--
--	/*
--	 * Start out with 1K of path space, and enough, in any case,
--	 * to hold the user's paths.
--	 */
--	if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
--		goto mem1;
--
--	/* Allocate/initialize root's parent. */
--	if ((parent = fts_alloc(sp, "", 0)) == NULL)
--		goto mem2;
--	parent->fts_level = FTS_ROOTPARENTLEVEL;
--
--	/* Allocate/initialize root(s). */
--	for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
--		/* Don't allow zero-length paths. */
--		if ((len = strlen(*argv)) == 0) {
--			errno = EINVAL;
--			goto mem3;
--		}
--
--		p = fts_alloc(sp, *argv, len);
--		p->fts_level = FTS_ROOTLEVEL;
--		p->fts_parent = parent;
--		p->fts_accpath = p->fts_name;
--		p->fts_info = fts_stat(sp, NULL, p, ISSET(FTS_COMFOLLOW));
--
--		/* Command-line "." and ".." are real directories. */
--		if (p->fts_info == FTS_DOT)
--			p->fts_info = FTS_D;
--
--		/*
--		 * If comparison routine supplied, traverse in sorted
--		 * order; otherwise traverse in the order specified.
--		 */
--		if (compar) {
--			p->fts_link = root;
--			root = p;
--		} else {
--			p->fts_link = NULL;
--			if (root == NULL)
--				tmp = root = p;
--			else {
--				tmp->fts_link = p;
--				tmp = p;
--			}
--		}
--	}
--	if (compar && nitems > 1)
--		root = fts_sort(sp, root, nitems);
--
--	/*
--	 * Allocate a dummy pointer and make fts_read think that we've just
--	 * finished the node before the root(s); set p->fts_info to FTS_INIT
--	 * so that everything about the "current" node is ignored.
--	 */
--	if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
--		goto mem3;
--	sp->fts_cur->fts_link = root;
--	sp->fts_cur->fts_info = FTS_INIT;
--
--	/*
--	 * If using chdir(2), grab a file descriptor pointing to dot to insure
--	 * that we can get back here; this could be avoided for some paths,
--	 * but almost certainly not worth the effort.  Slashes, symbolic links,
--	 * and ".." are all fairly nasty problems.  Note, if we can't get the
--	 * descriptor we run anyway, just more slowly.
--	 */
--	if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0)
--		SET(FTS_NOCHDIR);
--
--	return (sp);
--
--mem3:	fts_lfree(root);
--	free(parent);
--mem2:	free(sp->fts_path);
--mem1:	free(sp);
--	return (NULL);
--}
-+/*
-+ * Special case a root of "/" so that slashes aren't appended which would
-+ * cause paths to be written as "//foo".
-+ */
-+#define	NAPPEND(p)							\
-+	(p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 &&	\
-+	    p->fts_path[0] == '/' ? 0 : p->fts_pathlen)
- 
- static void
--fts_load(sp, p)
--	FTS *sp;
--	register FTSENT *p;
-+fts_load(FTS *sp, register FTSENT *p)
- {
- 	register int len;
- 	register char *cp;
-@@ -208,332 +95,214 @@ fts_load(sp, p)
- 	sp->fts_dev = p->fts_dev;
- }
- 
--int
--fts_close(sp)
--	FTS *sp;
-+static void
-+fts_lfree(register FTSENT *head)
- {
--	register FTSENT *freep, *p;
--	int saved_errno;
-+	register FTSENT *p;
- 
--	/*
--	 * This still works if we haven't read anything -- the dummy structure
--	 * points to the root list, so we step through to the end of the root
--	 * list which has a valid parent pointer.
--	 */
--	if (sp->fts_cur) {
--		for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
--			freep = p;
--			p = p->fts_link ? p->fts_link : p->fts_parent;
--			free(freep);
--		}
-+	/* Free a linked list of structures. */
-+	while (p = head) {
-+		head = head->fts_link;
- 		free(p);
- 	}
-+}
- 
--	/* Free up child linked list, sort array, path buffer. */
--	if (sp->fts_child)
--		fts_lfree(sp->fts_child);
--	if (sp->fts_array)
--		free(sp->fts_array);
--	free(sp->fts_path);
-+static size_t
-+fts_maxarglen(char * const *argv)
-+{
-+	size_t len, max;
- 
--	/* Return to original directory, save errno if necessary. */
--	if (!ISSET(FTS_NOCHDIR)) {
--		saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
--		(void)close(sp->fts_rfd);
--	}
-+	for (max = 0; *argv; ++argv)
-+		if ((len = strlen(*argv)) > max)
-+			max = len;
-+	return (max);
-+}
- 
--	/* Free up the stream pointer. */
--	free(sp);
- 
--	/* Set errno and return. */
--	if (!ISSET(FTS_NOCHDIR) && saved_errno) {
--		errno = saved_errno;
--		return (-1);
-+/*
-+ * When the path is realloc'd, have to fix all of the pointers in structures
-+ * already returned.
-+ */
-+static void
-+fts_padjust(FTS *sp, void *addr)
-+{
-+	FTSENT *p;
-+
-+#define	ADJUST(p) {							\
-+	(p)->fts_accpath =						\
-+	    (char *)addr + ((p)->fts_accpath - (p)->fts_path);		\
-+	(p)->fts_path = addr;						\
-+}
-+	/* Adjust the current set of children. */
-+	for (p = sp->fts_child; p; p = p->fts_link)
-+		ADJUST(p);
-+
-+	/* Adjust the rest of the tree. */
-+	for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
-+		ADJUST(p);
-+		p = p->fts_link ? p->fts_link : p->fts_parent;
- 	}
--	return (0);
- }
- 
- /*
-- * Special case a root of "/" so that slashes aren't appended which would
-- * cause paths to be written as "//foo".
-+ * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
-+ * Most systems will allow creation of paths much longer than MAXPATHLEN, even
-+ * though the kernel won't resolve them.  Add the size (not just what's needed)
-+ * plus 256 bytes so don't realloc the path 2 bytes at a time.
-  */
--#define	NAPPEND(p)							\
--	(p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 &&	\
--	    p->fts_path[0] == '/' ? 0 : p->fts_pathlen)
-+static int
-+fts_palloc(FTS *sp, size_t more)
-+{
-+	sp->fts_pathlen += more + 256;
-+	sp->fts_path = realloc(sp->fts_path, (size_t)sp->fts_pathlen);
-+	return (sp->fts_path == NULL);
-+}
- 
--FTSENT *
--fts_read(sp)
--	register FTS *sp;
-+static FTSENT *
-+fts_alloc(FTS *sp, char *name, register int namelen)
- {
--	register FTSENT *p, *tmp;
--	register int instr;
--	register char *t;
--	int saved_errno;
-+	register FTSENT *p;
-+	size_t len;
- 
--	/* If finished or unrecoverable error, return NULL. */
--	if (sp->fts_cur == NULL || ISSET(FTS_STOP))
-+	/*
-+	 * The file name is a variable length array and no stat structure is
-+	 * necessary if the user has set the nostat bit.  Allocate the FTSENT
-+	 * structure, the file name and the stat structure in one chunk, but
-+	 * be careful that the stat structure is reasonably aligned.  Since the
-+	 * fts_name field is declared to be of size 1, the fts_name pointer is
-+	 * namelen + 2 before the first possible address of the stat structure.
-+	 */
-+	len = sizeof(FTSENT) + namelen;
-+	if (!ISSET(FTS_NOSTAT))
-+		len += sizeof(struct stat) + ALIGNBYTES;
-+	if ((p = malloc(len)) == NULL)
- 		return (NULL);
- 
--	/* Set current node pointer. */
--	p = sp->fts_cur;
-+	/* Copy the name plus the trailing NULL. */
-+	memmove(p->fts_name, name, namelen + 1);
- 
--	/* Save and zero out user instructions. */
--	instr = p->fts_instr;
-+	if (!ISSET(FTS_NOSTAT))
-+		p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
-+	p->fts_namelen = namelen;
-+	p->fts_path = sp->fts_path;
-+	p->fts_errno = 0;
-+	p->fts_flags = 0;
- 	p->fts_instr = FTS_NOINSTR;
-+	p->fts_number = 0;
-+	p->fts_pointer = NULL;
-+	return (p);
-+}
- 
--	/* Any type of file may be re-visited; re-stat and re-turn. */
--	if (instr == FTS_AGAIN) {
--		p->fts_info = fts_stat(sp, NULL, p, 0);
--		return (p);
--	}
- 
-+static u_short
-+fts_stat(FTS *sp, register FTSENT *p, struct dirent *dp, int follow)
-+{
-+	register FTSENT *t;
-+	register dev_t dev;
-+	register ino_t ino;
-+	struct stat *sbp, sb;
-+	int saved_errno;
-+
-+	/* If user needs stat info, stat buffer already allocated. */
-+	sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
-+
-+#ifdef S_IFWHT
- 	/*
--	 * Following a symlink -- SLNONE test allows application to see
--	 * SLNONE and recover.  If indirecting through a symlink, have
--	 * keep a pointer to current location.  If unable to get that
--	 * pointer, follow fails.
--	 */
--	if (instr == FTS_FOLLOW &&
--	    (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
--		p->fts_info = fts_stat(sp, NULL, p, 1);
--		if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR))
--			if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) {
--				p->fts_errno = errno;
--				p->fts_info = FTS_ERR;
--			} else
--				p->fts_flags |= FTS_SYMFOLLOW;
--		return (p);
-+	 * Whited-out files don't really exist.  However, there's stat(2) file
-+	 * mask for them, so we set it so that programs (i.e., find) don't have
-+	 * to test FTS_W separately from other file types.
-+	 */
-+	if (dp != NULL && dp->d_type == DT_WHT) {
-+		memset(sbp, 0, sizeof(struct stat));
-+		sbp->st_mode = S_IFWHT;
-+		return (FTS_W);
- 	}
--
--	/* Directory in pre-order. */
--	if (p->fts_info == FTS_D) {
--		/* If skipped or crossed mount point, do post-order visit. */
--		if (instr == FTS_SKIP ||
--		    ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev) {
--			if (p->fts_flags & FTS_SYMFOLLOW)
--				(void)close(p->fts_symfd);
--			if (sp->fts_child) {
--				fts_lfree(sp->fts_child);
--				sp->fts_child = NULL;
--			}
--			p->fts_info = FTS_DP;
--			return (p);
--		} 
--
--		/* Rebuild if only read the names and now traversing. */
--		if (sp->fts_child && sp->fts_options & FTS_NAMEONLY) {
--			sp->fts_options &= ~FTS_NAMEONLY;
--			fts_lfree(sp->fts_child);
--			sp->fts_child = NULL;
--		}
--
--		/*
--		 * Cd to the subdirectory.
--		 *
--		 * If have already read and now fail to chdir, whack the list
--		 * to make the names come out right, and set the parent errno
--		 * so the application will eventually get an error condition.
--		 * Set the FTS_DONTCHDIR flag so that when we logically change
--		 * directories back to the parent we don't do a chdir.
--		 *
--		 * If haven't read do so.  If the read fails, fts_build sets
--		 * FTS_STOP or the fts_info field of the node.
--		 */
--		if (sp->fts_child) {
--			if (CHDIR(sp, p->fts_accpath)) {
--				p->fts_errno = errno;
--				p->fts_flags |= FTS_DONTCHDIR;
--				for (p = sp->fts_child; p; p = p->fts_link)
--					p->fts_accpath =
--					    p->fts_parent->fts_accpath;
--			}
--		} else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
--			if (ISSET(FTS_STOP))
--				return (NULL);
--			return (p);
-+#endif
-+
-+	/*
-+	 * If doing a logical walk, or application requested FTS_FOLLOW, do
-+	 * a stat(2).  If that fails, check for a non-existent symlink.  If
-+	 * fail, set the errno from the stat call.
-+	 */
-+	if (ISSET(FTS_LOGICAL) || follow) {
-+		if (stat(p->fts_accpath, sbp)) {
-+			saved_errno = errno;
-+			if (!lstat(p->fts_accpath, sbp)) {
-+				errno = 0;
-+				return (FTS_SLNONE);
-+			}
-+			p->fts_errno = saved_errno;
-+			goto err;
- 		}
--		p = sp->fts_child;
--		sp->fts_child = NULL;
--		goto name;
-+	} else if (lstat(p->fts_accpath, sbp)) {
-+		p->fts_errno = errno;
-+err:		memset(sbp, 0, sizeof(struct stat));
-+		return (FTS_NS);
- 	}
- 
--	/* Move to the next node on this level. */
--next:	tmp = p;
--	if (p = p->fts_link) {
--		free(tmp);
--
--		/*
--		 * If reached the top, return to the original directory, and
--		 * load the paths for the next root.
--		 */
--		if (p->fts_level == FTS_ROOTLEVEL) {
--			if (!ISSET(FTS_NOCHDIR) && FCHDIR(sp, sp->fts_rfd)) {
--				SET(FTS_STOP);
--				return (NULL);
--			}
--			fts_load(sp, p);
--			return (sp->fts_cur = p);
--		}
--
-+	if (S_ISDIR(sbp->st_mode)) {
- 		/*
--		 * User may have called fts_set on the node.  If skipped,
--		 * ignore.  If followed, get a file descriptor so we can
--		 * get back if necessary.
-+		 * Set the device/inode.  Used to find cycles and check for
-+		 * crossing mount points.  Also remember the link count, used
-+		 * in fts_build to limit the number of stat calls.  It is
-+		 * understood that these fields are only referenced if fts_info
-+		 * is set to FTS_D.
- 		 */
--		if (p->fts_instr == FTS_SKIP)
--			goto next;
--		if (p->fts_instr == FTS_FOLLOW) {
--			p->fts_info = fts_stat(sp, NULL, p, 1);
--			if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR))
--				if ((p->fts_symfd =
--				    open(".", O_RDONLY, 0)) < 0) {
--					p->fts_errno = errno;
--					p->fts_info = FTS_ERR;
--				} else
--					p->fts_flags |= FTS_SYMFOLLOW;
--			p->fts_instr = FTS_NOINSTR;
--		}
--
--name:		t = sp->fts_path + NAPPEND(p->fts_parent);
--		*t++ = '/';
--		memmove(t, p->fts_name, p->fts_namelen + 1);
--		return (sp->fts_cur = p);
--	}
-+		dev = p->fts_dev = sbp->st_dev;
-+		ino = p->fts_ino = sbp->st_ino;
-+		p->fts_nlink = sbp->st_nlink;
- 
--	/* Move up to the parent node. */
--	p = tmp->fts_parent;
--	free(tmp);
-+		if (ISDOT(p->fts_name))
-+			return (FTS_DOT);
- 
--	if (p->fts_level == FTS_ROOTPARENTLEVEL) {
- 		/*
--		 * Done; free everything up and set errno to 0 so the user
--		 * can distinguish between error and EOF.
-+		 * Cycle detection is done by brute force when the directory
-+		 * is first encountered.  If the tree gets deep enough or the
-+		 * number of symbolic links to directories is high enough,
-+		 * something faster might be worthwhile.
- 		 */
--		free(p);
--		errno = 0;
--		return (sp->fts_cur = NULL);
--	}
--
--	/* Nul terminate the pathname. */
--	sp->fts_path[p->fts_pathlen] = '\0';
--
--	/*
--	 * Return to the parent directory.  If at a root node or came through
--	 * a symlink, go back through the file descriptor.  Otherwise, cd up
--	 * one directory.
--	 */
--	if (p->fts_level == FTS_ROOTLEVEL) {
--		if (!ISSET(FTS_NOCHDIR) && FCHDIR(sp, sp->fts_rfd)) {
--			SET(FTS_STOP);
--			return (NULL);
--		}
--	} else if (p->fts_flags & FTS_SYMFOLLOW) {
--		if (FCHDIR(sp, p->fts_symfd)) {
--			saved_errno = errno;
--			(void)close(p->fts_symfd);
--			errno = saved_errno;
--			SET(FTS_STOP);
--			return (NULL);
--		}
--		(void)close(p->fts_symfd);
--	} else if (!(p->fts_flags & FTS_DONTCHDIR)) {
--		if (CHDIR(sp, "..")) {
--			SET(FTS_STOP);
--			return (NULL);
--		}
--	}
--	p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
--	return (sp->fts_cur = p);
--}
--
--/*
-- * Fts_set takes the stream as an argument although it's not used in this
-- * implementation; it would be necessary if anyone wanted to add global
-- * semantics to fts using fts_set.  An error return is allowed for similar
-- * reasons.
-- */
--/* ARGSUSED */
--int
--fts_set(sp, p, instr)
--	FTS *sp;
--	FTSENT *p;
--	int instr;
--{
--	if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
--	    instr != FTS_NOINSTR && instr != FTS_SKIP) {
--		errno = EINVAL;
--		return (1);
-+		for (t = p->fts_parent;
-+		    t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
-+			if (ino == t->fts_ino && dev == t->fts_dev) {
-+				p->fts_cycle = t;
-+				return (FTS_DC);
-+			}
-+		return (FTS_D);
- 	}
--	p->fts_instr = instr;
--	return (0);
-+	if (S_ISLNK(sbp->st_mode))
-+		return (FTS_SL);
-+	if (S_ISREG(sbp->st_mode))
-+		return (FTS_F);
-+	return (FTS_DEFAULT);
- }
- 
--FTSENT *
--fts_children(sp, instr)
--	register FTS *sp;
--	int instr;
-+static FTSENT *
-+fts_sort(FTS *sp, FTSENT *head, register int nitems)
- {
--	register FTSENT *p;
--	int fd;
--
--	if (instr && instr != FTS_NAMEONLY) {
--		errno = EINVAL;
--		return (NULL);
--	}
--
--	/* Set current node pointer. */
--	p = sp->fts_cur;
--
--	/*
--	 * Errno set to 0 so user can distinguish empty directory from
--	 * an error.
--	 */
--	errno = 0;
--
--	/* Fatal errors stop here. */
--	if (ISSET(FTS_STOP))
--		return (NULL);
--
--	/* Return logical hierarchy of user's arguments. */
--	if (p->fts_info == FTS_INIT)
--		return (p->fts_link);
--
--	/*
--	 * If not a directory being visited in pre-order, stop here.  Could
--	 * allow FTS_DNR, assuming the user has fixed the problem, but the
--	 * same effect is available with FTS_AGAIN.
--	 */
--	if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
--		return (NULL);
--
--	/* Free up any previous child list. */
--	if (sp->fts_child)
--		fts_lfree(sp->fts_child);
--
--	if (instr == FTS_NAMEONLY) {
--		sp->fts_options |= FTS_NAMEONLY;
--		instr = BNAMES;
--	} else 
--		instr = BCHILD;
-+	register FTSENT **ap, *p;
- 
- 	/*
--	 * If using chdir on a relative path and called BEFORE fts_read does
--	 * its chdir to the root of a traversal, we can lose -- we need to
--	 * chdir into the subdirectory, and we don't know where the current
--	 * directory is, so we can't get back so that the upcoming chdir by
--	 * fts_read will work.
-+	 * Construct an array of pointers to the structures and call qsort(3).
-+	 * Reassemble the array in the order returned by qsort.  If unable to
-+	 * sort for memory reasons, return the directory entries in their
-+	 * current order.  Allocate enough space for the current needs plus
-+	 * 40 so don't realloc one entry at a time.
- 	 */
--	if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
--	    ISSET(FTS_NOCHDIR))
--		return (sp->fts_child = fts_build(sp, instr));
--
--	if ((fd = open(".", O_RDONLY, 0)) < 0)
--		return (NULL);
--	sp->fts_child = fts_build(sp, instr);
--	if (fchdir(fd))
--		return (NULL);
--	(void)close(fd);
--	return (sp->fts_child);
-+	if (nitems > sp->fts_nitems) {
-+		sp->fts_nitems = nitems + 40;
-+		if ((sp->fts_array = realloc(sp->fts_array,
-+		    (size_t)(sp->fts_nitems * sizeof(FTSENT *)))) == NULL) {
-+			sp->fts_nitems = 0;
-+			return (head);
-+		}
-+	}
-+	for (ap = sp->fts_array, p = head; p; p = p->fts_link)
-+		*ap++ = p;
-+	qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
-+	for (head = *(ap = sp->fts_array); --nitems; ++ap)
-+		ap[0]->fts_link = ap[1];
-+	ap[0]->fts_link = NULL;
-+	return (head);
- }
- 
- /*
-@@ -551,9 +320,7 @@ fts_children(sp, instr)
-  * been found, cutting the stat calls by about 2/3.
-  */
- static FTSENT *
--fts_build(sp, type)
--	register FTS *sp;
--	int type;
-+fts_build(register FTS *sp, int type)
- {
- 	register struct dirent *dp;
- 	register FTSENT *p, *head;
-@@ -716,283 +483,479 @@ mem1:				saved_errno = errno;
- 				--nlinks;
- 		}
- 
--		/* We walk in directory order so "ls -f" doesn't get upset. */
--		p->fts_link = NULL;
--		if (head == NULL)
--			head = tail = p;
--		else {
--			tail->fts_link = p;
--			tail = p;
-+		/* We walk in directory order so "ls -f" doesn't get upset. */
-+		p->fts_link = NULL;
-+		if (head == NULL)
-+			head = tail = p;
-+		else {
-+			tail->fts_link = p;
-+			tail = p;
-+		}
-+		++nitems;
-+	}
-+	(void)closedir(dirp);
-+
-+	/*
-+	 * If had to realloc the path, adjust the addresses for the rest
-+	 * of the tree.
-+	 */
-+	if (adjaddr)
-+		fts_padjust(sp, adjaddr);
-+
-+	/*
-+	 * If not changing directories, reset the path back to original
-+	 * state.
-+	 */
-+	if (ISSET(FTS_NOCHDIR)) {
-+		if (cp - 1 > sp->fts_path)
-+			--cp;
-+		*cp = '\0';
-+	}
-+
-+	/*
-+	 * If descended after called from fts_children or after called from
-+	 * fts_read and nothing found, get back.  At the root level we use
-+	 * the saved fd; if one of fts_open()'s arguments is a relative path
-+	 * to an empty directory, we wind up here with no other way back.  If
-+	 * can't get back, we're done.
-+	 */
-+	if (descend && (type == BCHILD || !nitems) &&
-+	    (cur->fts_level == FTS_ROOTLEVEL ?
-+	    FCHDIR(sp, sp->fts_rfd) : CHDIR(sp, ".."))) {
-+		cur->fts_info = FTS_ERR;
-+		SET(FTS_STOP);
-+		return (NULL);
-+	}
-+
-+	/* If didn't find anything, return NULL. */
-+	if (!nitems) {
-+		if (type == BREAD)
-+			cur->fts_info = FTS_DP;
-+		return (NULL);
-+	}
-+
-+	/* Sort the entries. */
-+	if (sp->fts_compar && nitems > 1)
-+		head = fts_sort(sp, head, nitems);
-+	return (head);
-+}
-+
-+
-+FTS *
-+fts_open(char * const *argv, register int options, int (*compar)())
-+{
-+	register FTS *sp;
-+	register FTSENT *p, *root;
-+	register int nitems;
-+	FTSENT *parent, *tmp;
-+	int len;
-+
-+	/* Options check. */
-+	if (options & ~FTS_OPTIONMASK) {
-+		errno = EINVAL;
-+		return (NULL);
-+	}
-+
-+	/* Allocate/initialize the stream */
-+	if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
-+		return (NULL);
-+	memset(sp, 0, sizeof(FTS));
-+	sp->fts_compar = compar;
-+	sp->fts_options = options;
-+
-+	/* Logical walks turn on NOCHDIR; symbolic links are too hard. */
-+	if (ISSET(FTS_LOGICAL))
-+		SET(FTS_NOCHDIR);
-+
-+	/*
-+	 * Start out with 1K of path space, and enough, in any case,
-+	 * to hold the user's paths.
-+	 */
-+	if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
-+		goto mem1;
-+
-+	/* Allocate/initialize root's parent. */
-+	if ((parent = fts_alloc(sp, "", 0)) == NULL)
-+		goto mem2;
-+	parent->fts_level = FTS_ROOTPARENTLEVEL;
-+
-+	/* Allocate/initialize root(s). */
-+	for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
-+		/* Don't allow zero-length paths. */
-+		if ((len = strlen(*argv)) == 0) {
-+			errno = EINVAL;
-+			goto mem3;
-+		}
-+
-+		p = fts_alloc(sp, *argv, len);
-+		p->fts_level = FTS_ROOTLEVEL;
-+		p->fts_parent = parent;
-+		p->fts_accpath = p->fts_name;
-+		p->fts_info = fts_stat(sp, NULL, p, ISSET(FTS_COMFOLLOW));
-+
-+		/* Command-line "." and ".." are real directories. */
-+		if (p->fts_info == FTS_DOT)
-+			p->fts_info = FTS_D;
-+
-+		/*
-+		 * If comparison routine supplied, traverse in sorted
-+		 * order; otherwise traverse in the order specified.
-+		 */
-+		if (compar) {
-+			p->fts_link = root;
-+			root = p;
-+		} else {
-+			p->fts_link = NULL;
-+			if (root == NULL)
-+				tmp = root = p;
-+			else {
-+				tmp->fts_link = p;
-+				tmp = p;
-+			}
- 		}
--		++nitems;
- 	}
--	(void)closedir(dirp);
--
--	/*
--	 * If had to realloc the path, adjust the addresses for the rest
--	 * of the tree.
--	 */
--	if (adjaddr)
--		fts_padjust(sp, adjaddr);
-+	if (compar && nitems > 1)
-+		root = fts_sort(sp, root, nitems);
- 
- 	/*
--	 * If not changing directories, reset the path back to original
--	 * state.
-+	 * Allocate a dummy pointer and make fts_read think that we've just
-+	 * finished the node before the root(s); set p->fts_info to FTS_INIT
-+	 * so that everything about the "current" node is ignored.
- 	 */
--	if (ISSET(FTS_NOCHDIR)) {
--		if (cp - 1 > sp->fts_path)
--			--cp;
--		*cp = '\0';
--	}
-+	if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
-+		goto mem3;
-+	sp->fts_cur->fts_link = root;
-+	sp->fts_cur->fts_info = FTS_INIT;
- 
- 	/*
--	 * If descended after called from fts_children or after called from
--	 * fts_read and nothing found, get back.  At the root level we use
--	 * the saved fd; if one of fts_open()'s arguments is a relative path
--	 * to an empty directory, we wind up here with no other way back.  If
--	 * can't get back, we're done.
-+	 * If using chdir(2), grab a file descriptor pointing to dot to insure
-+	 * that we can get back here; this could be avoided for some paths,
-+	 * but almost certainly not worth the effort.  Slashes, symbolic links,
-+	 * and ".." are all fairly nasty problems.  Note, if we can't get the
-+	 * descriptor we run anyway, just more slowly.
- 	 */
--	if (descend && (type == BCHILD || !nitems) &&
--	    (cur->fts_level == FTS_ROOTLEVEL ?
--	    FCHDIR(sp, sp->fts_rfd) : CHDIR(sp, ".."))) {
--		cur->fts_info = FTS_ERR;
--		SET(FTS_STOP);
--		return (NULL);
--	}
-+	if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0)
-+		SET(FTS_NOCHDIR);
- 
--	/* If didn't find anything, return NULL. */
--	if (!nitems) {
--		if (type == BREAD)
--			cur->fts_info = FTS_DP;
--		return (NULL);
--	}
-+	return (sp);
- 
--	/* Sort the entries. */
--	if (sp->fts_compar && nitems > 1)
--		head = fts_sort(sp, head, nitems);
--	return (head);
-+mem3:	fts_lfree(root);
-+	free(parent);
-+mem2:	free(sp->fts_path);
-+mem1:	free(sp);
-+	return (NULL);
- }
- 
--static u_short
--fts_stat(sp, dp, p, follow)
--	FTS *sp;
--	register FTSENT *p;
--	struct dirent *dp;
--	int follow;
-+FTSENT *
-+fts_read(register FTS *sp)
- {
--	register FTSENT *t;
--	register dev_t dev;
--	register ino_t ino;
--	struct stat *sbp, sb;
-+	register FTSENT *p, *tmp;
-+	register int instr;
-+	register char *t;
- 	int saved_errno;
- 
--	/* If user needs stat info, stat buffer already allocated. */
--	sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
-+	/* If finished or unrecoverable error, return NULL. */
-+	if (sp->fts_cur == NULL || ISSET(FTS_STOP))
-+		return (NULL);
- 
--#ifdef S_IFWHT
--	/*
--	 * Whited-out files don't really exist.  However, there's stat(2) file
--	 * mask for them, so we set it so that programs (i.e., find) don't have
--	 * to test FTS_W separately from other file types.
--	 */
--	if (dp != NULL && dp->d_type == DT_WHT) {
--		memset(sbp, 0, sizeof(struct stat));
--		sbp->st_mode = S_IFWHT;
--		return (FTS_W);
-+	/* Set current node pointer. */
-+	p = sp->fts_cur;
-+
-+	/* Save and zero out user instructions. */
-+	instr = p->fts_instr;
-+	p->fts_instr = FTS_NOINSTR;
-+
-+	/* Any type of file may be re-visited; re-stat and re-turn. */
-+	if (instr == FTS_AGAIN) {
-+		p->fts_info = fts_stat(sp, NULL, p, 0);
-+		return (p);
- 	}
--#endif
--	
-+
- 	/*
--	 * If doing a logical walk, or application requested FTS_FOLLOW, do
--	 * a stat(2).  If that fails, check for a non-existent symlink.  If
--	 * fail, set the errno from the stat call.
-+	 * Following a symlink -- SLNONE test allows application to see
-+	 * SLNONE and recover.  If indirecting through a symlink, have
-+	 * keep a pointer to current location.  If unable to get that
-+	 * pointer, follow fails.
- 	 */
--	if (ISSET(FTS_LOGICAL) || follow) {
--		if (stat(p->fts_accpath, sbp)) {
--			saved_errno = errno;
--			if (!lstat(p->fts_accpath, sbp)) {
--				errno = 0;
--				return (FTS_SLNONE);
--			} 
--			p->fts_errno = saved_errno;
--			goto err;
-+	if (instr == FTS_FOLLOW &&
-+	    (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
-+		p->fts_info = fts_stat(sp, NULL, p, 1);
-+		if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR))
-+			if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) {
-+				p->fts_errno = errno;
-+				p->fts_info = FTS_ERR;
-+			} else
-+				p->fts_flags |= FTS_SYMFOLLOW;
-+		return (p);
-+	}
-+
-+	/* Directory in pre-order. */
-+	if (p->fts_info == FTS_D) {
-+		/* If skipped or crossed mount point, do post-order visit. */
-+		if (instr == FTS_SKIP ||
-+		    ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev) {
-+			if (p->fts_flags & FTS_SYMFOLLOW)
-+				(void)close(p->fts_symfd);
-+			if (sp->fts_child) {
-+				fts_lfree(sp->fts_child);
-+				sp->fts_child = NULL;
-+			}
-+			p->fts_info = FTS_DP;
-+			return (p);
- 		}
--	} else if (lstat(p->fts_accpath, sbp)) {
--		p->fts_errno = errno;
--err:		memset(sbp, 0, sizeof(struct stat));
--		return (FTS_NS);
-+
-+		/* Rebuild if only read the names and now traversing. */
-+		if (sp->fts_child && sp->fts_options & FTS_NAMEONLY) {
-+			sp->fts_options &= ~FTS_NAMEONLY;
-+			fts_lfree(sp->fts_child);
-+			sp->fts_child = NULL;
-+		}
-+
-+		/*
-+		 * Cd to the subdirectory.
-+		 *
-+		 * If have already read and now fail to chdir, whack the list
-+		 * to make the names come out right, and set the parent errno
-+		 * so the application will eventually get an error condition.
-+		 * Set the FTS_DONTCHDIR flag so that when we logically change
-+		 * directories back to the parent we don't do a chdir.
-+		 *
-+		 * If haven't read do so.  If the read fails, fts_build sets
-+		 * FTS_STOP or the fts_info field of the node.
-+		 */
-+		if (sp->fts_child) {
-+			if (CHDIR(sp, p->fts_accpath)) {
-+				p->fts_errno = errno;
-+				p->fts_flags |= FTS_DONTCHDIR;
-+				for (p = sp->fts_child; p; p = p->fts_link)
-+					p->fts_accpath =
-+					    p->fts_parent->fts_accpath;
-+			}
-+		} else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
-+			if (ISSET(FTS_STOP))
-+				return (NULL);
-+			return (p);
-+		}
-+		p = sp->fts_child;
-+		sp->fts_child = NULL;
-+		goto name;
- 	}
- 
--	if (S_ISDIR(sbp->st_mode)) {
-+	/* Move to the next node on this level. */
-+next:	tmp = p;
-+	if (p = p->fts_link) {
-+		free(tmp);
-+
- 		/*
--		 * Set the device/inode.  Used to find cycles and check for
--		 * crossing mount points.  Also remember the link count, used
--		 * in fts_build to limit the number of stat calls.  It is
--		 * understood that these fields are only referenced if fts_info
--		 * is set to FTS_D.
-+		 * If reached the top, return to the original directory, and
-+		 * load the paths for the next root.
- 		 */
--		dev = p->fts_dev = sbp->st_dev;
--		ino = p->fts_ino = sbp->st_ino;
--		p->fts_nlink = sbp->st_nlink;
-+		if (p->fts_level == FTS_ROOTLEVEL) {
-+			if (!ISSET(FTS_NOCHDIR) && FCHDIR(sp, sp->fts_rfd)) {
-+				SET(FTS_STOP);
-+				return (NULL);
-+			}
-+			fts_load(sp, p);
-+			return (sp->fts_cur = p);
-+		}
-+
-+		/*
-+		 * User may have called fts_set on the node.  If skipped,
-+		 * ignore.  If followed, get a file descriptor so we can
-+		 * get back if necessary.
-+		 */
-+		if (p->fts_instr == FTS_SKIP)
-+			goto next;
-+		if (p->fts_instr == FTS_FOLLOW) {
-+			p->fts_info = fts_stat(sp, NULL, p, 1);
-+			if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR))
-+				if ((p->fts_symfd =
-+				    open(".", O_RDONLY, 0)) < 0) {
-+					p->fts_errno = errno;
-+					p->fts_info = FTS_ERR;
-+				} else
-+					p->fts_flags |= FTS_SYMFOLLOW;
-+			p->fts_instr = FTS_NOINSTR;
-+		}
- 
--		if (ISDOT(p->fts_name))
--			return (FTS_DOT);
-+name:		t = sp->fts_path + NAPPEND(p->fts_parent);
-+		*t++ = '/';
-+		memmove(t, p->fts_name, p->fts_namelen + 1);
-+		return (sp->fts_cur = p);
-+	}
- 
-+	/* Move up to the parent node. */
-+	p = tmp->fts_parent;
-+	free(tmp);
-+
-+	if (p->fts_level == FTS_ROOTPARENTLEVEL) {
- 		/*
--		 * Cycle detection is done by brute force when the directory
--		 * is first encountered.  If the tree gets deep enough or the
--		 * number of symbolic links to directories is high enough,
--		 * something faster might be worthwhile.
-+		 * Done; free everything up and set errno to 0 so the user
-+		 * can distinguish between error and EOF.
- 		 */
--		for (t = p->fts_parent;
--		    t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
--			if (ino == t->fts_ino && dev == t->fts_dev) {
--				p->fts_cycle = t;
--				return (FTS_DC);
--			}
--		return (FTS_D);
-+		free(p);
-+		errno = 0;
-+		return (sp->fts_cur = NULL);
- 	}
--	if (S_ISLNK(sbp->st_mode))
--		return (FTS_SL);
--	if (S_ISREG(sbp->st_mode))
--		return (FTS_F);
--	return (FTS_DEFAULT);
--}
- 
--static FTSENT *
--fts_sort(sp, head, nitems)
--	FTS *sp;
--	FTSENT *head;
--	register int nitems;
--{
--	register FTSENT **ap, *p;
-+	/* Nul terminate the pathname. */
-+	sp->fts_path[p->fts_pathlen] = '\0';
- 
- 	/*
--	 * Construct an array of pointers to the structures and call qsort(3).
--	 * Reassemble the array in the order returned by qsort.  If unable to
--	 * sort for memory reasons, return the directory entries in their
--	 * current order.  Allocate enough space for the current needs plus
--	 * 40 so don't realloc one entry at a time.
-+	 * Return to the parent directory.  If at a root node or came through
-+	 * a symlink, go back through the file descriptor.  Otherwise, cd up
-+	 * one directory.
- 	 */
--	if (nitems > sp->fts_nitems) {
--		sp->fts_nitems = nitems + 40;
--		if ((sp->fts_array = realloc(sp->fts_array,
--		    (size_t)(sp->fts_nitems * sizeof(FTSENT *)))) == NULL) {
--			sp->fts_nitems = 0;
--			return (head);
-+	if (p->fts_level == FTS_ROOTLEVEL) {
-+		if (!ISSET(FTS_NOCHDIR) && FCHDIR(sp, sp->fts_rfd)) {
-+			SET(FTS_STOP);
-+			return (NULL);
-+		}
-+	} else if (p->fts_flags & FTS_SYMFOLLOW) {
-+		if (FCHDIR(sp, p->fts_symfd)) {
-+			saved_errno = errno;
-+			(void)close(p->fts_symfd);
-+			errno = saved_errno;
-+			SET(FTS_STOP);
-+			return (NULL);
-+		}
-+		(void)close(p->fts_symfd);
-+	} else if (!(p->fts_flags & FTS_DONTCHDIR)) {
-+		if (CHDIR(sp, "..")) {
-+			SET(FTS_STOP);
-+			return (NULL);
- 		}
- 	}
--	for (ap = sp->fts_array, p = head; p; p = p->fts_link)
--		*ap++ = p;
--	qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
--	for (head = *(ap = sp->fts_array); --nitems; ++ap)
--		ap[0]->fts_link = ap[1];
--	ap[0]->fts_link = NULL;
--	return (head);
-+	p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
-+	return (sp->fts_cur = p);
- }
- 
--static FTSENT *
--fts_alloc(sp, name, namelen)
--	FTS *sp;
--	char *name;
--	register int namelen;
-+/*
-+ * Fts_set takes the stream as an argument although it's not used in this
-+ * implementation; it would be necessary if anyone wanted to add global
-+ * semantics to fts using fts_set.  An error return is allowed for similar
-+ * reasons.
-+ */
-+/* ARGSUSED */
-+int
-+fts_set(FTS *sp, FTSENT *p, int instr)
-+{
-+	if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
-+	    instr != FTS_NOINSTR && instr != FTS_SKIP) {
-+		errno = EINVAL;
-+		return (1);
-+	}
-+	p->fts_instr = instr;
-+	return (0);
-+}
-+
-+FTSENT *
-+fts_children(register FTS *sp, int instr)
- {
- 	register FTSENT *p;
--	size_t len;
-+	int fd;
-+
-+	if (instr && instr != FTS_NAMEONLY) {
-+		errno = EINVAL;
-+		return (NULL);
-+	}
-+
-+	/* Set current node pointer. */
-+	p = sp->fts_cur;
- 
- 	/*
--	 * The file name is a variable length array and no stat structure is
--	 * necessary if the user has set the nostat bit.  Allocate the FTSENT
--	 * structure, the file name and the stat structure in one chunk, but
--	 * be careful that the stat structure is reasonably aligned.  Since the
--	 * fts_name field is declared to be of size 1, the fts_name pointer is
--	 * namelen + 2 before the first possible address of the stat structure.
-+	 * Errno set to 0 so user can distinguish empty directory from
-+	 * an error.
- 	 */
--	len = sizeof(FTSENT) + namelen;
--	if (!ISSET(FTS_NOSTAT))
--		len += sizeof(struct stat) + ALIGNBYTES;
--	if ((p = malloc(len)) == NULL)
-+	errno = 0;
-+
-+	/* Fatal errors stop here. */
-+	if (ISSET(FTS_STOP))
- 		return (NULL);
- 
--	/* Copy the name plus the trailing NULL. */
--	memmove(p->fts_name, name, namelen + 1);
-+	/* Return logical hierarchy of user's arguments. */
-+	if (p->fts_info == FTS_INIT)
-+		return (p->fts_link);
- 
--	if (!ISSET(FTS_NOSTAT))
--		p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
--	p->fts_namelen = namelen;
--	p->fts_path = sp->fts_path;
--	p->fts_errno = 0;
--	p->fts_flags = 0;
--	p->fts_instr = FTS_NOINSTR;
--	p->fts_number = 0;
--	p->fts_pointer = NULL;
--	return (p);
-+	/*
-+	 * If not a directory being visited in pre-order, stop here.  Could
-+	 * allow FTS_DNR, assuming the user has fixed the problem, but the
-+	 * same effect is available with FTS_AGAIN.
-+	 */
-+	if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
-+		return (NULL);
-+
-+	/* Free up any previous child list. */
-+	if (sp->fts_child)
-+		fts_lfree(sp->fts_child);
-+
-+	if (instr == FTS_NAMEONLY) {
-+		sp->fts_options |= FTS_NAMEONLY;
-+		instr = BNAMES;
-+	} else
-+		instr = BCHILD;
-+
-+	/*
-+	 * If using chdir on a relative path and called BEFORE fts_read does
-+	 * its chdir to the root of a traversal, we can lose -- we need to
-+	 * chdir into the subdirectory, and we don't know where the current
-+	 * directory is, so we can't get back so that the upcoming chdir by
-+	 * fts_read will work.
-+	 */
-+	if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
-+	    ISSET(FTS_NOCHDIR))
-+		return (sp->fts_child = fts_build(sp, instr));
-+
-+	if ((fd = open(".", O_RDONLY, 0)) < 0)
-+		return (NULL);
-+	sp->fts_child = fts_build(sp, instr);
-+	if (fchdir(fd))
-+		return (NULL);
-+	(void)close(fd);
-+	return (sp->fts_child);
- }
- 
--static void
--fts_lfree(head)
--	register FTSENT *head;
-+int
-+fts_close(FTS *sp)
- {
--	register FTSENT *p;
-+	register FTSENT *freep, *p;
-+	int saved_errno;
- 
--	/* Free a linked list of structures. */
--	while (p = head) {
--		head = head->fts_link;
-+	/*
-+	 * This still works if we haven't read anything -- the dummy structure
-+	 * points to the root list, so we step through to the end of the root
-+	 * list which has a valid parent pointer.
-+	 */
-+	if (sp->fts_cur) {
-+		for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
-+			freep = p;
-+			p = p->fts_link ? p->fts_link : p->fts_parent;
-+			free(freep);
-+		}
- 		free(p);
- 	}
--}
- 
--/*
-- * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
-- * Most systems will allow creation of paths much longer than MAXPATHLEN, even
-- * though the kernel won't resolve them.  Add the size (not just what's needed)
-- * plus 256 bytes so don't realloc the path 2 bytes at a time. 
-- */
--static int
--fts_palloc(sp, more)
--	FTS *sp;
--	size_t more;
--{
--	sp->fts_pathlen += more + 256;
--	sp->fts_path = realloc(sp->fts_path, (size_t)sp->fts_pathlen);
--	return (sp->fts_path == NULL);
--}
-+	/* Free up child linked list, sort array, path buffer. */
-+	if (sp->fts_child)
-+		fts_lfree(sp->fts_child);
-+	if (sp->fts_array)
-+		free(sp->fts_array);
-+	free(sp->fts_path);
- 
--/*
-- * When the path is realloc'd, have to fix all of the pointers in structures
-- * already returned.
-- */
--static void
--fts_padjust(sp, addr)
--	FTS *sp;
--	void *addr;
--{
--	FTSENT *p;
-+	/* Return to original directory, save errno if necessary. */
-+	if (!ISSET(FTS_NOCHDIR)) {
-+		saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
-+		(void)close(sp->fts_rfd);
-+	}
- 
--#define	ADJUST(p) {							\
--	(p)->fts_accpath =						\
--	    (char *)addr + ((p)->fts_accpath - (p)->fts_path);		\
--	(p)->fts_path = addr;						\
--}
--	/* Adjust the current set of children. */
--	for (p = sp->fts_child; p; p = p->fts_link)
--		ADJUST(p);
-+	/* Free up the stream pointer. */
-+	free(sp);
- 
--	/* Adjust the rest of the tree. */
--	for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
--		ADJUST(p);
--		p = p->fts_link ? p->fts_link : p->fts_parent;
-+	/* Set errno and return. */
-+	if (!ISSET(FTS_NOCHDIR) && saved_errno) {
-+		errno = saved_errno;
-+		return (-1);
- 	}
-+	return (0);
- }
- 
--static size_t
--fts_maxarglen(argv)
--	char * const *argv;
--{
--	size_t len, max;
--
--	for (max = 0; *argv; ++argv)
--		if ((len = strlen(*argv)) > max)
--			max = len;
--	return (max);
--}
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 @@
-Replace use of macros from sys/cdefs.h since cdefs.h is missing on musl
-
-Signed-off-by: Khem Raj <raj.khem@gmail.com>
-Upstream-Status: Inappropriate
-
-Index: fts/fts.h
-===================================================================
---- fts.orig/fts.h
-+++ fts/fts.h
-@@ -126,15 +126,21 @@ typedef struct _ftsent {
- 	char fts_name[1];		/* file name */
- } FTSENT;
- 
--#include <sys/cdefs.h>
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
- 
--__BEGIN_DECLS
--FTSENT	*fts_children __P((FTS *, int));
--int	 fts_close __P((FTS *));
--FTS	*fts_open __P((char * const *, int,
--	    int (*)(const FTSENT **, const FTSENT **)));
--FTSENT	*fts_read __P((FTS *));
--int	 fts_set __P((FTS *, FTSENT *, int));
--__END_DECLS
-+#ifndef __P
-+#define __P
-+#endif
-+FTSENT	*fts_children (FTS *p, int opts);
-+int	 fts_close (FTS *p);
-+FTS	*fts_open (char * const * path, int opts,
-+	    int (*compfn)(const FTSENT **, const FTSENT **));
-+FTSENT	*fts_read (FTS *p);
-+int	 fts_set (FTS *p, FTSENT *f, int opts);
- 
-+#ifdef __cplusplus
-+}
-+#endif
- #endif /* !_FTS_H_ */
-Index: fts/fts.c
-===================================================================
---- fts.orig/fts.c
-+++ fts/fts.c
-@@ -50,15 +50,15 @@ static char sccsid[] = "@(#)fts.c	8.6 (B
- #include <string.h>
- #include <unistd.h>
- 
--static FTSENT	*fts_alloc __P((FTS *, char *, int));
--static FTSENT	*fts_build __P((FTS *, int));
--static void	 fts_lfree __P((FTSENT *));
--static void	 fts_load __P((FTS *, FTSENT *));
--static size_t	 fts_maxarglen __P((char * const *));
--static void	 fts_padjust __P((FTS *, void *));
--static int	 fts_palloc __P((FTS *, size_t));
--static FTSENT	*fts_sort __P((FTS *, FTSENT *, int));
--static u_short	 fts_stat __P((FTS *, struct dirent *, FTSENT *, int));
-+static FTSENT	*fts_alloc __P(FTS *, char *, int);
-+static FTSENT	*fts_build __P(FTS *, int);
-+static void	 fts_lfree __P(FTSENT *);
-+static void	 fts_load __P(FTS *, FTSENT *);
-+static size_t	 fts_maxarglen __P(char * const *);
-+static void	 fts_padjust __P(FTS *, void *);
-+static int	 fts_palloc __P(FTS *, size_t);
-+static FTSENT	*fts_sort __P(FTS *, FTSENT *, int);
-+static u_short	 fts_stat __P(FTS *, struct dirent *, FTSENT *, int);
- 
- #define	ISDOT(a)	(a[0] == '.' && (!a[1] || a[1] == '.' && !a[2]))
- 
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 @@
-Include stdint.h for u_* typedefs
-
-Signed-off-by: Khem Raj <raj.khem@gmail.com>
-Upstream-Status: Inappropriate
-
---- ./fts.c.orig
-+++ ./fts.c
-@@ -46,6 +46,7 @@
- #include <errno.h>
- #include <fcntl.h>
- #include <fts.h>
-+#include <stdint.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
