From patchwork Tue May 30 17:15:22 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Khem Raj X-Patchwork-Id: 100724 Delivered-To: patch@linaro.org Received: by 10.182.202.35 with SMTP id kf3csp1238173obc; Tue, 30 May 2017 10:16:26 -0700 (PDT) X-Received: by 10.98.25.19 with SMTP id 19mr25285147pfz.146.1496164585945; Tue, 30 May 2017 10:16:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1496164585; cv=none; d=google.com; s=arc-20160816; b=aPKkDZEx6BqbSoyTyJEOC7sLxZGq+0+e/O3OlUgbQBt62HcoGV5N1wGVzl9/pM5xrX c+Bqs/z6FXbujMnPjpNPWlDcYZcjHz5gOhORCKGwd1ucVtAOqNDsCaUJYyr2ttjLQcPg BdxSvpOuUQj55Jt8aIxTLl7arF9veOs2I2Sz8wE+yhZgoAuAnpWWD5t67M8XDdrA7U0M HK/ZEZIZ9imbnEHuSgzhOXokdFpDInkW4aqxs2gxxhyiRbVSNze3bW8vYE8cK2EvWor7 YIlCy5BqlF0bKDWiqDXiTDUi71xBAlv4Jqle5nQD2vDsVjZaWj7YSpdjkHwChfiAukEh IKZQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:sender:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:delivered-to:arc-authentication-results; bh=WWclTgedAtFHXCd98+BczJB/XdqW7d4ugwHaMj4RmO8=; b=OmQIWGb10o/Z5hpdywJDi1oG9NjRnBUMdk8UctM0siLIRCYXwU9BN5pUc/hNa0mL5V fEKh7CJPpaKDW+06mzkhRfFCtNYjQfJDIGbzaAs150m1yzcI9s1Bdc0upDtvqnfVg8Fo NV2JsZA3S9jqVQ3Ru7tAm5Pfa2ZbAR8lmmXkAH1J1gCTLIhRBMlrp7xJtx/0N3HGlo7R AMnjlsHGu+KKb6en2KI+nz7UvyAUxcEfdZEF4ubECCgafcZvnNVnbjo+2OR3sOcTKF1O dEp5MoG++6hWIO6PiZYnPcB4KN5GJ3eR76jbd0+pysU7OKbb00sgWRJvFCigy0/nYFHj V57A== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: best guess record for domain of openembedded-core-bounces@lists.openembedded.org designates 140.211.169.62 as permitted sender) smtp.mailfrom=openembedded-core-bounces@lists.openembedded.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Return-Path: Received: from mail.openembedded.org (mail.openembedded.org. [140.211.169.62]) by mx.google.com with ESMTP id k8si46054237pln.98.2017.05.30.10.16.25; Tue, 30 May 2017 10:16:25 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of openembedded-core-bounces@lists.openembedded.org designates 140.211.169.62 as permitted sender) client-ip=140.211.169.62; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: best guess record for domain of openembedded-core-bounces@lists.openembedded.org designates 140.211.169.62 as permitted sender) smtp.mailfrom=openembedded-core-bounces@lists.openembedded.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from review.yoctoproject.org (localhost [127.0.0.1]) by mail.openembedded.org (Postfix) with ESMTP id DF88078200; Tue, 30 May 2017 17:16:15 +0000 (UTC) X-Original-To: openembedded-core@lists.openembedded.org Delivered-To: openembedded-core@lists.openembedded.org Received: from mail-pf0-f194.google.com (mail-pf0-f194.google.com [209.85.192.194]) by mail.openembedded.org (Postfix) with ESMTP id 66851781C8 for ; Tue, 30 May 2017 17:15:35 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id n23so19250808pfb.3 for ; Tue, 30 May 2017 10:15:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zJ+YQIbpNrO0kswyRWKn/f5YMfze8wwe2vgYvAajZXo=; b=nL62RJVSsuvgj+4/C0OpJOHEYoEjLwCjsrV89TEx2CUiYmMrRqgN7zqnJjT3Q9xN86 0zWkJ8ncAIeskUjIB+5CsL/Iu5Tazqd7ZSDYp/e1WA63r2zr2abrQgjxPzPAjbg2lgRG DnDX2PBROVcbINB9/xBTGZo1OrovV8J46gl3xJTUCzmvAQDQvpYWdrZMcbVUvYxhQ+qR clPVimxGgRGPgVngNAqvHzoUpd+Y89MjdwakmTEJ0k5tIx5GFB5JbQYKbnZ2S5ZkUmVf 44U/YJdKsHk5lIjdoZTYri8AwaTN/yzj+F/vhtJxvBNKJ8SqJSBkmHiAZ3abIakckl7C ddAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zJ+YQIbpNrO0kswyRWKn/f5YMfze8wwe2vgYvAajZXo=; b=EGoGI4vVWiwVWW401bEq58xOEiGQkAxtI7Z3+k9O7IYtJe5bR6LD+bCdt0Jv6duvyx Br7PsH4cwra8Jzm/aaTf5wUd0SC9bTtlK0o3E4TY6R7uqG/LnnI7a8WB1kbVNlI9jlMs OwSL/Mvm3mdogcMGbpeo4dQ9UFUXvD/ssYb+ZIbdhufRKJrMiaX0cvL/kf+IP8ePEFh2 7LYxC4KoCV7ZzLoyylo8CHORZAEGlxgoec8TXh0W+9fEirZ3a6yAI0+Lch7QqjU54fut G1wAP8kvCcUaleeLin5aSJ7yngn45H3IIMH3SB03kWcmt6MxJspEpXgzHUb/3IMAsd33 IIeg== X-Gm-Message-State: AODbwcD28CgbMmVL0JSV+kPK/cZpqzHfvmMqnZvFjo1VQI5d39caDUc2 Dl3tjB0Ai+zUniKR X-Received: by 10.99.161.25 with SMTP id b25mr26526068pgf.26.1496164535598; Tue, 30 May 2017 10:15:35 -0700 (PDT) Received: from localhost.localdomain ([2601:646:8882:b8c::cf4]) by smtp.gmail.com with ESMTPSA id n24sm28071137pgd.57.2017.05.30.10.15.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 30 May 2017 10:15:34 -0700 (PDT) From: Khem Raj To: openembedded-core@lists.openembedded.org Date: Tue, 30 May 2017 10:15:22 -0700 Message-Id: <20170530171523.37470-2-raj.khem@gmail.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: <20170530171523.37470-1-raj.khem@gmail.com> References: <20170530171523.37470-1-raj.khem@gmail.com> Subject: [OE-core] [PATCH 2/3] fts: Switch SRC_URI to github X-BeenThere: openembedded-core@lists.openembedded.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Patches and discussions about the oe-core layer List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: openembedded-core-bounces@lists.openembedded.org Errors-To: openembedded-core-bounces@lists.openembedded.org Use the package maintained by voidlinux Drop local patches Signed-off-by: Khem Raj --- meta/recipes-core/fts/fts.bb | 36 +- .../fts/fts/fts-header-correctness.patch | 25 - meta/recipes-core/fts/fts/fts-uclibc.patch | 50 - meta/recipes-core/fts/fts/gcc5.patch | 1368 -------------------- meta/recipes-core/fts/fts/remove_cdefs.patch | 69 - meta/recipes-core/fts/fts/stdint.patch | 15 - 6 files changed, 8 insertions(+), 1555 deletions(-) delete mode 100644 meta/recipes-core/fts/fts/fts-header-correctness.patch delete mode 100644 meta/recipes-core/fts/fts/fts-uclibc.patch delete mode 100644 meta/recipes-core/fts/fts/gcc5.patch delete mode 100644 meta/recipes-core/fts/fts/remove_cdefs.patch delete mode 100644 meta/recipes-core/fts/fts/stdint.patch -- 2.13.0 -- _______________________________________________ Openembedded-core mailing list Openembedded-core@lists.openembedded.org http://lists.openembedded.org/mailman/listinfo/openembedded-core 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 -Upstream-Status: Inappropriate - ---- fts.orig/fts.h -+++ fts/fts.h -@@ -38,6 +38,17 @@ - #ifndef _FTS_H_ - #define _FTS_H_ - -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ - 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 -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 -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 - #include - --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 -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 -+#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 - #include - --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 -Upstream-Status: Inappropriate - ---- ./fts.c.orig -+++ ./fts.c -@@ -46,6 +46,7 @@ - #include - #include - #include -+#include - #include - #include - #include