get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2224507/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2224507,
    "url": "http://patchwork.ozlabs.org/api/patches/2224507/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/glibc/patch/20260417132808.235562-2-adhemerval.zanella@linaro.org/",
    "project": {
        "id": 41,
        "url": "http://patchwork.ozlabs.org/api/projects/41/?format=api",
        "name": "GNU C Library",
        "link_name": "glibc",
        "list_id": "libc-alpha.sourceware.org",
        "list_email": "libc-alpha@sourceware.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260417132808.235562-2-adhemerval.zanella@linaro.org>",
    "list_archive_url": null,
    "date": "2026-04-17T13:24:55",
    "name": "[1/3] io: Consolidate fts implementation",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "b65aec8d420b49ed8fee804da158f4c002bd483b",
    "submitter": {
        "id": 66065,
        "url": "http://patchwork.ozlabs.org/api/people/66065/?format=api",
        "name": "Adhemerval Zanella Netto",
        "email": "adhemerval.zanella@linaro.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/glibc/patch/20260417132808.235562-2-adhemerval.zanella@linaro.org/mbox/",
    "series": [
        {
            "id": 500340,
            "url": "http://patchwork.ozlabs.org/api/series/500340/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/glibc/list/?series=500340",
            "date": "2026-04-17T13:24:54",
            "name": "Consolidate and sync fts/ftw",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/500340/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2224507/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2224507/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "libc-alpha@sourceware.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "libc-alpha@sourceware.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=yYrlc05b;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org;\n receiver=patchwork.ozlabs.org)",
            "sourceware.org;\n\tdkim=pass (2048-bit key,\n unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=yYrlc05b",
            "sourceware.org;\n dmarc=pass (p=none dis=none) header.from=linaro.org",
            "sourceware.org; spf=pass smtp.mailfrom=linaro.org",
            "server2.sourceware.org;\n arc=none smtp.remote-ip=2607:f8b0:4864:20::122b"
        ],
        "Received": [
            "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fxwpT5jbQz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 17 Apr 2026 23:34:25 +1000 (AEST)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id C9B264AA51B4\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 17 Apr 2026 13:34:23 +0000 (GMT)",
            "from mail-dl1-x122b.google.com (mail-dl1-x122b.google.com\n [IPv6:2607:f8b0:4864:20::122b])\n by sourceware.org (Postfix) with ESMTPS id 929854C91778\n for <libc-alpha@sourceware.org>; Fri, 17 Apr 2026 13:28:19 +0000 (GMT)",
            "by mail-dl1-x122b.google.com with SMTP id\n a92af1059eb24-12c19d23b19so896773c88.0\n for <libc-alpha@sourceware.org>; Fri, 17 Apr 2026 06:28:19 -0700 (PDT)",
            "from mandiga.. ([2804:1b3:a7c3:d5d0:abc1:209f:f276:2b34])\n by smtp.gmail.com with ESMTPSA id\n a92af1059eb24-12c74a20eb5sm2556236c88.14.2026.04.17.06.28.13\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Fri, 17 Apr 2026 06:28:14 -0700 (PDT)"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org C9B264AA51B4",
            "OpenDKIM Filter v2.11.0 sourceware.org 929854C91778"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 929854C91778",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 929854C91778",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776432500; cv=none;\n b=qJ4BIlal1SNqo+p0Ge6lgEVIUi9+ZcyrNDM1nEEXVKKWzSfDyAIv0mjdBM0paqFIn13Q4tPjqg4NQfiwmagK4EUsm5wxhIUpvaRUb8aoyaZDwvMATGVk8JKBS8h96deWuWgPHQe64tuQPLtT8+P1vVRlInA1jKRrQEGsK/eOiB8=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776432500; c=relaxed/simple;\n bh=sK/iXRisLxDLJeJTtQnslh2Rg22KKUMux3zmqE69HZc=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=HprmwKWuBNDAi5fqQH9ZoDVjgWFaaIcC0vAVLlBXKjS+PCo12VjWUzNl0QH8kc03ZVtG4YP7/ptQz4kYKHv276GxDdj1Yt9uFNH+fB0N2SgsbMlBqleMqQyxC9nYwbwajuJYflyDR7AB+4fhIsHE6pignLp6tttDwGCK2396Jq8=",
        "ARC-Authentication-Results": "i=1; server2.sourceware.org",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=linaro.org; s=google; t=1776432498; x=1777037298; darn=sourceware.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=qlZy3STRuRjqBb4FAPyjBe2MH2Ex5nLWCIuzDPkl4yI=;\n b=yYrlc05bQ9C+YCPd266DtkCqObDSmQ9Fy2n5+F+M+zKS8VxgCnP1k63WrB7P/WTdxN\n AnXH3v6rn4bUlkq1dQVlfMwSA916/Oi2BhkwQ66QZFpUhHHBbYSo3hVOfF5/+JyQNZpI\n JZSK5o83hbZD2goRkV8CjC2HcVcNlqIFtr3Co1N9vsfq75xEDrlHnjoikLsgsJc11e1K\n TasAsNDbGBs9qYagFyoq8qo/bWNOFuODYVQLa7TAs+8q4WhVsx8NWgUm/PcaVwoR+nAq\n 3fgS4EFOjQ2vFYF8S2u4mUYEf4ZtLEB6JFhoBkpwnrSmmIODbb2mJRiyngtQEAy/LHp8\n 7+Jg==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776432498; x=1777037298;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=qlZy3STRuRjqBb4FAPyjBe2MH2Ex5nLWCIuzDPkl4yI=;\n b=K+NlKYmtPEXuqBVKx5SK4c0o+xiBvrPh5j7g+pTxyCC3Ee3JQq1NaOltUMj5uIHZtp\n V0oLh2yQY7ezGcuOTRsPXWFsYUl2y/c3K/C6rGZggAbUMQmbd5FQvDPyJP553qwkicvP\n k7ytOQKoGdr1vzqJLXpZkb8yB0bG4SLDNo0TQ3/U0I/9y5qeZV0soEIyi7OYyjpJ/FmI\n RdaJuPZx04r3XoI2FEer831501aPrOvS/VIA3v5rdMZNGPR8bBcqHHFn4cXvFtgL2cch\n Tz4UWXgI7tgdLynipf1BT8QXuu5x4d435QH0/ZGhWPKAfTukY7QTwc0hHPw03iYSx6X7\n GYrQ==",
        "X-Gm-Message-State": "AOJu0YwvzhLn5AlmDXa9qBF4tabNGqnHq2yt1HnISlzumB2Sravxjyko\n WLGX5sQ2AuFOR5YQJZod7UaXJ2sPFUH+qiwIastCcATOBz3n7LRCuVY66FOQf0iGJuHCzMh5QaM\n ZQVOG",
        "X-Gm-Gg": "AeBDieuB/GYetU6+lZPNGYOrKL+25lf24aNi8VrlPGraA6JcYCv+SibpNPksbnFvYwA\n UYgSj3g/tCtPCR0NdvG65s65udAWOTmTJdHq3eEwVLdSF9VfTSjUOlNW37lekIifC6NgjbnqUYq\n P6PhHEKeNlqPw2/btF8tu8KQfeaPMMJvVe0HBjA0e1H46ZAyo4wrLUWe0AE+oLH36WHFV57WT2R\n cNdwD/oC6AAxm/T+cnkVIxpq72Ie0hr5X+RWxM7d5zMkl2qdpcS3gz3hudgZNkbZ+0CRcQyw6tI\n IoexDacNB0Z8f6kTM3cHrGBCOSsil3LTIjzMNz0KNGFFlO7qTsL44k+1ClKCqHlmslm3W2mKQ3U\n UxSwR4mPS1jLdT4cG5DoWkYzkXb8jBNvzGak3ZIihUd9aTv9MWmEMS+X01QKwDIltRXFnrl6VcT\n QvQq1ZU5gUCiK6n/0Wn2U8hi7w1o0ZxeUm09mMAjBdGqxEvQ==",
        "X-Received": "by 2002:a05:7022:48c:b0:128:ca83:5aa3 with SMTP id\n a92af1059eb24-12c73f6d910mr1392057c88.1.1776432495513;\n Fri, 17 Apr 2026 06:28:15 -0700 (PDT)",
        "From": "Adhemerval Zanella <adhemerval.zanella@linaro.org>",
        "To": "libc-alpha@sourceware.org",
        "Cc": "Collin Funk <collin.funk1@gmail.com>,\n\tPaul Eggert <eggert@cs.ucla.edu>",
        "Subject": "[PATCH 1/3] io: Consolidate fts implementation",
        "Date": "Fri, 17 Apr 2026 10:24:55 -0300",
        "Message-ID": "<20260417132808.235562-2-adhemerval.zanella@linaro.org>",
        "X-Mailer": "git-send-email 2.43.0",
        "In-Reply-To": "<20260417132808.235562-1-adhemerval.zanella@linaro.org>",
        "References": "<20260417132808.235562-1-adhemerval.zanella@linaro.org>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "libc-alpha@sourceware.org",
        "X-Mailman-Version": "2.1.30",
        "Precedence": "list",
        "List-Id": "Libc-alpha mailing list <libc-alpha.sourceware.org>",
        "List-Unsubscribe": "<https://sourceware.org/mailman/options/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=unsubscribe>",
        "List-Archive": "<https://sourceware.org/pipermail/libc-alpha/>",
        "List-Post": "<mailto:libc-alpha@sourceware.org>",
        "List-Help": "<mailto:libc-alpha-request@sourceware.org?subject=help>",
        "List-Subscribe": "<https://sourceware.org/mailman/listinfo/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=subscribe>",
        "Errors-To": "libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org"
    },
    "content": "Remove wordsize-64 and arch-specific implementations, for ABIs when\noff_t is the same as off64_t (__OFF_T_MATCHES_OFF64_T) the fts64.c\nwill create the requires aliases.\n\nThe fts.c implementation is moved to fts-common.c to simplify\nthe __OFF_T_MATCHES_OFF64_T usage.\n---\n SHARED-FILES                                  |    2 +-\n io/fts-common.c                               | 2208 ++++++++++++++++\n io/fts.c                                      | 2217 +----------------\n io/fts64-time64.c                             |    2 +-\n io/fts64.c                                    |   38 +-\n sysdeps/unix/sysv/linux/mips/mips64/n64/fts.c |    1 -\n .../unix/sysv/linux/mips/mips64/n64/fts64.c   |    1 -\n sysdeps/unix/sysv/linux/x86_64/x32/fts.c      |    1 -\n sysdeps/unix/sysv/linux/x86_64/x32/fts64.c    |    1 -\n sysdeps/wordsize-64/fts.c                     |   19 -\n sysdeps/wordsize-64/fts64.c                   |    1 -\n 11 files changed, 2258 insertions(+), 2233 deletions(-)\n create mode 100644 io/fts-common.c\n delete mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fts.c\n delete mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fts64.c\n delete mode 100644 sysdeps/unix/sysv/linux/x86_64/x32/fts.c\n delete mode 100644 sysdeps/unix/sysv/linux/x86_64/x32/fts64.c\n delete mode 100644 sysdeps/wordsize-64/fts.c\n delete mode 100644 sysdeps/wordsize-64/fts64.c",
    "diff": "diff --git a/SHARED-FILES b/SHARED-FILES\nindex 126aaf096d..645040d7e1 100644\n--- a/SHARED-FILES\n+++ b/SHARED-FILES\n@@ -49,7 +49,7 @@ gnulib:\n   io/cycle-check.h\n   io/dev-ino.h\n   io/fts-cycle.c\n-  io/fts.c\n+  io/fts-common.c\n   io/i-ring.c\n   io/same-inode.h\n   locale/programs/3level.h\ndiff --git a/io/fts-common.c b/io/fts-common.c\nnew file mode 100644\nindex 0000000000..3825f0aeb4\n--- /dev/null\n+++ b/io/fts-common.c\n@@ -0,0 +1,2208 @@\n+/* Traverse a file hierarchy.\n+\n+   Copyright (C) 2004-2026 Free Software Foundation, Inc.\n+\n+   This file is free software: you can redistribute it and/or modify\n+   it under the terms of the GNU Lesser General Public License as\n+   published by the Free Software Foundation; either version 2.1 of the\n+   License, or (at your option) any later version.\n+\n+   This file is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+   GNU Lesser General Public License for more details.\n+\n+   You should have received a copy of the GNU Lesser General Public License\n+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */\n+\n+/*-\n+ * Copyright (c) 1990, 1993, 1994\n+ *      The Regents of the University of California.  All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or without\n+ * modification, are permitted provided that the following conditions\n+ * are met:\n+ * 1. Redistributions of source code must retain the above copyright\n+ *    notice, this list of conditions and the following disclaimer.\n+ * 2. Redistributions in binary form must reproduce the above copyright\n+ *    notice, this list of conditions and the following disclaimer in the\n+ *    documentation and/or other materials provided with the distribution.\n+ * 4. Neither the name of the University nor the names of its contributors\n+ *    may be used to endorse or promote products derived from this software\n+ *    without specific prior written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS \"AS IS\" AND\n+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n+ * SUCH DAMAGE.\n+ */\n+\n+#include <config.h>\n+\n+#if defined LIBC_SCCS && !defined GCC_LINT && !defined lint\n+static char sccsid[] = \"@(#)fts.c       8.6 (Berkeley) 8/14/94\";\n+#endif\n+\n+#if _LIBC\n+# include <fts.h>\n+#else\n+# include \"fts_.h\"\n+#endif\n+#if _LIBC || HAVE_SYS_PARAM_H\n+# include <sys/param.h>\n+#endif\n+#include <sys/stat.h>\n+#include <fcntl.h>\n+#include <errno.h>\n+#include <stddef.h>\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <unistd.h>\n+\n+/* Support for the LFS API version.  */\n+#ifndef FTS_OPEN\n+# define FTS_OPEN fts_open\n+# define FTS_CLOSE fts_close\n+# define FTS_READ fts_read\n+# define FTS_SET fts_set\n+# define FTS_CHILDREN fts_children\n+# define FTSOBJ FTS\n+# define FTSENTRY FTSENT\n+# define INO_T ino_t\n+# define STRUCT_STAT stat\n+# define FSTAT __fstat\n+# define FSTATAT __fstatat\n+# define STRUCT_STATFS statfs\n+# define FSTATFS __fstatfs\n+#endif\n+\n+#if ! _LIBC\n+# include \"attribute.h\"\n+# include \"fcntl--.h\"\n+# include \"openat.h\"\n+# include \"opendirat.h\"\n+# include \"same-inode.h\"\n+# define OPENDIRAT opendirat\n+# define FTSENT_WRAPPER(__p) __p\n+# define FTS_COMPAR_CAST(__fn) __fn\n+#else\n+# include <stdbool.h>\n+\n+# define internal_function\n+# define FALLTHROUGH               ; [[fallthrough]]\n+# define HAVE_STRUCT_DIRENT_D_TYPE 1\n+# define GNULIB_FTS_DEBUG          0\n+# ifdef O_PATH\n+#  define O_SEARCH                 O_PATH\n+# else\n+#  define O_SEARCH                 O_RDONLY\n+# endif\n+# define HAVE_SYS_VFS_H            1\n+# define HAVE_FSTATFS              1\n+# define HAVE_STRUCT_STATFS_F_TYPE 1\n+# define HAVE_OPENAT               1\n+# define HAVE_WORKING_O_NOFOLLOW   1\n+# define _GL_CMP(a, b)             ((a) < (b) ? -1 : (a) > (b))\n+# define OPENDIRAT                 __opendirat\n+\n+static inline bool openat_needs_fchdir (void)\n+{\n+  return false;\n+}\n+\n+static inline bool streq (const char *s1, const char *s2)\n+{\n+  return strcmp (s1, s2) == 0;\n+}\n+# define reallocarray              __libc_reallocarray\n+# define fchdir                    __fchdir\n+# define close                     __close\n+# define closedir                  __closedir\n+# define fcntl                     __fcntl\n+# define readdir                   __readdir\n+# ifndef dirfd\n+#  define dirfd                    __dirfd\n+# endif\n+# define open                      __open\n+# define openat                    __openat\n+\n+# include \"cycle-check.c\"\n+# include \"i-ring.c\"\n+\n+struct FTSENT_wrapper\n+{\n+  FTSOBJ *fts_fts;                /* the file hierarchy itself */\n+  DIR *fts_dirp;                  /* Dir pointer for any directory containing\n+\t\t\t\t     more entries than we read at one time.  */\n+  struct STRUCT_STAT fts_stat;\n+\n+  FTSENTRY ent;\n+};\n+\n+/* glibc historicaly defines the FTS::fts_compar as having 'void *', while the\n+   fts_open has a function point using 'FTSENT **' as argument.  */\n+# define FTS_COMPAR_CAST(__fn) ((int (*) (void const *, void const *))__fn)\n+\n+# define FTSENT_WRAPPER(p) \\\n+    ((struct FTSENT_wrapper *) ((char *)(p) - offsetof(struct FTSENT_wrapper, ent)))\n+#endif\n+#define FTSENT_FTS(p)   (FTSENT_WRAPPER(p)->fts_fts)\n+#define FTSENT_DIRP(p)  (FTSENT_WRAPPER(p)->fts_dirp)\n+\n+#include \"flexmember.h\"\n+\n+#include <dirent.h>\n+#ifndef _D_EXACT_NAMLEN\n+# define _D_EXACT_NAMLEN(dirent) strlen ((dirent)->d_name)\n+#endif\n+\n+#if HAVE_STRUCT_DIRENT_D_TYPE\n+/* True if the type of the directory entry D is known.  */\n+# define DT_IS_KNOWN(d) ((d)->d_type != DT_UNKNOWN)\n+/* True if the type of the directory entry D must be T.  */\n+# define DT_MUST_BE(d, t) ((d)->d_type == (t))\n+# define D_TYPE(d) ((d)->d_type)\n+#else\n+# define DT_IS_KNOWN(d) false\n+# define DT_MUST_BE(d, t) false\n+# define D_TYPE(d) DT_UNKNOWN\n+\n+# undef DT_UNKNOWN\n+# define DT_UNKNOWN 0\n+\n+/* Any nonzero values will do here, so long as they're distinct.\n+   Undef any existing macros out of the way.  */\n+# undef DT_BLK\n+# undef DT_CHR\n+# undef DT_DIR\n+# undef DT_FIFO\n+# undef DT_LNK\n+# undef DT_REG\n+# undef DT_SOCK\n+# define DT_BLK 1\n+# define DT_CHR 2\n+# define DT_DIR 3\n+# define DT_FIFO 4\n+# define DT_LNK 5\n+# define DT_REG 6\n+# define DT_SOCK 7\n+#endif\n+\n+#ifndef S_IFBLK\n+# define S_IFBLK 0\n+#endif\n+#ifndef S_IFLNK\n+# define S_IFLNK 0\n+#endif\n+#ifndef S_IFSOCK\n+# define S_IFSOCK 0\n+#endif\n+\n+enum\n+{\n+  NOT_AN_INODE_NUMBER = 0\n+};\n+\n+#ifdef D_INO_IN_DIRENT\n+# define D_INO(dp) (dp)->d_ino\n+#else\n+/* Some systems don't have inodes, so fake them to avoid lots of ifdefs.  */\n+# define D_INO(dp) NOT_AN_INODE_NUMBER\n+#endif\n+\n+/* If possible (see max_entries, below), read no more than this many directory\n+   entries at a time.  Without this limit (i.e., when using non-NULL\n+   fts_compar), processing a directory with 4,000,000 entries requires ~1GiB\n+   of memory, and handling 64M entries would require 16GiB of memory.  */\n+#ifndef FTS_MAX_READDIR_ENTRIES\n+# define FTS_MAX_READDIR_ENTRIES 100000\n+#endif\n+\n+/* If there are more than this many entries in a directory,\n+   and the conditions mentioned below are satisfied, then sort\n+   the entries on inode number before any further processing.  */\n+#ifndef FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD\n+# define FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD 10000\n+#endif\n+\n+enum\n+{\n+  _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD = FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD\n+};\n+\n+enum Fts_stat\n+{\n+  FTS_NO_STAT_REQUIRED = 1,\n+  FTS_STAT_REQUIRED = 2\n+};\n+\n+#ifndef __set_errno\n+# define __set_errno(Val) errno = (Val)\n+#endif\n+\n+/* If this host provides the openat function, then we can avoid\n+   attempting to open \".\" in some initialization code below.  */\n+#ifdef HAVE_OPENAT\n+# define HAVE_OPENAT_SUPPORT 1\n+#else\n+# define HAVE_OPENAT_SUPPORT 0\n+#endif\n+\n+#ifdef NDEBUG\n+# define fts_assert(expr) ((void) (0 && (expr)))\n+#else\n+# define fts_assert(expr)       \\\n+    do                          \\\n+      {                         \\\n+        if (!(expr))            \\\n+          abort ();             \\\n+      }                         \\\n+    while (false)\n+#endif\n+\n+static FTSENTRY  *fts_alloc (FTSOBJ *, const char *, size_t);\n+static FTSENTRY  *fts_build (FTSOBJ *, int);\n+static void      fts_lfree (FTSENTRY *);\n+static void      fts_load (FTSOBJ *, FTSENTRY *);\n+static size_t    fts_maxarglen (char * const *);\n+static void      fts_padjust (FTSOBJ *, FTSENTRY *);\n+static bool      fts_palloc (FTSOBJ *, size_t);\n+static FTSENTRY  *fts_sort (FTSOBJ *, FTSENTRY *, size_t);\n+static unsigned short int fts_stat (FTSOBJ *, FTSENTRY *, bool);\n+static int      fts_safe_changedir (FTSOBJ *, FTSENTRY *, int, const char *);\n+\n+#include \"fts-cycle.c\"\n+\n+#ifndef MAX\n+# define MAX(a,b) ((a) > (b) ? (a) : (b))\n+#endif\n+\n+#ifndef SIZE_MAX\n+# define SIZE_MAX ((size_t) -1)\n+#endif\n+\n+#define ISDOT(a)        (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))\n+\n+#define CLR(opt)        (sp->fts_options &= ~(opt))\n+#define ISSET(opt)      ((sp->fts_options & (opt)) != 0)\n+#define SET(opt)        (sp->fts_options |= (opt))\n+\n+/* FIXME: FTS_NOCHDIR is now misnamed.\n+   Call it FTS_USE_FULL_RELATIVE_FILE_NAMES instead. */\n+#define FCHDIR(sp, fd)                                  \\\n+  (!ISSET(FTS_NOCHDIR) && (ISSET(FTS_CWDFD)             \\\n+                           ? (cwd_advance_fd ((sp), (fd), true), 0) \\\n+                           : fchdir (fd)))\n+\n+\n+/* fts_build flags */\n+/* FIXME: make this an enum */\n+#define BCHILD          1               /* fts_children */\n+#define BNAMES          2               /* fts_children, names only */\n+#define BREAD           3               /* fts_read */\n+\n+#if GNULIB_FTS_DEBUG\n+# include <inttypes.h>\n+# include <stdio.h>\n+bool fts_debug = false;\n+# define Dprintf(x) do { if (fts_debug) printf x; } while (false)\n+static void fd_ring_check (FTSOBJ const *);\n+static void fd_ring_print (FTSOBJ const *, FILE *, char const *);\n+#else\n+# define Dprintf(x)\n+# define fd_ring_check(x)\n+# define fd_ring_print(a, b, c)\n+#endif\n+\n+#define LEAVE_DIR(Fts, Ent, Tag)                                \\\n+  do                                                            \\\n+    {                                                           \\\n+      Dprintf ((\"  %s-leaving: %s\\n\", Tag, (Ent)->fts_path));   \\\n+      leave_dir (Fts, Ent);                                     \\\n+      fd_ring_check (Fts);                                      \\\n+    }                                                           \\\n+  while (false)\n+\n+static void\n+fd_ring_clear (I_ring *fd_ring)\n+{\n+  while ( ! i_ring_empty (fd_ring))\n+    {\n+      int fd = i_ring_pop (fd_ring);\n+      if (0 <= fd)\n+        close (fd);\n+    }\n+}\n+\n+/* Overload the fts_statp->st_size member (otherwise unused, when\n+   fts_info is FTS_NSOK) to indicate whether fts_read should stat\n+   this entry or not.  */\n+static void\n+fts_set_stat_required (FTSENTRY *p, bool required)\n+{\n+  fts_assert (p->fts_info == FTS_NSOK);\n+  p->fts_statp->st_size = (required\n+                           ? FTS_STAT_REQUIRED\n+                           : FTS_NO_STAT_REQUIRED);\n+}\n+\n+/* Virtual fchdir.  Advance SP's working directory file descriptor,\n+   SP->fts_cwd_fd, to FD, and push the previous value onto the fd_ring.\n+   CHDIR_DOWN_ONE is true if FD corresponds to an entry in the directory\n+   open on sp->fts_cwd_fd; i.e., to move the working directory one level\n+   down.  */\n+static void\n+internal_function\n+cwd_advance_fd (FTSOBJ *sp, int fd, bool chdir_down_one)\n+{\n+  int old = sp->fts_cwd_fd;\n+  fts_assert (old != fd || old == AT_FDCWD);\n+\n+  if (chdir_down_one)\n+    {\n+      /* Push \"old\" onto the ring.\n+         If the displaced file descriptor is non-negative, close it.  */\n+      int prev_fd_in_slot = i_ring_push (&sp->fts_fd_ring, old);\n+      fd_ring_print (sp, stderr, \"post-push\");\n+      if (0 <= prev_fd_in_slot)\n+        close (prev_fd_in_slot); /* ignore any close failure */\n+    }\n+  else if ( ! ISSET (FTS_NOCHDIR))\n+    {\n+      if (0 <= old)\n+        close (old); /* ignore any close failure */\n+    }\n+\n+  sp->fts_cwd_fd = fd;\n+}\n+\n+/* Restore the initial, pre-traversal, \"working directory\".\n+   In FTS_CWDFD mode, we merely call cwd_advance_fd, otherwise,\n+   we may actually change the working directory.\n+   Return 0 upon success. Upon failure, set errno and return nonzero.  */\n+static int\n+restore_initial_cwd (FTSOBJ *sp)\n+{\n+  int fail = FCHDIR (sp, ISSET (FTS_CWDFD) ? AT_FDCWD : sp->fts_rfd);\n+  fd_ring_clear (&(sp->fts_fd_ring));\n+  return fail;\n+}\n+\n+/* Open the directory DIR if possible, and return a file\n+   descriptor.  Return -1 and set errno on failure.  It doesn't matter\n+   whether the file descriptor has read or write access.  */\n+\n+static int\n+internal_function\n+diropen (FTSOBJ const *sp, char const *dir)\n+{\n+  int open_flags = (O_SEARCH | O_CLOEXEC | O_DIRECTORY | O_NOCTTY | O_NONBLOCK\n+                    | (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0));\n+\n+  int fd = (ISSET (FTS_CWDFD)\n+            ? openat (sp->fts_cwd_fd, dir, open_flags)\n+            : open (dir, open_flags));\n+  return fd;\n+}\n+\n+FTSOBJ *\n+FTS_OPEN (char * const *argv,\n+          register int options,\n+          int (*compar) (const FTSENTRY **, const FTSENTRY **))\n+{\n+        /* Options check: glibc added other flags after FTS_NAMEONLY and\n+\t   FTS_STOP, and they are assumed to be private.  */\n+        if (options & ~FTS_OPTIONMASK\n+#if _LIBC\n+\t    || options & (FTS_NAMEONLY | FTS_STOP)\n+#endif\n+\t    ) {\n+                __set_errno (EINVAL);\n+                return (NULL);\n+        }\n+        if ((options & FTS_NOCHDIR) && (options & FTS_CWDFD)) {\n+                __set_errno (EINVAL);\n+                return (NULL);\n+        }\n+#if !_LIBC\n+        if ( ! (options & (FTS_LOGICAL | FTS_PHYSICAL))) {\n+                __set_errno (EINVAL);\n+                return (NULL);\n+        }\n+#else\n+\t/* glibc historically falls to FTS_PHYSICAL if no FTS_PHYSICAL or\n+\t   FTS_LOGICAL is specified.  */\n+        if (! (options & (FTS_PHYSICAL | FTS_LOGICAL)))\n+\t  options |= FTS_PHYSICAL;\n+#endif\n+\n+        /* Allocate/initialize the stream */\n+        register FTSOBJ *sp = calloc (1, sizeof *sp);\n+        if (sp == NULL)\n+                return (NULL);\n+        sp->fts_compar = FTS_COMPAR_CAST(compar);\n+        sp->fts_options = options;\n+\n+        /* Logical walks turn on NOCHDIR; symbolic links are too hard. */\n+        if (ISSET(FTS_LOGICAL)) {\n+                SET(FTS_NOCHDIR);\n+                CLR(FTS_CWDFD);\n+        }\n+\n+        /* Initialize fts_cwd_fd.  */\n+        sp->fts_cwd_fd = AT_FDCWD;\n+        if ( ISSET(FTS_CWDFD) && ! HAVE_OPENAT_SUPPORT)\n+          {\n+            /* While it isn't technically necessary to open \".\" this\n+               early, doing it here saves us the trouble of ensuring\n+               later (where it'd be messier) that \".\" can in fact\n+               be opened.  If not, revert to FTS_NOCHDIR mode.  */\n+            int fd = open (\".\", O_SEARCH | O_CLOEXEC);\n+            if (fd < 0)\n+              {\n+                /* Even if \".\" is unreadable, don't revert to FTS_NOCHDIR mode\n+                   on systems like Linux+PROC_FS, where our openat emulation\n+                   is good enough.  Note: on a system that emulates\n+                   openat via /proc, this technique can still fail, but\n+                   only in extreme conditions, e.g., when the working\n+                   directory cannot be saved (i.e. save_cwd fails) --\n+                   and that happens on Linux only when \".\" is unreadable\n+                   and the CWD would be longer than PATH_MAX.\n+                   FIXME: once Linux kernel openat support is well established,\n+                   replace the above open call and this entire if/else block\n+                   with the body of the if-block below.  */\n+                if ( openat_needs_fchdir ())\n+                  {\n+                    SET(FTS_NOCHDIR);\n+                    CLR(FTS_CWDFD);\n+                  }\n+              }\n+            else\n+              {\n+                close (fd);\n+              }\n+          }\n+\n+        /*\n+         * Start out with 1K of file name space, and enough, in any case,\n+         * to hold the user's file names.\n+         */\n+#ifndef MAXPATHLEN\n+# define MAXPATHLEN 1024\n+#endif\n+        {\n+          size_t maxarglen = fts_maxarglen(argv);\n+          if (! fts_palloc(sp, MAX(maxarglen, MAXPATHLEN)))\n+                  goto mem1;\n+        }\n+\n+        /* Allocate/initialize root's parent. */\n+        FTSENTRY *parent = NULL;\n+        if (*argv != NULL) {\n+                if ((parent = fts_alloc(sp, \"\", 0)) == NULL)\n+                        goto mem2;\n+                parent->fts_level = FTS_ROOTPARENTLEVEL;\n+          }\n+\n+        /* The classic fts implementation would call fts_stat with\n+           a new entry for each iteration of the loop below.\n+           If the comparison function is not specified or if the\n+           FTS_DEFER_STAT option is in effect, don't stat any entry\n+           in this loop.  This is an attempt to minimize the interval\n+           between the initial stat/lstat/fstatat and the point at which\n+           a directory argument is first opened.  This matters for any\n+           directory command line argument that resides on a file system\n+           without genuine i-nodes.  If you specify FTS_DEFER_STAT along\n+           with a comparison function, that function must not access any\n+           data via the fts_statp pointer.  */\n+        bool defer_stat = (compar == NULL || ISSET(FTS_DEFER_STAT));\n+\n+        /* Allocate/initialize root(s). */\n+        register FTSENTRY *root;\n+        register size_t nitems;\n+        FTSENTRY *tmp = NULL;     /* pacify gcc */\n+        for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {\n+                /* *Do* allow zero-length file names. */\n+                size_t len = strlen(*argv);\n+\n+                if ( ! (options & FTS_VERBATIM))\n+                  {\n+                    /* If there are two or more trailing slashes, trim all but one,\n+                       but don't change \"//\" to \"/\", and do map \"///\" to \"/\".  */\n+                    char const *v = *argv;\n+                    if (2 < len && v[len - 1] == '/')\n+                      while (1 < len && v[len - 2] == '/')\n+                        --len;\n+                  }\n+\n+                register FTSENTRY *p = fts_alloc(sp, *argv, len);\n+                if (p == NULL)\n+                        goto mem3;\n+                p->fts_level = FTS_ROOTLEVEL;\n+                p->fts_parent = parent;\n+                p->fts_accpath = p->fts_name;\n+                /* Even when defer_stat is true, be sure to stat the first\n+                   command line argument, since fts_read (at least with\n+                   FTS_XDEV) requires that.  */\n+                if (defer_stat && root != NULL) {\n+                        p->fts_info = FTS_NSOK;\n+                        fts_set_stat_required(p, true);\n+                } else {\n+                        p->fts_info = fts_stat(sp, p, false);\n+                }\n+\n+                /*\n+                 * If comparison routine supplied, traverse in sorted\n+                 * order; otherwise traverse in the order specified.\n+                 */\n+                if (compar) {\n+                        p->fts_link = root;\n+                        root = p;\n+                } else {\n+                        p->fts_link = NULL;\n+                        if (root == NULL)\n+                                tmp = root = p;\n+                        else {\n+                                tmp->fts_link = p;\n+                                tmp = p;\n+                        }\n+                }\n+        }\n+        if (compar && nitems > 1)\n+                root = fts_sort(sp, root, nitems);\n+\n+        /*\n+         * Allocate a dummy pointer and make fts_read think that we've just\n+         * finished the node before the root(s); set p->fts_info to FTS_INIT\n+         * so that everything about the \"current\" node is ignored.\n+         */\n+        if ((sp->fts_cur = fts_alloc(sp, \"\", 0)) == NULL)\n+                goto mem3;\n+        sp->fts_cur->fts_link = root;\n+        sp->fts_cur->fts_info = FTS_INIT;\n+        sp->fts_cur->fts_level = 1;\n+        if (! setup_dir (sp))\n+                goto mem3;\n+\n+        /*\n+         * If using chdir(2), grab a file descriptor pointing to dot to ensure\n+         * that we can get back here; this could be avoided for some file names,\n+         * but almost certainly not worth the effort.  Slashes, symbolic links,\n+         * and \"..\" are all fairly nasty problems.  Note, if we can't get the\n+         * descriptor we run anyway, just more slowly.\n+         */\n+        if (!ISSET(FTS_NOCHDIR) && !ISSET(FTS_CWDFD)\n+            && (sp->fts_rfd = diropen (sp, \".\")) < 0)\n+                SET(FTS_NOCHDIR);\n+\n+        i_ring_init (&sp->fts_fd_ring, -1);\n+        return (sp);\n+\n+mem3:   fts_lfree(root);\n+        free(FTSENT_WRAPPER(parent));\n+mem2:   free(sp->fts_path);\n+mem1:   free(sp);\n+        return (NULL);\n+}\n+\n+static void\n+internal_function\n+fts_load (FTSOBJ *sp, register FTSENTRY *p)\n+{\n+        /*\n+         * Load the stream structure for the next traversal.  Since we don't\n+         * actually enter the directory until after the preorder visit, set\n+         * the fts_accpath field specially so the chdir gets done to the right\n+         * place and the user can access the first node.  From fts_open it's\n+         * known that the file name will fit.\n+         */\n+        register size_t len = p->fts_pathlen = p->fts_namelen;\n+        memmove(sp->fts_path, p->fts_name, len + 1);\n+        register char *cp = strrchr(p->fts_name, '/');\n+        if (cp && (cp != p->fts_name || cp[1])) {\n+                len = strlen(++cp);\n+                memmove(p->fts_name, cp, len + 1);\n+                p->fts_namelen = len;\n+        }\n+        p->fts_accpath = p->fts_path = sp->fts_path;\n+}\n+\n+int\n+FTS_CLOSE (FTSOBJ *sp)\n+{\n+        /*\n+         * This still works if we haven't read anything -- the dummy structure\n+         * points to the root list, so we step through to the end of the root\n+         * list which has a valid parent pointer.\n+         */\n+        if (sp->fts_cur) {\n+                register FTSENTRY *p;\n+                for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {\n+                        register FTSENTRY *freep = p;\n+                        p = p->fts_link != NULL ? p->fts_link : p->fts_parent;\n+                        free(FTSENT_WRAPPER(freep));\n+                }\n+                free(FTSENT_WRAPPER(p));\n+        }\n+\n+        /* Free up child linked list, sort array, file name buffer. */\n+        if (sp->fts_child)\n+                fts_lfree(sp->fts_child);\n+        free(sp->fts_array);\n+        free(sp->fts_path);\n+\n+        int saved_errno = 0;\n+        if (ISSET(FTS_CWDFD))\n+          {\n+            if (0 <= sp->fts_cwd_fd)\n+              if (close (sp->fts_cwd_fd))\n+                saved_errno = errno;\n+          }\n+        else if (!ISSET(FTS_NOCHDIR))\n+          {\n+            /* Return to original directory, save errno if necessary. */\n+            if (fchdir(sp->fts_rfd))\n+              saved_errno = errno;\n+\n+            /* If close fails, record errno only if saved_errno is zero,\n+               so that we report the probably-more-meaningful fchdir errno.  */\n+            if (close (sp->fts_rfd))\n+              if (saved_errno == 0)\n+                saved_errno = errno;\n+          }\n+\n+        fd_ring_clear (&sp->fts_fd_ring);\n+\n+        if (sp->fts_leaf_optimization_works_ht)\n+          hash_free (sp->fts_leaf_optimization_works_ht);\n+\n+        free_dir (sp);\n+\n+        /* Free up the stream pointer. */\n+        free(sp);\n+\n+        /* Set errno and return. */\n+        if (saved_errno) {\n+                __set_errno (saved_errno);\n+                return (-1);\n+        }\n+\n+        return (0);\n+}\n+\n+/* Minimum link count of a traditional Unix directory.  When leaf\n+   optimization is OK and a directory's st_nlink == MIN_DIR_NLINK,\n+   then the directory has no subdirectories.  */\n+enum { MIN_DIR_NLINK = 2 };\n+\n+/* Whether leaf optimization is OK for a directory.  */\n+enum leaf_optimization\n+  {\n+    /* st_nlink is not reliable for this directory's subdirectories.  */\n+    NO_LEAF_OPTIMIZATION,\n+\n+    /* st_nlink == 2 means the directory lacks subdirectories.  */\n+    OK_LEAF_OPTIMIZATION\n+  };\n+\n+#if (defined __linux__ || defined __ANDROID__) \\\n+  && HAVE_SYS_VFS_H && HAVE_FSTATFS && HAVE_STRUCT_STATFS_F_TYPE\n+\n+# include <sys/vfs.h>\n+\n+/* Linux-specific constants from coreutils' src/fs.h */\n+# define S_MAGIC_AFS 0x5346414F\n+# define S_MAGIC_CIFS 0xFF534D42\n+# define S_MAGIC_LUSTRE 0x0BD00BD0\n+# define S_MAGIC_NFS 0x6969\n+# define S_MAGIC_PROC 0x9FA0\n+# define S_MAGIC_TMPFS 0x1021994\n+\n+# ifdef HAVE___FSWORD_T\n+typedef __fsword_t fsword;\n+# else\n+typedef long int fsword;\n+# endif\n+\n+/* Map a stat.st_dev number to a file system type number f_ftype.  */\n+struct dev_type\n+{\n+  dev_t st_dev;\n+  fsword f_type;\n+};\n+\n+/* Use a tiny initial size.  If a traversal encounters more than\n+   a few devices, the cost of growing/rehashing this table will be\n+   rendered negligible by the number of inodes processed.  */\n+enum { DEV_TYPE_HT_INITIAL_SIZE = 13 };\n+\n+static size_t\n+dev_type_hash (void const *x, size_t table_size)\n+{\n+  struct dev_type const *ax = x;\n+  uintmax_t dev = ax->st_dev;\n+  return dev % table_size;\n+}\n+\n+static bool\n+dev_type_compare (void const *x, void const *y)\n+{\n+  struct dev_type const *ax = x;\n+  struct dev_type const *ay = y;\n+  return ax->st_dev == ay->st_dev;\n+}\n+\n+/* Return the file system type of P with file descriptor FD, or 0 if not known.\n+   If FD is negative, P's file descriptor is unavailable.\n+   Try to cache known values.  */\n+\n+static fsword\n+filesystem_type (FTSENTRY const *p, int fd)\n+{\n+  FTSOBJ *sp = FTSENT_FTS(p);\n+\n+  /* If we're not in CWDFD mode, don't bother with this optimization,\n+     since the caller is not serious about performance.  */\n+  if (!ISSET (FTS_CWDFD))\n+    return 0;\n+\n+  Hash_table *h = sp->fts_leaf_optimization_works_ht;\n+  if (! h)\n+    h = sp->fts_leaf_optimization_works_ht\n+      = hash_initialize (DEV_TYPE_HT_INITIAL_SIZE, NULL, dev_type_hash,\n+                         dev_type_compare, free);\n+\n+  if (h)\n+    {\n+      struct dev_type tmp;\n+      tmp.st_dev = p->fts_statp->st_dev;\n+      struct dev_type *ent = hash_lookup (h, &tmp);\n+      if (ent)\n+        return ent->f_type;\n+    }\n+\n+  /* Look-up failed.  Query directly and cache the result.  */\n+  struct STRUCT_STATFS fs_buf;\n+  if (fd < 0 || FSTATFS (fd, &fs_buf) != 0)\n+    return 0;\n+\n+  if (h)\n+    {\n+      struct dev_type *t2 = malloc (sizeof *t2);\n+      if (t2)\n+        {\n+          t2->st_dev = p->fts_statp->st_dev;\n+          t2->f_type = fs_buf.f_type;\n+\n+          struct dev_type *ent = hash_insert (h, t2);\n+          if (ent)\n+            fts_assert (ent == t2);\n+          else\n+            free (t2);\n+        }\n+    }\n+\n+  return fs_buf.f_type;\n+}\n+\n+/* Return true if sorting dirents on inode numbers is known to improve\n+   traversal performance for the directory P with descriptor DIR_FD.\n+   Return false otherwise.  When in doubt, return true.\n+   DIR_FD is negative if unavailable.  */\n+static bool\n+dirent_inode_sort_may_be_useful (FTSENTRY const *p, int dir_fd)\n+{\n+  /* Skip the sort only if we can determine efficiently\n+     that skipping it is the right thing to do.\n+     The cost of performing an unnecessary sort is negligible,\n+     while the cost of *not* performing it can be O(N^2) with\n+     a very large constant.  */\n+\n+  switch (filesystem_type (p, dir_fd))\n+    {\n+    case S_MAGIC_LUSTRE:\n+      /* On Lustre, sorting directory entries interferes with its ability to\n+         prefetch file metadata (via statahead).  This would make a command\n+         like 'du' around 9 times slower.  See\n+         <https://bugs.gnu.org/80106>.  */\n+    case S_MAGIC_CIFS:\n+    case S_MAGIC_NFS:\n+    case S_MAGIC_TMPFS:\n+      /* On a file system of any of these types, sorting\n+         is unnecessary, and hence wasteful.  */\n+      return false;\n+\n+    default:\n+      return true;\n+    }\n+}\n+\n+/* Given an FTS entry P for a directory with descriptor DIR_FD,\n+   return whether it is valid to apply leaf optimization.\n+   The optimization is valid if a directory's st_nlink value equal\n+   to MIN_DIR_NLINK means the directory has no subdirectories.\n+   DIR_FD is negative if unavailable.  */\n+static enum leaf_optimization\n+leaf_optimization (FTSENTRY const *p, int dir_fd)\n+{\n+  switch (filesystem_type (p, dir_fd))\n+    {\n+    case 0:\n+      /* Leaf optimization is unsafe if the file system type is unknown.  */\n+      FALLTHROUGH;\n+    case S_MAGIC_AFS:\n+      /* Although AFS mount points are not counted in st_nlink, they\n+         act like directories.  See <https://bugs.debian.org/143111>.  */\n+      FALLTHROUGH;\n+    case S_MAGIC_CIFS:\n+      /* Leaf optimization causes 'find' to abort.  See\n+         <https://lists.gnu.org/r/bug-gnulib/2018-04/msg00015.html>.  */\n+      FALLTHROUGH;\n+    case S_MAGIC_NFS:\n+      /* NFS provides usable dirent.d_type but not necessarily for all entries\n+         of large directories, so as per <https://bugzilla.redhat.com/1252549>\n+         NFS should return true.  However st_nlink values are not accurate on\n+         all implementations as per <https://bugzilla.redhat.com/1299169>.  */\n+      FALLTHROUGH;\n+    case S_MAGIC_PROC:\n+      /* Per <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=143111> /proc\n+         may have bogus stat.st_nlink values.  */\n+      return NO_LEAF_OPTIMIZATION;\n+\n+    default:\n+      return OK_LEAF_OPTIMIZATION;\n+    }\n+}\n+\n+#else\n+static bool\n+dirent_inode_sort_may_be_useful (_GL_UNUSED FTSENTRY const *p,\n+                                 _GL_UNUSED int dir_fd)\n+{\n+  return true;\n+}\n+static enum leaf_optimization\n+leaf_optimization (_GL_UNUSED FTSENTRY const *p, _GL_UNUSED int dir_fd)\n+{\n+  return NO_LEAF_OPTIMIZATION;\n+}\n+#endif\n+\n+/*\n+ * Special case of \"/\" at the end of the file name so that slashes aren't\n+ * appended which would cause file names to be written as \"....//foo\".\n+ */\n+#define NAPPEND(p)                                                      \\\n+        (p->fts_path[p->fts_pathlen - 1] == '/'                         \\\n+            ? p->fts_pathlen - 1 : p->fts_pathlen)\n+\n+FTSENTRY *\n+FTS_READ (FTSOBJ *sp)\n+{\n+        /* If finished or unrecoverable error, return NULL. */\n+        if (sp->fts_cur == NULL || ISSET(FTS_STOP))\n+                return (NULL);\n+\n+        /* Set current node pointer. */\n+        register FTSENTRY *p = sp->fts_cur;\n+\n+        /* Save and zero out user instructions. */\n+        register unsigned short int instr = p->fts_instr;\n+        p->fts_instr = FTS_NOINSTR;\n+\n+        /* Any type of file may be re-visited; re-stat and re-turn. */\n+        if (instr == FTS_AGAIN) {\n+                p->fts_info = fts_stat(sp, p, false);\n+                return (p);\n+        }\n+        Dprintf ((\"fts_read: p=%s\\n\",\n+                  p->fts_info == FTS_INIT ? \"\" : p->fts_path));\n+\n+        /*\n+         * Following a symlink -- SLNONE test allows application to see\n+         * SLNONE and recover.  If indirecting through a symlink, have\n+         * keep a pointer to current location.  If unable to get that\n+         * pointer, follow fails.\n+         */\n+        if (instr == FTS_FOLLOW &&\n+            (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {\n+                p->fts_info = fts_stat(sp, p, true);\n+                if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {\n+                        if ((p->fts_symfd = diropen (sp, \".\")) < 0) {\n+                                p->fts_errno = errno;\n+                                p->fts_info = FTS_ERR;\n+                        } else\n+                                p->fts_flags |= FTS_SYMFOLLOW;\n+                }\n+                goto check_for_dir;\n+        }\n+\n+        /* Directory in pre-order. */\n+        if (p->fts_info == FTS_D) {\n+                /* If skipped or crossed mount point, do post-order visit. */\n+                if (instr == FTS_SKIP ||\n+                    (ISSET(FTS_XDEV) && p->fts_statp->st_dev != sp->fts_dev)) {\n+                        if (p->fts_flags & FTS_SYMFOLLOW)\n+                                (void)close(p->fts_symfd);\n+                        if (sp->fts_child) {\n+                                fts_lfree(sp->fts_child);\n+                                sp->fts_child = NULL;\n+                        }\n+                        p->fts_info = FTS_DP;\n+                        LEAVE_DIR (sp, p, \"1\");\n+                        return (p);\n+                }\n+\n+                /* Rebuild if only read the names and now traversing. */\n+                if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {\n+                        CLR(FTS_NAMEONLY);\n+                        fts_lfree(sp->fts_child);\n+                        sp->fts_child = NULL;\n+                }\n+\n+                /*\n+                 * Cd to the subdirectory.\n+                 *\n+                 * If have already read and now fail to chdir, whack the list\n+                 * to make the names come out right, and set the parent errno\n+                 * so the application will eventually get an error condition.\n+                 * Set the FTS_DONTCHDIR flag so that when we logically change\n+                 * directories back to the parent we don't do a chdir.\n+                 *\n+                 * If haven't read do so.  If the read fails, fts_build sets\n+                 * FTS_STOP or the fts_info field of the node.\n+                 */\n+                if (sp->fts_child != NULL) {\n+                        if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {\n+                                p->fts_errno = errno;\n+                                p->fts_flags |= FTS_DONTCHDIR;\n+                                for (p = sp->fts_child; p != NULL;\n+                                     p = p->fts_link)\n+                                        p->fts_accpath =\n+                                            p->fts_parent->fts_accpath;\n+                        }\n+                } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {\n+                        if (ISSET(FTS_STOP))\n+                                return (NULL);\n+                        /* If fts_build's call to fts_safe_changedir failed\n+                           because it was not able to fchdir into a\n+                           subdirectory, tell the caller.  */\n+                        if (p->fts_errno && p->fts_info != FTS_DNR)\n+                                p->fts_info = FTS_ERR;\n+                        LEAVE_DIR (sp, p, \"2\");\n+                        return (p);\n+                }\n+                p = sp->fts_child;\n+                sp->fts_child = NULL;\n+                goto name;\n+        }\n+\n+        /* Move to the next node on this level. */\n+next: ;\n+        register FTSENTRY *tmp = p;\n+\n+        /* If we have so many directory entries that we're reading them\n+           in batches, and we've reached the end of the current batch,\n+           read in a new batch.  */\n+        if (p->fts_link == NULL && FTSENT_DIRP(p->fts_parent))\n+          {\n+            p = tmp->fts_parent;\n+            sp->fts_cur = p;\n+            sp->fts_path[p->fts_pathlen] = '\\0';\n+\n+            if ((p = fts_build (sp, BREAD)) == NULL)\n+              {\n+                if (ISSET(FTS_STOP))\n+                  return NULL;\n+                goto cd_dot_dot;\n+              }\n+\n+            free(FTSENT_WRAPPER(tmp));\n+            goto name;\n+          }\n+\n+        if ((p = p->fts_link) != NULL) {\n+                sp->fts_cur = p;\n+                free(FTSENT_WRAPPER(tmp));\n+\n+                /*\n+                 * If reached the top, return to the original directory (or\n+                 * the root of the tree), and load the file names for the next\n+                 * root.\n+                 */\n+                if (p->fts_level == FTS_ROOTLEVEL) {\n+                        if (restore_initial_cwd(sp)) {\n+                                SET(FTS_STOP);\n+                                return (NULL);\n+                        }\n+                        free_dir(sp);\n+                        fts_load(sp, p);\n+                        if (! setup_dir(sp)) {\n+                                free_dir(sp);\n+                                return (NULL);\n+                        }\n+                        goto check_for_dir;\n+                }\n+\n+                /*\n+                 * User may have called fts_set on the node.  If skipped,\n+                 * ignore.  If followed, get a file descriptor so we can\n+                 * get back if necessary.\n+                 */\n+                if (p->fts_instr == FTS_SKIP)\n+                        goto next;\n+                if (p->fts_instr == FTS_FOLLOW) {\n+                        p->fts_info = fts_stat(sp, p, true);\n+                        if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {\n+                                if ((p->fts_symfd = diropen (sp, \".\")) < 0) {\n+                                        p->fts_errno = errno;\n+                                        p->fts_info = FTS_ERR;\n+                                } else\n+                                        p->fts_flags |= FTS_SYMFOLLOW;\n+                        }\n+                        p->fts_instr = FTS_NOINSTR;\n+                }\n+\n+name:           {\n+                  register char *t = sp->fts_path + NAPPEND(p->fts_parent);\n+                  *t++ = '/';\n+                  memmove(t, p->fts_name, p->fts_namelen + 1);\n+                }\n+check_for_dir:\n+                sp->fts_cur = p;\n+                if (p->fts_info == FTS_NSOK)\n+                  {\n+                    if (p->fts_statp->st_size == FTS_STAT_REQUIRED)\n+                      p->fts_info = fts_stat(sp, p, false);\n+                    else\n+                      fts_assert (p->fts_statp->st_size == FTS_NO_STAT_REQUIRED);\n+                  }\n+\n+                /* Skip files with different device numbers when FTS_MOUNT\n+                   is set.  */\n+                if (ISSET (FTS_MOUNT) && p->fts_info != FTS_NS &&\n+                    p->fts_level != FTS_ROOTLEVEL &&\n+                    p->fts_statp->st_dev != sp->fts_dev)\n+                      goto next;\n+\n+                if (p->fts_info == FTS_D)\n+                  {\n+                    /* Now that P->fts_statp is guaranteed to be valid, if\n+                       this is a command-line directory, record its device\n+                       number, to be used for FTS_MOUNT and FTS_XDEV.  */\n+                    if (p->fts_level == FTS_ROOTLEVEL)\n+                      sp->fts_dev = p->fts_statp->st_dev;\n+                    Dprintf ((\"  entering: %s\\n\", p->fts_path));\n+                    if (! enter_dir (sp, p))\n+                      return NULL;\n+                  }\n+                return p;\n+        }\n+cd_dot_dot:\n+\n+        /* Move up to the parent node. */\n+        p = tmp->fts_parent;\n+        sp->fts_cur = p;\n+        free(FTSENT_WRAPPER(tmp));\n+\n+        if (p->fts_level == FTS_ROOTPARENTLEVEL) {\n+                /*\n+                 * Done; free everything up and set errno to 0 so the user\n+                 * can distinguish between error and EOF.\n+                 */\n+                free(FTSENT_WRAPPER(p));\n+                __set_errno (0);\n+                return (sp->fts_cur = NULL);\n+        }\n+\n+        fts_assert (p->fts_info != FTS_NSOK);\n+\n+        /* NUL terminate the file name.  */\n+        sp->fts_path[p->fts_pathlen] = '\\0';\n+\n+        /*\n+         * Return to the parent directory.  If at a root node, restore\n+         * the initial working directory.  If we came through a symlink,\n+         * go back through the file descriptor.  Otherwise, move up\n+         * one level, via \"..\".\n+         */\n+        if (p->fts_level == FTS_ROOTLEVEL) {\n+                if (restore_initial_cwd(sp)) {\n+                        p->fts_errno = errno;\n+                        SET(FTS_STOP);\n+                }\n+        } else if (p->fts_flags & FTS_SYMFOLLOW) {\n+                if (FCHDIR(sp, p->fts_symfd)) {\n+                        p->fts_errno = errno;\n+                        SET(FTS_STOP);\n+                }\n+                (void)close(p->fts_symfd);\n+        } else if (!(p->fts_flags & FTS_DONTCHDIR) &&\n+                   fts_safe_changedir(sp, p->fts_parent, -1, \"..\")) {\n+                p->fts_errno = errno;\n+                SET(FTS_STOP);\n+        }\n+\n+        /* If the directory causes a cycle, preserve the FTS_DC flag and keep\n+           the corresponding dev/ino pair in the hash table.  It is going to be\n+           removed when leaving the original directory.  */\n+        if (p->fts_info != FTS_DC) {\n+                p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;\n+                if (p->fts_errno == 0)\n+                        LEAVE_DIR (sp, p, \"3\");\n+        }\n+        return ISSET(FTS_STOP) ? NULL : p;\n+}\n+\n+/*\n+ * Fts_set takes the stream as an argument although it's not used in this\n+ * implementation; it would be necessary if anyone wanted to add global\n+ * semantics to fts using fts_set.  An error return is allowed for similar\n+ * reasons.\n+ */\n+/* ARGSUSED */\n+int\n+FTS_SET (_GL_UNUSED FTSOBJ *sp, FTSENTRY *p, int instr)\n+{\n+        if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&\n+            instr != FTS_NOINSTR && instr != FTS_SKIP) {\n+                __set_errno (EINVAL);\n+                return (1);\n+        }\n+        p->fts_instr = instr;\n+        return (0);\n+}\n+\n+FTSENTRY *\n+FTS_CHILDREN (FTSOBJ *sp, int instr)\n+{\n+        if (instr != 0 && instr != FTS_NAMEONLY) {\n+                __set_errno (EINVAL);\n+                return (NULL);\n+        }\n+\n+        /* Set current node pointer. */\n+        register FTSENTRY *p = sp->fts_cur;\n+\n+        /*\n+         * Errno set to 0 so user can distinguish empty directory from\n+         * an error.\n+         */\n+        __set_errno (0);\n+\n+        /* Fatal errors stop here. */\n+        if (ISSET(FTS_STOP))\n+                return (NULL);\n+\n+        /* Return logical hierarchy of user's arguments. */\n+        if (p->fts_info == FTS_INIT)\n+                return (p->fts_link);\n+\n+        /*\n+         * If not a directory being visited in pre-order, stop here.  Could\n+         * allow FTS_DNR, assuming the user has fixed the problem, but the\n+         * same effect is available with FTS_AGAIN.\n+         */\n+        if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)\n+                return (NULL);\n+\n+        /* Free up any previous child list. */\n+        if (sp->fts_child != NULL)\n+                fts_lfree(sp->fts_child);\n+\n+        if (instr == FTS_NAMEONLY) {\n+                SET(FTS_NAMEONLY);\n+                instr = BNAMES;\n+        } else\n+                instr = BCHILD;\n+\n+        /*\n+         * If using chdir on a relative file name and called BEFORE fts_read\n+         * does its chdir to the root of a traversal, we can lose -- we need to\n+         * chdir into the subdirectory, and we don't know where the current\n+         * directory is, so we can't get back so that the upcoming chdir by\n+         * fts_read will work.\n+         */\n+        if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||\n+            ISSET(FTS_NOCHDIR))\n+                return (sp->fts_child = fts_build(sp, instr));\n+\n+        int fd = diropen (sp, \".\");\n+        if (fd < 0)\n+                return (sp->fts_child = NULL);\n+        sp->fts_child = fts_build(sp, instr);\n+        if (ISSET(FTS_CWDFD))\n+          {\n+            cwd_advance_fd (sp, fd, true);\n+          }\n+        else\n+          {\n+            if (fchdir(fd))\n+              {\n+                int saved_errno = errno;\n+                close (fd);\n+                __set_errno (saved_errno);\n+                return NULL;\n+              }\n+            close (fd);\n+          }\n+        return (sp->fts_child);\n+}\n+\n+/* A comparison function to sort on increasing inode number.\n+   For some file system types, sorting either way makes a huge\n+   performance difference for a directory with very many entries,\n+   but sorting on increasing values is slightly better than sorting\n+   on decreasing values.  The difference is in the 5% range.  */\n+static int\n+fts_compare_ino (FTSENTRY const **a, FTSENTRY const **b)\n+{\n+  return _GL_CMP (a[0]->fts_statp->st_ino, b[0]->fts_statp->st_ino);\n+}\n+\n+/* Map the dirent.d_type value, DTYPE, to the corresponding stat.st_mode\n+   S_IF* bit and set ST.st_mode, thus clearing all other bits in that field.  */\n+static void\n+set_stat_type (struct STRUCT_STAT *st, unsigned int dtype)\n+{\n+  mode_t type;\n+  switch (dtype)\n+    {\n+    case DT_BLK:\n+      type = S_IFBLK;\n+      break;\n+    case DT_CHR:\n+      type = S_IFCHR;\n+      break;\n+    case DT_DIR:\n+      type = S_IFDIR;\n+      break;\n+    case DT_FIFO:\n+      type = S_IFIFO;\n+      break;\n+    case DT_LNK:\n+      type = S_IFLNK;\n+      break;\n+    case DT_REG:\n+      type = S_IFREG;\n+      break;\n+    case DT_SOCK:\n+      type = S_IFSOCK;\n+      break;\n+    default:\n+      type = 0;\n+    }\n+  st->st_mode = type;\n+}\n+\n+#define closedir_and_clear(dirp)                \\\n+  do                                            \\\n+    {                                           \\\n+      closedir (dirp);                          \\\n+      dirp = NULL;                              \\\n+    }                                           \\\n+  while (0)\n+\n+#define fts_opendir(file, Pdir_fd)                              \\\n+        OPENDIRAT((! ISSET(FTS_NOCHDIR) && ISSET(FTS_CWDFD)     \\\n+                   ? sp->fts_cwd_fd : AT_FDCWD),                \\\n+                  file,                                         \\\n+                  (((ISSET(FTS_PHYSICAL)                        \\\n+                     && ! (ISSET(FTS_COMFOLLOW)                 \\\n+                           && cur->fts_level == FTS_ROOTLEVEL)) \\\n+                    ? O_NOFOLLOW : 0)),                         \\\n+                  Pdir_fd)\n+\n+/*\n+ * This is the tricky part -- do not casually change *anything* in here.  The\n+ * idea is to build the linked list of entries that are used by fts_children\n+ * and fts_read.  There are lots of special cases.\n+ *\n+ * The real slowdown in walking the tree is the stat calls.  If FTS_NOSTAT is\n+ * set and it's a physical walk (so that symbolic links can't be directories),\n+ * we can do things quickly.  First, if it's a 4.4BSD file system, the type\n+ * of the file is in the directory entry.  Otherwise, we assume that the number\n+ * of subdirectories in a node is equal to the number of links to the parent.\n+ * The former skips all stat calls.  The latter skips stat calls in any leaf\n+ * directories and for any files after the subdirectories in the directory have\n+ * been found, cutting the stat calls by about 2/3.\n+ */\n+static FTSENTRY *\n+internal_function\n+fts_build (register FTSOBJ *sp, int type)\n+{\n+        FTSENTRY *cur = sp->fts_cur;\n+        bool continue_readdir = !!FTSENT_DIRP(cur);\n+\n+        /* When cur->fts_dirp is non-NULL, that means we should\n+           continue calling readdir on that existing DIR* pointer\n+           rather than opening a new one.  */\n+        int dir_fd;\n+        if (continue_readdir)\n+          {\n+            DIR *dp = FTSENT_DIRP(cur);\n+            dir_fd = dirfd (dp);\n+            if (dir_fd < 0)\n+              {\n+                int dirfd_errno = errno;\n+                closedir_and_clear (FTSENT_DIRP(cur));\n+                if (type == BREAD)\n+                  {\n+                    cur->fts_info = FTS_DNR;\n+                    cur->fts_errno = dirfd_errno;\n+                  }\n+                return NULL;\n+              }\n+          }\n+        else\n+          {\n+            /* Open the directory for reading.  If this fails, we're done.\n+               If being called from fts_read, set the fts_info field. */\n+            if ((FTSENT_DIRP (cur) = fts_opendir(cur->fts_accpath, &dir_fd)) == NULL)\n+              {\n+                if (type == BREAD)\n+                  {\n+                    cur->fts_info = FTS_DNR;\n+                    cur->fts_errno = errno;\n+                  }\n+                return NULL;\n+              }\n+            /* Rather than calling fts_stat for each and every entry encountered\n+               in the readdir loop (below), stat each directory only right after\n+               opening it.  */\n+            bool stat_optimization = cur->fts_info == FTS_NSOK;\n+\n+            if (stat_optimization\n+                /* Also read the stat info again after opening a directory to\n+                   reveal eventual changes caused by a submount triggered by\n+                   the traversal.  But do it only for utilities which use\n+                   FTS_TIGHT_CYCLE_CHECK.  Therefore, only find and du\n+                   benefit/suffer from this feature for now.  */\n+                || ISSET (FTS_TIGHT_CYCLE_CHECK))\n+              {\n+                if (!stat_optimization)\n+                  LEAVE_DIR (sp, cur, \"4\");\n+                if (FSTAT (dir_fd, cur->fts_statp) != 0)\n+                  {\n+                    int fstat_errno = errno;\n+                    closedir_and_clear (FTSENT_DIRP(cur));\n+                    if (type == BREAD)\n+                      {\n+                        cur->fts_errno = fstat_errno;\n+                        cur->fts_info = FTS_NS;\n+                      }\n+                    __set_errno (fstat_errno);\n+                    return NULL;\n+                  }\n+                if (stat_optimization)\n+                  cur->fts_info = FTS_D;\n+                else if (! enter_dir (sp, cur))\n+                  {\n+                    int saved_errno = errno;\n+                    closedir_and_clear (FTSENT_DIRP(cur));\n+                    __set_errno (saved_errno);\n+                    return NULL;\n+                  }\n+              }\n+          }\n+\n+        /* Maximum number of readdir entries to read at one time.  This\n+           limitation is to avoid reading millions of entries into memory\n+           at once.  When an fts_compar function is specified, we have no\n+           choice: we must read all entries into memory before calling that\n+           function.  But when no such function is specified, we can read\n+           entries in batches that are large enough to help us with inode-\n+           sorting, yet not so large that we risk exhausting memory.  */\n+        size_t max_entries = sp->fts_compar ? SIZE_MAX : FTS_MAX_READDIR_ENTRIES;\n+\n+        /*\n+         * If we're going to need to stat anything or we want to descend\n+         * and stay in the directory, chdir.  If this fails we keep going,\n+         * but set a flag so we don't chdir after the post-order visit.\n+         * We won't be able to stat anything, but we can still return the\n+         * names themselves.  Note, that since fts_read won't be able to\n+         * chdir into the directory, it will have to return different file\n+         * names than before, i.e. \"a/b\" instead of \"b\".  Since the node\n+         * has already been visited in pre-order, have to wait until the\n+         * post-order visit to return the error.  There is a special case\n+         * here, if there was nothing to stat then it's not an error to\n+         * not be able to stat.  This is all fairly nasty.  If a program\n+         * needed sorted entries or stat information, they had better be\n+         * checking FTS_NS on the returned nodes.\n+         */\n+        bool descend;\n+        if (continue_readdir)\n+          {\n+            /* When resuming a short readdir run, we already have\n+               the required dirp and dir_fd.  */\n+            descend = true;\n+          }\n+        else\n+          {\n+            /* Try to descend unless it is a names-only fts_children,\n+               or the directory is known to lack subdirectories.  */\n+            descend = (type != BNAMES\n+                       && ! (ISSET (FTS_NOSTAT) && ISSET (FTS_PHYSICAL)\n+                             && ! ISSET (FTS_SEEDOT)\n+                             && cur->fts_statp->st_nlink == MIN_DIR_NLINK\n+                             && (leaf_optimization (cur, dir_fd)\n+                                 != NO_LEAF_OPTIMIZATION)));\n+            if (descend || type == BREAD)\n+              {\n+                if (ISSET(FTS_CWDFD))\n+                  dir_fd = fcntl (dir_fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1);\n+                if (dir_fd < 0 || fts_safe_changedir(sp, cur, dir_fd, NULL)) {\n+                        if (descend && type == BREAD)\n+                                cur->fts_errno = errno;\n+                        cur->fts_flags |= FTS_DONTCHDIR;\n+                        descend = false;\n+                        closedir_and_clear(FTSENT_DIRP(cur));\n+                        if (ISSET(FTS_CWDFD) && 0 <= dir_fd)\n+                                close (dir_fd);\n+                        FTSENT_DIRP(cur) = NULL;\n+                } else\n+                        descend = true;\n+              }\n+          }\n+\n+        /*\n+         * Figure out the max file name length that can be stored in the\n+         * current buffer -- the inner loop allocates more space as necessary.\n+         * We really wouldn't have to do the maxlen calculations here, we\n+         * could do them in fts_read before returning the name, but it's a\n+         * lot easier here since the length is part of the dirent structure.\n+         *\n+         * If not changing directories set a pointer so that can just append\n+         * each new component into the file name.\n+         */\n+        size_t len = NAPPEND(cur);\n+        char *cp;\n+        if (ISSET(FTS_NOCHDIR)) {\n+                cp = sp->fts_path + len;\n+                *cp++ = '/';\n+        } else {\n+                /* GCC, you're too verbose. */\n+                cp = NULL;\n+        }\n+        len++;\n+        size_t maxlen = sp->fts_pathlen - len;\n+\n+        ptrdiff_t level = cur->fts_level + 1;\n+\n+        /* Read the directory, attaching each entry to the \"link\" pointer. */\n+        bool doadjust = false;\n+        register FTSENTRY *head = NULL;\n+        FTSENTRY *tail = NULL;\n+        register size_t nitems = 0;\n+        bool sort_by_inode = false;\n+        while (FTSENT_DIRP(cur)) {\n+                __set_errno (0);\n+                struct dirent *dp = readdir(FTSENT_DIRP(cur));\n+                if (dp == NULL) {\n+                        /* Some readdir()s do not absorb ENOENT (dir\n+                           deleted but open).  This bug was fixed in\n+                           glibc 2.3 (2002).  */\n+#if ! (2 < __GLIBC__ + (3 <= __GLIBC_MINOR__))\n+                        if (errno == ENOENT)\n+                          errno = 0;\n+#endif\n+                        if (errno) {\n+                                cur->fts_errno = errno;\n+                                /* If we've not read any items yet, treat\n+                                   the error as if we can't access the dir.  */\n+                                cur->fts_info = (continue_readdir || nitems)\n+                                                ? FTS_ERR : FTS_DNR;\n+                        }\n+                        closedir_and_clear(FTSENT_DIRP(cur));\n+                        break;\n+                }\n+                if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))\n+                        continue;\n+\n+                size_t d_namelen = _D_EXACT_NAMLEN (dp);\n+                register FTSENTRY *p = fts_alloc (sp, dp->d_name, d_namelen);\n+                if (!p)\n+                        goto mem1;\n+                if (d_namelen >= maxlen) {\n+                        /* include space for NUL */\n+                        uintptr_t oldaddr = (uintptr_t) sp->fts_path;\n+                        if (! fts_palloc(sp, d_namelen + len + 1)) {\n+                                /*\n+                                 * No more memory.  Save\n+                                 * errno, free up the current structure and the\n+                                 * structures already allocated.\n+                                 */\n+mem1: ;\n+                                int saved_errno = errno;\n+                                free(FTSENT_WRAPPER(p));\n+                                fts_lfree(head);\n+                                closedir_and_clear(FTSENT_DIRP(cur));\n+                                cur->fts_info = FTS_ERR;\n+                                SET(FTS_STOP);\n+                                __set_errno (saved_errno);\n+                                return (NULL);\n+                        }\n+                        /* Did realloc() change the pointer? */\n+                        if (oldaddr != (uintptr_t) sp->fts_path) {\n+                                doadjust = true;\n+                                if (ISSET(FTS_NOCHDIR))\n+                                        cp = sp->fts_path + len;\n+                        }\n+                        maxlen = sp->fts_pathlen - len;\n+                }\n+\n+                size_t new_len = len + d_namelen;\n+                if (new_len < len) {\n+                        /*\n+                         * In the unlikely event that we would end up\n+                         * with a file name longer than SIZE_MAX, free up\n+                         * the current structure and the structures already\n+                         * allocated, then error out with ENAMETOOLONG.\n+                         */\n+                        free(FTSENT_WRAPPER(p));\n+                        fts_lfree(head);\n+                        closedir_and_clear(FTSENT_DIRP(cur));\n+                        cur->fts_info = FTS_ERR;\n+                        SET(FTS_STOP);\n+                        __set_errno (ENAMETOOLONG);\n+                        return (NULL);\n+                }\n+                p->fts_level = level;\n+                p->fts_parent = sp->fts_cur;\n+                p->fts_pathlen = new_len;\n+\n+                /* Store dirent.d_ino, in case we need to sort\n+                   entries before processing them.  */\n+                p->fts_statp->st_ino = D_INO (dp);\n+\n+                /* Build a file name for fts_stat to stat. */\n+                if (ISSET(FTS_NOCHDIR)) {\n+                        p->fts_accpath = p->fts_path;\n+                        memmove(cp, p->fts_name, p->fts_namelen + 1);\n+                } else\n+                        p->fts_accpath = p->fts_name;\n+\n+                if (sp->fts_compar == NULL || ISSET(FTS_DEFER_STAT)) {\n+                        /* Record what fts_read will have to do with this\n+                           entry. In many cases, it will simply fts_stat it,\n+                           but we can take advantage of any d_type information\n+                           to optimize away the unnecessary stat calls.  I.e.,\n+                           if FTS_NOSTAT is in effect, we don't need device\n+                           numbers unconditionally (FTS_MOUNT) and we're not\n+                           following symlinks (FTS_PHYSICAL) and d_type\n+                           indicates this is *not* a directory, then we won't\n+                           have to stat it  at all.  If it *is* a directory,\n+                           then (currently) we stat it regardless, in order to\n+                           get device and inode numbers.  Some day we might\n+                           optimize that away, too, for directories where\n+                           d_ino is known to be valid.  */\n+                        bool skip_stat = (ISSET(FTS_NOSTAT)\n+                                          && DT_IS_KNOWN(dp)\n+                                          && ! DT_MUST_BE(dp, DT_DIR)\n+                                          && (ISSET(FTS_PHYSICAL)\n+                                              || ! DT_MUST_BE(dp, DT_LNK))\n+                                          && ! ISSET(FTS_MOUNT));\n+                        p->fts_info = FTS_NSOK;\n+                        /* Propagate dirent.d_type information back\n+                           to caller, when possible.  */\n+                        set_stat_type (p->fts_statp, D_TYPE (dp));\n+                        fts_set_stat_required(p, !skip_stat);\n+                } else {\n+                        p->fts_info = fts_stat(sp, p, false);\n+                }\n+\n+                /* We walk in directory order so \"ls -f\" doesn't get upset. */\n+                p->fts_link = NULL;\n+                if (head == NULL)\n+                        head = tail = p;\n+                else {\n+                        tail->fts_link = p;\n+                        tail = p;\n+                }\n+\n+                /* If there are many entries, no sorting function has been\n+                   specified, and this file system is of a type that may be\n+                   slow with a large number of entries, arrange to sort the\n+                   directory entries on increasing inode numbers.\n+\n+                   The NITEMS comparison uses ==, not >, because the test\n+                   needs to be tried at most once once, and NITEMS will exceed\n+                   the threshold after it is incremented below.  */\n+                if (nitems == _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD\n+                    && !sp->fts_compar)\n+                  sort_by_inode = dirent_inode_sort_may_be_useful (cur, dir_fd);\n+\n+                ++nitems;\n+                if (max_entries <= nitems) {\n+                        /* When there are too many dir entries, leave\n+                           fts_dirp open, so that a subsequent fts_read\n+                           can take up where we leave off.  */\n+                        break;\n+                }\n+        }\n+\n+        /*\n+         * If realloc() changed the address of the file name, adjust the\n+         * addresses for the rest of the tree and the dir list.\n+         */\n+        if (doadjust)\n+                fts_padjust(sp, head);\n+\n+        /*\n+         * If not changing directories, reset the file name back to original\n+         * state.\n+         */\n+        if (ISSET(FTS_NOCHDIR)) {\n+                if (len == sp->fts_pathlen || nitems == 0)\n+                        --cp;\n+                *cp = '\\0';\n+        }\n+\n+        /*\n+         * If descended after called from fts_children or after called from\n+         * fts_read and nothing found, get back.  At the root level we use\n+         * the saved fd; if one of fts_open()'s arguments is a relative name\n+         * to an empty directory, we wind up here with no other way back.  If\n+         * can't get back, we're done.\n+         */\n+        if (!continue_readdir && descend && (type == BCHILD || !nitems) &&\n+            (cur->fts_level == FTS_ROOTLEVEL\n+             ? restore_initial_cwd(sp)\n+             : fts_safe_changedir(sp, cur->fts_parent, -1, \"..\"))) {\n+                cur->fts_info = FTS_ERR;\n+                SET(FTS_STOP);\n+                fts_lfree(head);\n+                return (NULL);\n+        }\n+\n+        /* If didn't find anything, return NULL. */\n+        if (!nitems) {\n+                if (type == BREAD\n+                    && cur->fts_info != FTS_DNR && cur->fts_info != FTS_ERR)\n+                        cur->fts_info = FTS_DP;\n+                fts_lfree(head);\n+                return (NULL);\n+        }\n+\n+        if (sort_by_inode) {\n+                sp->fts_compar = FTS_COMPAR_CAST (fts_compare_ino);\n+                head = fts_sort (sp, head, nitems);\n+                sp->fts_compar = NULL;\n+        }\n+\n+        /* Sort the entries. */\n+        if (sp->fts_compar && nitems > 1)\n+                head = fts_sort(sp, head, nitems);\n+        return (head);\n+}\n+\n+#if GNULIB_FTS_DEBUG\n+\n+struct devino {\n+  intmax_t dev, ino;\n+};\n+#define PRINT_DEVINO \"(%jd,%jd)\"\n+\n+static struct devino\n+getdevino (int fd)\n+{\n+  struct STRUCT_STAT st;\n+  return (fd == AT_FDCWD\n+          ? (struct devino) { -1, 0 }\n+          : FSTAT (fd, &st) == 0\n+          ? (struct devino) { st.st_dev, st.st_ino }\n+          : (struct devino) { -1, errno });\n+}\n+\n+/* Walk ->fts_parent links starting at E_CURR, until the root of the\n+   current hierarchy.  There should be a directory with dev/inode\n+   matching those of AD.  If not, print a lot of diagnostics.  */\n+static void\n+find_matching_ancestor (FTSENTRY const *e_curr, struct Active_dir const *ad)\n+{\n+  for (FTSENTRY const *ent = e_curr;\n+       ent->fts_level >= FTS_ROOTLEVEL;\n+       ent = ent->fts_parent)\n+    {\n+      if (ad->ino == ent->fts_statp->st_ino\n+          && ad->dev == ent->fts_statp->st_dev)\n+        return;\n+    }\n+  printf (\"ERROR: tree dir, %s, not active\\n\", ad->fts_ent->fts_accpath);\n+  printf (\"active dirs:\\n\");\n+  for (FTSENTRY const *ent = e_curr;\n+       ent->fts_level >= FTS_ROOTLEVEL;\n+       ent = ent->fts_parent)\n+    printf (\"  %s(%\"PRIuMAX\"/%\"PRIuMAX\") to %s(%\"PRIuMAX\"/%\"PRIuMAX\")...\\n\",\n+            ad->fts_ent->fts_accpath,\n+            (uintmax_t) ad->dev,\n+            (uintmax_t) ad->ino,\n+            ent->fts_accpath,\n+            (uintmax_t) ent->fts_statp->st_dev,\n+            (uintmax_t) ent->fts_statp->st_ino);\n+}\n+\n+void\n+fts_cross_check (FTSOBJ const *sp)\n+{\n+  if ( ! ISSET (FTS_TIGHT_CYCLE_CHECK))\n+    return;\n+\n+  FTSENTRY const *ent = sp->fts_cur;\n+\n+  Dprintf ((\"fts-cross-check cur=%s\\n\", ent->fts_path));\n+  /* Make sure every parent dir is in the tree.  */\n+  for (FTSENTRY const *t = ent->fts_parent;\n+       t->fts_level >= FTS_ROOTLEVEL;\n+       t = t->fts_parent)\n+    {\n+      struct Active_dir ad;\n+      ad.ino = t->fts_statp->st_ino;\n+      ad.dev = t->fts_statp->st_dev;\n+      if ( ! hash_lookup (sp->fts_cycle.ht, &ad))\n+        printf (\"ERROR: active dir, %s, not in tree\\n\", t->fts_path);\n+    }\n+\n+  /* Make sure every dir in the tree is an active dir.\n+     But ENT is not necessarily a directory.  If so, just skip this part. */\n+  if (ent->fts_parent->fts_level >= FTS_ROOTLEVEL\n+      && (ent->fts_info == FTS_DP\n+          || ent->fts_info == FTS_D))\n+    for (struct Active_dir *ad = hash_get_first (sp->fts_cycle.ht);\n+         ad != NULL;\n+         ad = hash_get_next (sp->fts_cycle.ht, ad))\n+      {\n+        find_matching_ancestor (ent, ad);\n+      }\n+}\n+\n+static bool\n+same_fd (int fd1, int fd2)\n+{\n+  struct STRUCT_STAT sb1, sb2;\n+  return (FSTAT (fd1, &sb1) == 0\n+          && FSTAT (fd2, &sb2) == 0\n+          && psame_inode (&sb1, &sb2));\n+}\n+\n+static void\n+fd_ring_print (FTSOBJ const *sp, FILE *stream, char const *msg)\n+{\n+  if (!fts_debug)\n+    return;\n+  I_ring const *fd_ring = &sp->fts_fd_ring;\n+  struct devino cwd = getdevino (sp->fts_cwd_fd);\n+  fprintf (stream, \"=== %s ========== \"PRINT_DEVINO\"\\n\", msg, cwd.dev, cwd.ino);\n+  if (i_ring_empty (fd_ring))\n+    return;\n+\n+  unsigned int i = fd_ring->ir_front;\n+  while (true)\n+    {\n+      int fd = fd_ring->ir_data[i];\n+      if (fd < 0)\n+        fprintf (stream, \"%u: %d:\\n\", i, fd);\n+      else\n+        {\n+          struct devino wd = getdevino (fd);\n+          fprintf (stream, \"%u: %d: \"PRINT_DEVINO\"\\n\", i, fd, wd.dev, wd.ino);\n+        }\n+      if (i == fd_ring->ir_back)\n+        break;\n+      i = (i + I_RING_SIZE - 1) % I_RING_SIZE;\n+    }\n+}\n+\n+/* Ensure that each file descriptor on the fd_ring matches a\n+   parent, grandparent, etc. of the current working directory.  */\n+static void\n+fd_ring_check (FTSOBJ const *sp)\n+{\n+  if (!fts_debug)\n+    return;\n+\n+  /* Make a writable copy.  */\n+  I_ring fd_w = sp->fts_fd_ring;\n+\n+  int cwd_fd = sp->fts_cwd_fd;\n+  cwd_fd = fcntl (cwd_fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1);\n+  struct devino dot = getdevino (cwd_fd);\n+  fprintf (stderr, \"===== check ===== cwd: \"PRINT_DEVINO\"\\n\",\n+           dot.dev, dot.ino);\n+  while ( ! i_ring_empty (&fd_w))\n+    {\n+      int fd = i_ring_pop (&fd_w);\n+      if (0 <= fd)\n+        {\n+          int open_flags = O_SEARCH | O_CLOEXEC;\n+          int parent_fd = openat (cwd_fd, \"..\", open_flags);\n+          if (parent_fd < 0)\n+            {\n+              // Warn?\n+              break;\n+            }\n+          if (!same_fd (fd, parent_fd))\n+            {\n+              struct devino cwd = getdevino (fd);\n+              fprintf (stderr, \"ring  : \"PRINT_DEVINO\"\\n\", cwd.dev, cwd.ino);\n+              struct devino c2 = getdevino (parent_fd);\n+              fprintf (stderr, \"parent: \"PRINT_DEVINO\"\\n\", c2.dev, c2.ino);\n+              fts_assert (0);\n+            }\n+          close (cwd_fd);\n+          cwd_fd = parent_fd;\n+        }\n+    }\n+  close (cwd_fd);\n+}\n+#endif\n+\n+static unsigned short int\n+internal_function\n+fts_stat(FTSOBJ *sp, register FTSENTRY *p, bool follow)\n+{\n+        if (ISSET (FTS_LOGICAL)\n+            || (ISSET (FTS_COMFOLLOW) && p->fts_level == FTS_ROOTLEVEL))\n+                follow = true;\n+\n+        struct STRUCT_STAT *sbp = p->fts_statp;\n+\n+        /*\n+         * If doing a logical walk, or application requested FTS_FOLLOW, do\n+         * a stat(2).  If that fails, check for a nonexistent symlink.  If\n+         * fail, set the errno from the stat call.\n+         */\n+        int flags = follow ? 0 : AT_SYMLINK_NOFOLLOW;\n+        if (FSTATAT (sp->fts_cwd_fd, p->fts_accpath, sbp, flags) < 0)\n+          {\n+            if (follow && errno == ENOENT\n+                && 0 <= FSTATAT (sp->fts_cwd_fd, p->fts_accpath, sbp,\n+                                 AT_SYMLINK_NOFOLLOW))\n+              {\n+                __set_errno (0);\n+                return FTS_SLNONE;\n+              }\n+\n+            p->fts_errno = errno;\n+           memset (sbp, 0, sizeof *sbp);\n+            return FTS_NS;\n+          }\n+\n+        if (S_ISDIR(sbp->st_mode)) {\n+                if (ISDOT(p->fts_name)) {\n+                        /* Command-line \".\" and \"..\" are real directories. */\n+                        return (p->fts_level == FTS_ROOTLEVEL ? FTS_D : FTS_DOT);\n+                }\n+\n+                return (FTS_D);\n+        }\n+        if (S_ISLNK(sbp->st_mode))\n+                return (FTS_SL);\n+        if (S_ISREG(sbp->st_mode))\n+                return (FTS_F);\n+        return (FTS_DEFAULT);\n+}\n+\n+static int\n+fts_compar (void const *a, void const *b)\n+{\n+  /* Convert A and B to the correct types, to pacify the compiler, and\n+     for portability to bizarre hosts where \"void const *\" and \"FTSENT\n+     const **\" differ in runtime representation.  The comparison\n+     function cannot modify *a and *b, but there is no compile-time\n+     check for this.  */\n+  FTSENTRY const **pa = (FTSENTRY const **) a;\n+  FTSENTRY const **pb = (FTSENTRY const **) b;\n+  return FTSENT_FTS(pa[0])->fts_compar (pa, pb);\n+}\n+\n+static FTSENTRY *\n+internal_function\n+fts_sort (FTSOBJ *sp, FTSENTRY *head, register size_t nitems)\n+{\n+        register FTSENTRY **ap, *p;\n+\n+        /* On most modern hosts, void * and FTSENT ** have the same\n+           run-time representation, and one can convert sp->fts_compar to\n+           the type qsort expects without problem.  Use the heuristic that\n+           this is OK if the two pointer types are the same size, and if\n+           converting FTSENT ** to uintptr_t is the same as converting\n+           FTSENT ** to void * and then to uintptr_t.  This heuristic isn't\n+           valid in general but we don't know of any counterexamples.  */\n+        FTSENTRY *dummy;\n+        int (*compare) (void const *, void const *) =\n+          ((sizeof &dummy == sizeof (void *)\n+            && (uintptr_t) &dummy == (uintptr_t) (void *) &dummy)\n+           ? (int (*) (void const *, void const *)) sp->fts_compar\n+           : fts_compar);\n+\n+        /*\n+         * Construct an array of pointers to the structures and call qsort(3).\n+         * Reassemble the array in the order returned by qsort.  If unable to\n+         * sort for memory reasons, return the directory entries in their\n+         * current order.  Allocate enough space for the current needs plus\n+         * 40 so don't realloc one entry at a time.\n+         */\n+        if (nitems > sp->fts_nitems) {\n+                sp->fts_nitems = nitems + 40;\n+                FTSENTRY **a;\n+                if (! (a = reallocarray (sp->fts_array,\n+                                         sp->fts_nitems, sizeof *a))) {\n+                        free(sp->fts_array);\n+                        sp->fts_array = NULL;\n+                        sp->fts_nitems = 0;\n+                        return (head);\n+                }\n+                sp->fts_array = a;\n+        }\n+        for (ap = sp->fts_array, p = head; p; p = p->fts_link)\n+                *ap++ = p;\n+        qsort((void *)sp->fts_array, nitems, sizeof(FTSENTRY *), compare);\n+        for (head = *(ap = sp->fts_array); --nitems; ++ap)\n+                ap[0]->fts_link = ap[1];\n+        ap[0]->fts_link = NULL;\n+        return (head);\n+}\n+\n+static FTSENTRY *\n+internal_function\n+fts_alloc (FTSOBJ *sp, const char *name, register size_t namelen)\n+{\n+        /*\n+         * The file name is a variable length array.  Allocate the FTSENT\n+         * structure and the file name in one chunk.\n+         */\n+        size_t len = FLEXSIZEOF(FTSENT, fts_name, namelen + 1);\n+\tregister FTSENTRY *p;\n+#if !_LIBC\n+        p = malloc(len);\n+        if (p == NULL)\n+                return (NULL);\n+#else\n+\t/*\n+\t * For glibc, we use a wrapper struct to provide the extra required\n+\t * fields without changing the FSENT layout.\n+\t */\n+\tlen += sizeof (struct FTSENT_wrapper);\n+\tstruct FTSENT_wrapper *wrapper = malloc(len);\n+\tif (wrapper == NULL)\n+\t\treturn (NULL);\n+\tp = &wrapper->ent;\n+        p->fts_statp = &wrapper->fts_stat;\n+#endif\n+\n+        /* Copy the name and guarantee NUL termination. */\n+        memcpy(p->fts_name, name, namelen);\n+        p->fts_name[namelen] = '\\0';\n+\n+        p->fts_namelen = namelen;\n+        FTSENT_FTS(p)= sp;\n+        p->fts_path = sp->fts_path;\n+        p->fts_errno = 0;\n+        FTSENT_DIRP(p) = NULL;\n+        p->fts_flags = 0;\n+        p->fts_instr = FTS_NOINSTR;\n+        p->fts_number = 0;\n+        p->fts_pointer = NULL;\n+        return (p);\n+}\n+\n+static void\n+internal_function\n+fts_lfree (register FTSENTRY *head)\n+{\n+        int saved_errno = errno;\n+\n+        /* Free a linked list of structures. */\n+        register FTSENTRY *p;\n+        while ((p = head)) {\n+                head = head->fts_link;\n+                if (FTSENT_DIRP(p))\n+                        closedir (FTSENT_DIRP(p));\n+                free(FTSENT_WRAPPER(p));\n+        }\n+\n+        __set_errno (saved_errno);\n+}\n+\n+/*\n+ * Allow essentially unlimited file name lengths; find, rm, ls should\n+ * all work on any tree.  Most systems will allow creation of file\n+ * names much longer than MAXPATHLEN, even though the kernel won't\n+ * resolve them.  Add the size (not just what's needed) plus 256 bytes\n+ * so don't realloc the file name 2 bytes at a time.\n+ */\n+static bool\n+internal_function\n+fts_palloc (FTSOBJ *sp, size_t more)\n+{\n+        size_t new_len = sp->fts_pathlen + more + 256;\n+\n+        /*\n+         * See if fts_pathlen would overflow.\n+         */\n+        if (new_len < sp->fts_pathlen) {\n+                free(sp->fts_path);\n+                sp->fts_path = NULL;\n+                __set_errno (ENAMETOOLONG);\n+                return false;\n+        }\n+        sp->fts_pathlen = new_len;\n+        char *p = realloc(sp->fts_path, sp->fts_pathlen);\n+        if (p == NULL) {\n+                free(sp->fts_path);\n+                sp->fts_path = NULL;\n+                return false;\n+        }\n+        sp->fts_path = p;\n+        return true;\n+}\n+\n+/*\n+ * When the file name is realloc'd, have to fix all of the pointers in\n+ *  structures already returned.\n+ */\n+static void\n+internal_function\n+fts_padjust (FTSOBJ *sp, FTSENTRY *head)\n+{\n+        char *addr = sp->fts_path;\n+\n+        /* This code looks at bit-patterns of freed pointers to\n+           relocate them, so it relies on undefined behavior.  If this\n+           trick does not work on your platform, please report a bug.  */\n+\n+#define ADJUST(p) do {                                                  \\\n+        uintptr_t old_accpath = (uintptr_t) (p)->fts_accpath;           \\\n+        if (old_accpath != (uintptr_t) (p)->fts_name) {                 \\\n+                (p)->fts_accpath =                                      \\\n+                  addr + (old_accpath - (uintptr_t) (p)->fts_path);     \\\n+        }                                                               \\\n+        (p)->fts_path = addr;                                           \\\n+} while (0)\n+        /* Adjust the current set of children. */\n+        for (FTSENTRY *p = sp->fts_child; p; p = p->fts_link)\n+                ADJUST(p);\n+\n+        /* Adjust the rest of the tree, including the current level. */\n+        for (FTSENTRY *p = head; p->fts_level >= FTS_ROOTLEVEL;) {\n+                ADJUST(p);\n+                p = p->fts_link ? p->fts_link : p->fts_parent;\n+        }\n+}\n+\n+static size_t\n+internal_function _GL_ATTRIBUTE_PURE\n+fts_maxarglen (char * const *argv)\n+{\n+        size_t max;\n+\n+        for (max = 0; *argv; ++argv) {\n+                size_t len = strlen(*argv);\n+                if (len > max)\n+                        max = len;\n+        }\n+        return (max + 1);\n+}\n+\n+/*\n+ * Change to dir specified by fd or file name without getting\n+ * tricked by someone changing the world out from underneath us.\n+ * Assumes p->fts_statp->st_dev and p->fts_statp->st_ino are filled in.\n+ * If FD is non-negative, expect it to be used after this function returns,\n+ * and to be closed eventually.  So don't pass e.g., 'dirfd(dirp)' and then\n+ * do closedir(dirp), because that would invalidate the saved FD.\n+ * Upon failure, close FD immediately and return nonzero.\n+ */\n+static int\n+internal_function\n+fts_safe_changedir (FTSOBJ *sp, FTSENTRY *p, int fd, char const *dir)\n+{\n+        fts_assert (0 <= fd || dir != NULL);\n+        bool is_dotdot = dir && streq (dir, \"..\");\n+\n+        /* This clause handles the unusual case in which FTS_NOCHDIR\n+           is specified, along with FTS_CWDFD.  In that case, there is\n+           no need to change even the virtual cwd file descriptor.\n+           However, if FD is non-negative, we do close it here.  */\n+        if (ISSET (FTS_NOCHDIR))\n+          {\n+            if (ISSET (FTS_CWDFD) && 0 <= fd)\n+              close (fd);\n+            return 0;\n+          }\n+\n+        if (fd < 0 && is_dotdot && ISSET (FTS_CWDFD))\n+          {\n+            /* When possible, skip the diropen and subsequent fstat+dev/ino\n+               comparison.  I.e., when changing to parent directory\n+               (chdir (\"..\")), use a file descriptor from the ring and\n+               save the overhead of diropen+fstat, as well as avoiding\n+               failure when we lack \"x\" access to the virtual cwd.  */\n+            if ( ! i_ring_empty (&sp->fts_fd_ring))\n+              {\n+                int parent_fd;\n+                fd_ring_print (sp, stderr, \"pre-pop\");\n+                parent_fd = i_ring_pop (&sp->fts_fd_ring);\n+                if (0 <= parent_fd)\n+                  {\n+                    fd = parent_fd;\n+                    dir = NULL;\n+                  }\n+              }\n+          }\n+\n+        int newfd = fd;\n+        if (fd < 0 && (newfd = diropen (sp, dir)) < 0)\n+          return -1;\n+\n+        /* The following dev/inode check is necessary if we're doing a\n+           \"logical\" traversal (through symlinks, a la chown -L), if the\n+           system lacks O_NOFOLLOW support, or if we're changing to \"..\"\n+           (but not via a popped file descriptor).  When changing to the\n+           name \"..\", O_NOFOLLOW can't help.  In general, when the target is\n+           not \"..\", diropen's use of O_NOFOLLOW ensures we don't mistakenly\n+           follow a symlink, so we can avoid the expense of this fstat.  */\n+        int ret;\n+        if (ISSET(FTS_LOGICAL) || ! HAVE_WORKING_O_NOFOLLOW\n+            || (dir && streq (dir, \"..\")))\n+          {\n+            struct STRUCT_STAT sb;\n+            if (FSTAT (newfd, &sb))\n+              {\n+                ret = -1;\n+                goto bail;\n+              }\n+            if (p->fts_statp->st_dev != sb.st_dev\n+                || p->fts_statp->st_ino != sb.st_ino)\n+              {\n+                __set_errno (ENOENT);           /* disinformation */\n+                ret = -1;\n+                goto bail;\n+              }\n+          }\n+\n+        if (ISSET(FTS_CWDFD))\n+          {\n+            cwd_advance_fd (sp, newfd, ! is_dotdot);\n+            return 0;\n+          }\n+\n+        ret = fchdir(newfd);\n+bail:\n+        if (fd < 0)\n+          {\n+            int oerrno = errno;\n+            (void)close(newfd);\n+            __set_errno (oerrno);\n+          }\n+        return ret;\n+}\ndiff --git a/io/fts.c b/io/fts.c\nindex 3825f0aeb4..d3b8e5a100 100644\n--- a/io/fts.c\n+++ b/io/fts.c\n@@ -1,2208 +1,23 @@\n-/* Traverse a file hierarchy.\n+/* File tree traversal functions LFS version.\n+   Copyright (C) 2026 Free Software Foundation, Inc.\n+   This file is part of the GNU C Library.\n \n-   Copyright (C) 2004-2026 Free Software Foundation, Inc.\n+   The GNU C Library is free software; you can redistribute it and/or\n+   modify it under the terms of the GNU Lesser General Public\n+   License as published by the Free Software Foundation; either\n+   version 2.1 of the License, or (at your option) any later version.\n \n-   This file is free software: you can redistribute it and/or modify\n-   it under the terms of the GNU Lesser General Public License as\n-   published by the Free Software Foundation; either version 2.1 of the\n-   License, or (at your option) any later version.\n-\n-   This file is distributed in the hope that it will be useful,\n+   The GNU C Library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n-   GNU Lesser General Public License for more details.\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+   Lesser General Public License for more details.\n \n-   You should have received a copy of the GNU Lesser General Public License\n-   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */\n+   You should have received a copy of the GNU Lesser General Public\n+   License along with the GNU C Library; if not, see\n+   <https://www.gnu.org/licenses/>.  */\n \n-/*-\n- * Copyright (c) 1990, 1993, 1994\n- *      The Regents of the University of California.  All rights reserved.\n- *\n- * Redistribution and use in source and binary forms, with or without\n- * modification, are permitted provided that the following conditions\n- * are met:\n- * 1. Redistributions of source code must retain the above copyright\n- *    notice, this list of conditions and the following disclaimer.\n- * 2. Redistributions in binary form must reproduce the above copyright\n- *    notice, this list of conditions and the following disclaimer in the\n- *    documentation and/or other materials provided with the distribution.\n- * 4. Neither the name of the University nor the names of its contributors\n- *    may be used to endorse or promote products derived from this software\n- *    without specific prior written permission.\n- *\n- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS \"AS IS\" AND\n- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n- * SUCH DAMAGE.\n- */\n+#include <sys/types.h>\n \n-#include <config.h>\n-\n-#if defined LIBC_SCCS && !defined GCC_LINT && !defined lint\n-static char sccsid[] = \"@(#)fts.c       8.6 (Berkeley) 8/14/94\";\n+#ifndef __OFF_T_MATCHES_OFF64_T\n+# include \"io/fts-common.c\"\n #endif\n-\n-#if _LIBC\n-# include <fts.h>\n-#else\n-# include \"fts_.h\"\n-#endif\n-#if _LIBC || HAVE_SYS_PARAM_H\n-# include <sys/param.h>\n-#endif\n-#include <sys/stat.h>\n-#include <fcntl.h>\n-#include <errno.h>\n-#include <stddef.h>\n-#include <stdint.h>\n-#include <stdlib.h>\n-#include <string.h>\n-#include <unistd.h>\n-\n-/* Support for the LFS API version.  */\n-#ifndef FTS_OPEN\n-# define FTS_OPEN fts_open\n-# define FTS_CLOSE fts_close\n-# define FTS_READ fts_read\n-# define FTS_SET fts_set\n-# define FTS_CHILDREN fts_children\n-# define FTSOBJ FTS\n-# define FTSENTRY FTSENT\n-# define INO_T ino_t\n-# define STRUCT_STAT stat\n-# define FSTAT __fstat\n-# define FSTATAT __fstatat\n-# define STRUCT_STATFS statfs\n-# define FSTATFS __fstatfs\n-#endif\n-\n-#if ! _LIBC\n-# include \"attribute.h\"\n-# include \"fcntl--.h\"\n-# include \"openat.h\"\n-# include \"opendirat.h\"\n-# include \"same-inode.h\"\n-# define OPENDIRAT opendirat\n-# define FTSENT_WRAPPER(__p) __p\n-# define FTS_COMPAR_CAST(__fn) __fn\n-#else\n-# include <stdbool.h>\n-\n-# define internal_function\n-# define FALLTHROUGH               ; [[fallthrough]]\n-# define HAVE_STRUCT_DIRENT_D_TYPE 1\n-# define GNULIB_FTS_DEBUG          0\n-# ifdef O_PATH\n-#  define O_SEARCH                 O_PATH\n-# else\n-#  define O_SEARCH                 O_RDONLY\n-# endif\n-# define HAVE_SYS_VFS_H            1\n-# define HAVE_FSTATFS              1\n-# define HAVE_STRUCT_STATFS_F_TYPE 1\n-# define HAVE_OPENAT               1\n-# define HAVE_WORKING_O_NOFOLLOW   1\n-# define _GL_CMP(a, b)             ((a) < (b) ? -1 : (a) > (b))\n-# define OPENDIRAT                 __opendirat\n-\n-static inline bool openat_needs_fchdir (void)\n-{\n-  return false;\n-}\n-\n-static inline bool streq (const char *s1, const char *s2)\n-{\n-  return strcmp (s1, s2) == 0;\n-}\n-# define reallocarray              __libc_reallocarray\n-# define fchdir                    __fchdir\n-# define close                     __close\n-# define closedir                  __closedir\n-# define fcntl                     __fcntl\n-# define readdir                   __readdir\n-# ifndef dirfd\n-#  define dirfd                    __dirfd\n-# endif\n-# define open                      __open\n-# define openat                    __openat\n-\n-# include \"cycle-check.c\"\n-# include \"i-ring.c\"\n-\n-struct FTSENT_wrapper\n-{\n-  FTSOBJ *fts_fts;                /* the file hierarchy itself */\n-  DIR *fts_dirp;                  /* Dir pointer for any directory containing\n-\t\t\t\t     more entries than we read at one time.  */\n-  struct STRUCT_STAT fts_stat;\n-\n-  FTSENTRY ent;\n-};\n-\n-/* glibc historicaly defines the FTS::fts_compar as having 'void *', while the\n-   fts_open has a function point using 'FTSENT **' as argument.  */\n-# define FTS_COMPAR_CAST(__fn) ((int (*) (void const *, void const *))__fn)\n-\n-# define FTSENT_WRAPPER(p) \\\n-    ((struct FTSENT_wrapper *) ((char *)(p) - offsetof(struct FTSENT_wrapper, ent)))\n-#endif\n-#define FTSENT_FTS(p)   (FTSENT_WRAPPER(p)->fts_fts)\n-#define FTSENT_DIRP(p)  (FTSENT_WRAPPER(p)->fts_dirp)\n-\n-#include \"flexmember.h\"\n-\n-#include <dirent.h>\n-#ifndef _D_EXACT_NAMLEN\n-# define _D_EXACT_NAMLEN(dirent) strlen ((dirent)->d_name)\n-#endif\n-\n-#if HAVE_STRUCT_DIRENT_D_TYPE\n-/* True if the type of the directory entry D is known.  */\n-# define DT_IS_KNOWN(d) ((d)->d_type != DT_UNKNOWN)\n-/* True if the type of the directory entry D must be T.  */\n-# define DT_MUST_BE(d, t) ((d)->d_type == (t))\n-# define D_TYPE(d) ((d)->d_type)\n-#else\n-# define DT_IS_KNOWN(d) false\n-# define DT_MUST_BE(d, t) false\n-# define D_TYPE(d) DT_UNKNOWN\n-\n-# undef DT_UNKNOWN\n-# define DT_UNKNOWN 0\n-\n-/* Any nonzero values will do here, so long as they're distinct.\n-   Undef any existing macros out of the way.  */\n-# undef DT_BLK\n-# undef DT_CHR\n-# undef DT_DIR\n-# undef DT_FIFO\n-# undef DT_LNK\n-# undef DT_REG\n-# undef DT_SOCK\n-# define DT_BLK 1\n-# define DT_CHR 2\n-# define DT_DIR 3\n-# define DT_FIFO 4\n-# define DT_LNK 5\n-# define DT_REG 6\n-# define DT_SOCK 7\n-#endif\n-\n-#ifndef S_IFBLK\n-# define S_IFBLK 0\n-#endif\n-#ifndef S_IFLNK\n-# define S_IFLNK 0\n-#endif\n-#ifndef S_IFSOCK\n-# define S_IFSOCK 0\n-#endif\n-\n-enum\n-{\n-  NOT_AN_INODE_NUMBER = 0\n-};\n-\n-#ifdef D_INO_IN_DIRENT\n-# define D_INO(dp) (dp)->d_ino\n-#else\n-/* Some systems don't have inodes, so fake them to avoid lots of ifdefs.  */\n-# define D_INO(dp) NOT_AN_INODE_NUMBER\n-#endif\n-\n-/* If possible (see max_entries, below), read no more than this many directory\n-   entries at a time.  Without this limit (i.e., when using non-NULL\n-   fts_compar), processing a directory with 4,000,000 entries requires ~1GiB\n-   of memory, and handling 64M entries would require 16GiB of memory.  */\n-#ifndef FTS_MAX_READDIR_ENTRIES\n-# define FTS_MAX_READDIR_ENTRIES 100000\n-#endif\n-\n-/* If there are more than this many entries in a directory,\n-   and the conditions mentioned below are satisfied, then sort\n-   the entries on inode number before any further processing.  */\n-#ifndef FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD\n-# define FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD 10000\n-#endif\n-\n-enum\n-{\n-  _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD = FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD\n-};\n-\n-enum Fts_stat\n-{\n-  FTS_NO_STAT_REQUIRED = 1,\n-  FTS_STAT_REQUIRED = 2\n-};\n-\n-#ifndef __set_errno\n-# define __set_errno(Val) errno = (Val)\n-#endif\n-\n-/* If this host provides the openat function, then we can avoid\n-   attempting to open \".\" in some initialization code below.  */\n-#ifdef HAVE_OPENAT\n-# define HAVE_OPENAT_SUPPORT 1\n-#else\n-# define HAVE_OPENAT_SUPPORT 0\n-#endif\n-\n-#ifdef NDEBUG\n-# define fts_assert(expr) ((void) (0 && (expr)))\n-#else\n-# define fts_assert(expr)       \\\n-    do                          \\\n-      {                         \\\n-        if (!(expr))            \\\n-          abort ();             \\\n-      }                         \\\n-    while (false)\n-#endif\n-\n-static FTSENTRY  *fts_alloc (FTSOBJ *, const char *, size_t);\n-static FTSENTRY  *fts_build (FTSOBJ *, int);\n-static void      fts_lfree (FTSENTRY *);\n-static void      fts_load (FTSOBJ *, FTSENTRY *);\n-static size_t    fts_maxarglen (char * const *);\n-static void      fts_padjust (FTSOBJ *, FTSENTRY *);\n-static bool      fts_palloc (FTSOBJ *, size_t);\n-static FTSENTRY  *fts_sort (FTSOBJ *, FTSENTRY *, size_t);\n-static unsigned short int fts_stat (FTSOBJ *, FTSENTRY *, bool);\n-static int      fts_safe_changedir (FTSOBJ *, FTSENTRY *, int, const char *);\n-\n-#include \"fts-cycle.c\"\n-\n-#ifndef MAX\n-# define MAX(a,b) ((a) > (b) ? (a) : (b))\n-#endif\n-\n-#ifndef SIZE_MAX\n-# define SIZE_MAX ((size_t) -1)\n-#endif\n-\n-#define ISDOT(a)        (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))\n-\n-#define CLR(opt)        (sp->fts_options &= ~(opt))\n-#define ISSET(opt)      ((sp->fts_options & (opt)) != 0)\n-#define SET(opt)        (sp->fts_options |= (opt))\n-\n-/* FIXME: FTS_NOCHDIR is now misnamed.\n-   Call it FTS_USE_FULL_RELATIVE_FILE_NAMES instead. */\n-#define FCHDIR(sp, fd)                                  \\\n-  (!ISSET(FTS_NOCHDIR) && (ISSET(FTS_CWDFD)             \\\n-                           ? (cwd_advance_fd ((sp), (fd), true), 0) \\\n-                           : fchdir (fd)))\n-\n-\n-/* fts_build flags */\n-/* FIXME: make this an enum */\n-#define BCHILD          1               /* fts_children */\n-#define BNAMES          2               /* fts_children, names only */\n-#define BREAD           3               /* fts_read */\n-\n-#if GNULIB_FTS_DEBUG\n-# include <inttypes.h>\n-# include <stdio.h>\n-bool fts_debug = false;\n-# define Dprintf(x) do { if (fts_debug) printf x; } while (false)\n-static void fd_ring_check (FTSOBJ const *);\n-static void fd_ring_print (FTSOBJ const *, FILE *, char const *);\n-#else\n-# define Dprintf(x)\n-# define fd_ring_check(x)\n-# define fd_ring_print(a, b, c)\n-#endif\n-\n-#define LEAVE_DIR(Fts, Ent, Tag)                                \\\n-  do                                                            \\\n-    {                                                           \\\n-      Dprintf ((\"  %s-leaving: %s\\n\", Tag, (Ent)->fts_path));   \\\n-      leave_dir (Fts, Ent);                                     \\\n-      fd_ring_check (Fts);                                      \\\n-    }                                                           \\\n-  while (false)\n-\n-static void\n-fd_ring_clear (I_ring *fd_ring)\n-{\n-  while ( ! i_ring_empty (fd_ring))\n-    {\n-      int fd = i_ring_pop (fd_ring);\n-      if (0 <= fd)\n-        close (fd);\n-    }\n-}\n-\n-/* Overload the fts_statp->st_size member (otherwise unused, when\n-   fts_info is FTS_NSOK) to indicate whether fts_read should stat\n-   this entry or not.  */\n-static void\n-fts_set_stat_required (FTSENTRY *p, bool required)\n-{\n-  fts_assert (p->fts_info == FTS_NSOK);\n-  p->fts_statp->st_size = (required\n-                           ? FTS_STAT_REQUIRED\n-                           : FTS_NO_STAT_REQUIRED);\n-}\n-\n-/* Virtual fchdir.  Advance SP's working directory file descriptor,\n-   SP->fts_cwd_fd, to FD, and push the previous value onto the fd_ring.\n-   CHDIR_DOWN_ONE is true if FD corresponds to an entry in the directory\n-   open on sp->fts_cwd_fd; i.e., to move the working directory one level\n-   down.  */\n-static void\n-internal_function\n-cwd_advance_fd (FTSOBJ *sp, int fd, bool chdir_down_one)\n-{\n-  int old = sp->fts_cwd_fd;\n-  fts_assert (old != fd || old == AT_FDCWD);\n-\n-  if (chdir_down_one)\n-    {\n-      /* Push \"old\" onto the ring.\n-         If the displaced file descriptor is non-negative, close it.  */\n-      int prev_fd_in_slot = i_ring_push (&sp->fts_fd_ring, old);\n-      fd_ring_print (sp, stderr, \"post-push\");\n-      if (0 <= prev_fd_in_slot)\n-        close (prev_fd_in_slot); /* ignore any close failure */\n-    }\n-  else if ( ! ISSET (FTS_NOCHDIR))\n-    {\n-      if (0 <= old)\n-        close (old); /* ignore any close failure */\n-    }\n-\n-  sp->fts_cwd_fd = fd;\n-}\n-\n-/* Restore the initial, pre-traversal, \"working directory\".\n-   In FTS_CWDFD mode, we merely call cwd_advance_fd, otherwise,\n-   we may actually change the working directory.\n-   Return 0 upon success. Upon failure, set errno and return nonzero.  */\n-static int\n-restore_initial_cwd (FTSOBJ *sp)\n-{\n-  int fail = FCHDIR (sp, ISSET (FTS_CWDFD) ? AT_FDCWD : sp->fts_rfd);\n-  fd_ring_clear (&(sp->fts_fd_ring));\n-  return fail;\n-}\n-\n-/* Open the directory DIR if possible, and return a file\n-   descriptor.  Return -1 and set errno on failure.  It doesn't matter\n-   whether the file descriptor has read or write access.  */\n-\n-static int\n-internal_function\n-diropen (FTSOBJ const *sp, char const *dir)\n-{\n-  int open_flags = (O_SEARCH | O_CLOEXEC | O_DIRECTORY | O_NOCTTY | O_NONBLOCK\n-                    | (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0));\n-\n-  int fd = (ISSET (FTS_CWDFD)\n-            ? openat (sp->fts_cwd_fd, dir, open_flags)\n-            : open (dir, open_flags));\n-  return fd;\n-}\n-\n-FTSOBJ *\n-FTS_OPEN (char * const *argv,\n-          register int options,\n-          int (*compar) (const FTSENTRY **, const FTSENTRY **))\n-{\n-        /* Options check: glibc added other flags after FTS_NAMEONLY and\n-\t   FTS_STOP, and they are assumed to be private.  */\n-        if (options & ~FTS_OPTIONMASK\n-#if _LIBC\n-\t    || options & (FTS_NAMEONLY | FTS_STOP)\n-#endif\n-\t    ) {\n-                __set_errno (EINVAL);\n-                return (NULL);\n-        }\n-        if ((options & FTS_NOCHDIR) && (options & FTS_CWDFD)) {\n-                __set_errno (EINVAL);\n-                return (NULL);\n-        }\n-#if !_LIBC\n-        if ( ! (options & (FTS_LOGICAL | FTS_PHYSICAL))) {\n-                __set_errno (EINVAL);\n-                return (NULL);\n-        }\n-#else\n-\t/* glibc historically falls to FTS_PHYSICAL if no FTS_PHYSICAL or\n-\t   FTS_LOGICAL is specified.  */\n-        if (! (options & (FTS_PHYSICAL | FTS_LOGICAL)))\n-\t  options |= FTS_PHYSICAL;\n-#endif\n-\n-        /* Allocate/initialize the stream */\n-        register FTSOBJ *sp = calloc (1, sizeof *sp);\n-        if (sp == NULL)\n-                return (NULL);\n-        sp->fts_compar = FTS_COMPAR_CAST(compar);\n-        sp->fts_options = options;\n-\n-        /* Logical walks turn on NOCHDIR; symbolic links are too hard. */\n-        if (ISSET(FTS_LOGICAL)) {\n-                SET(FTS_NOCHDIR);\n-                CLR(FTS_CWDFD);\n-        }\n-\n-        /* Initialize fts_cwd_fd.  */\n-        sp->fts_cwd_fd = AT_FDCWD;\n-        if ( ISSET(FTS_CWDFD) && ! HAVE_OPENAT_SUPPORT)\n-          {\n-            /* While it isn't technically necessary to open \".\" this\n-               early, doing it here saves us the trouble of ensuring\n-               later (where it'd be messier) that \".\" can in fact\n-               be opened.  If not, revert to FTS_NOCHDIR mode.  */\n-            int fd = open (\".\", O_SEARCH | O_CLOEXEC);\n-            if (fd < 0)\n-              {\n-                /* Even if \".\" is unreadable, don't revert to FTS_NOCHDIR mode\n-                   on systems like Linux+PROC_FS, where our openat emulation\n-                   is good enough.  Note: on a system that emulates\n-                   openat via /proc, this technique can still fail, but\n-                   only in extreme conditions, e.g., when the working\n-                   directory cannot be saved (i.e. save_cwd fails) --\n-                   and that happens on Linux only when \".\" is unreadable\n-                   and the CWD would be longer than PATH_MAX.\n-                   FIXME: once Linux kernel openat support is well established,\n-                   replace the above open call and this entire if/else block\n-                   with the body of the if-block below.  */\n-                if ( openat_needs_fchdir ())\n-                  {\n-                    SET(FTS_NOCHDIR);\n-                    CLR(FTS_CWDFD);\n-                  }\n-              }\n-            else\n-              {\n-                close (fd);\n-              }\n-          }\n-\n-        /*\n-         * Start out with 1K of file name space, and enough, in any case,\n-         * to hold the user's file names.\n-         */\n-#ifndef MAXPATHLEN\n-# define MAXPATHLEN 1024\n-#endif\n-        {\n-          size_t maxarglen = fts_maxarglen(argv);\n-          if (! fts_palloc(sp, MAX(maxarglen, MAXPATHLEN)))\n-                  goto mem1;\n-        }\n-\n-        /* Allocate/initialize root's parent. */\n-        FTSENTRY *parent = NULL;\n-        if (*argv != NULL) {\n-                if ((parent = fts_alloc(sp, \"\", 0)) == NULL)\n-                        goto mem2;\n-                parent->fts_level = FTS_ROOTPARENTLEVEL;\n-          }\n-\n-        /* The classic fts implementation would call fts_stat with\n-           a new entry for each iteration of the loop below.\n-           If the comparison function is not specified or if the\n-           FTS_DEFER_STAT option is in effect, don't stat any entry\n-           in this loop.  This is an attempt to minimize the interval\n-           between the initial stat/lstat/fstatat and the point at which\n-           a directory argument is first opened.  This matters for any\n-           directory command line argument that resides on a file system\n-           without genuine i-nodes.  If you specify FTS_DEFER_STAT along\n-           with a comparison function, that function must not access any\n-           data via the fts_statp pointer.  */\n-        bool defer_stat = (compar == NULL || ISSET(FTS_DEFER_STAT));\n-\n-        /* Allocate/initialize root(s). */\n-        register FTSENTRY *root;\n-        register size_t nitems;\n-        FTSENTRY *tmp = NULL;     /* pacify gcc */\n-        for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {\n-                /* *Do* allow zero-length file names. */\n-                size_t len = strlen(*argv);\n-\n-                if ( ! (options & FTS_VERBATIM))\n-                  {\n-                    /* If there are two or more trailing slashes, trim all but one,\n-                       but don't change \"//\" to \"/\", and do map \"///\" to \"/\".  */\n-                    char const *v = *argv;\n-                    if (2 < len && v[len - 1] == '/')\n-                      while (1 < len && v[len - 2] == '/')\n-                        --len;\n-                  }\n-\n-                register FTSENTRY *p = fts_alloc(sp, *argv, len);\n-                if (p == NULL)\n-                        goto mem3;\n-                p->fts_level = FTS_ROOTLEVEL;\n-                p->fts_parent = parent;\n-                p->fts_accpath = p->fts_name;\n-                /* Even when defer_stat is true, be sure to stat the first\n-                   command line argument, since fts_read (at least with\n-                   FTS_XDEV) requires that.  */\n-                if (defer_stat && root != NULL) {\n-                        p->fts_info = FTS_NSOK;\n-                        fts_set_stat_required(p, true);\n-                } else {\n-                        p->fts_info = fts_stat(sp, p, false);\n-                }\n-\n-                /*\n-                 * If comparison routine supplied, traverse in sorted\n-                 * order; otherwise traverse in the order specified.\n-                 */\n-                if (compar) {\n-                        p->fts_link = root;\n-                        root = p;\n-                } else {\n-                        p->fts_link = NULL;\n-                        if (root == NULL)\n-                                tmp = root = p;\n-                        else {\n-                                tmp->fts_link = p;\n-                                tmp = p;\n-                        }\n-                }\n-        }\n-        if (compar && nitems > 1)\n-                root = fts_sort(sp, root, nitems);\n-\n-        /*\n-         * Allocate a dummy pointer and make fts_read think that we've just\n-         * finished the node before the root(s); set p->fts_info to FTS_INIT\n-         * so that everything about the \"current\" node is ignored.\n-         */\n-        if ((sp->fts_cur = fts_alloc(sp, \"\", 0)) == NULL)\n-                goto mem3;\n-        sp->fts_cur->fts_link = root;\n-        sp->fts_cur->fts_info = FTS_INIT;\n-        sp->fts_cur->fts_level = 1;\n-        if (! setup_dir (sp))\n-                goto mem3;\n-\n-        /*\n-         * If using chdir(2), grab a file descriptor pointing to dot to ensure\n-         * that we can get back here; this could be avoided for some file names,\n-         * but almost certainly not worth the effort.  Slashes, symbolic links,\n-         * and \"..\" are all fairly nasty problems.  Note, if we can't get the\n-         * descriptor we run anyway, just more slowly.\n-         */\n-        if (!ISSET(FTS_NOCHDIR) && !ISSET(FTS_CWDFD)\n-            && (sp->fts_rfd = diropen (sp, \".\")) < 0)\n-                SET(FTS_NOCHDIR);\n-\n-        i_ring_init (&sp->fts_fd_ring, -1);\n-        return (sp);\n-\n-mem3:   fts_lfree(root);\n-        free(FTSENT_WRAPPER(parent));\n-mem2:   free(sp->fts_path);\n-mem1:   free(sp);\n-        return (NULL);\n-}\n-\n-static void\n-internal_function\n-fts_load (FTSOBJ *sp, register FTSENTRY *p)\n-{\n-        /*\n-         * Load the stream structure for the next traversal.  Since we don't\n-         * actually enter the directory until after the preorder visit, set\n-         * the fts_accpath field specially so the chdir gets done to the right\n-         * place and the user can access the first node.  From fts_open it's\n-         * known that the file name will fit.\n-         */\n-        register size_t len = p->fts_pathlen = p->fts_namelen;\n-        memmove(sp->fts_path, p->fts_name, len + 1);\n-        register char *cp = strrchr(p->fts_name, '/');\n-        if (cp && (cp != p->fts_name || cp[1])) {\n-                len = strlen(++cp);\n-                memmove(p->fts_name, cp, len + 1);\n-                p->fts_namelen = len;\n-        }\n-        p->fts_accpath = p->fts_path = sp->fts_path;\n-}\n-\n-int\n-FTS_CLOSE (FTSOBJ *sp)\n-{\n-        /*\n-         * This still works if we haven't read anything -- the dummy structure\n-         * points to the root list, so we step through to the end of the root\n-         * list which has a valid parent pointer.\n-         */\n-        if (sp->fts_cur) {\n-                register FTSENTRY *p;\n-                for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {\n-                        register FTSENTRY *freep = p;\n-                        p = p->fts_link != NULL ? p->fts_link : p->fts_parent;\n-                        free(FTSENT_WRAPPER(freep));\n-                }\n-                free(FTSENT_WRAPPER(p));\n-        }\n-\n-        /* Free up child linked list, sort array, file name buffer. */\n-        if (sp->fts_child)\n-                fts_lfree(sp->fts_child);\n-        free(sp->fts_array);\n-        free(sp->fts_path);\n-\n-        int saved_errno = 0;\n-        if (ISSET(FTS_CWDFD))\n-          {\n-            if (0 <= sp->fts_cwd_fd)\n-              if (close (sp->fts_cwd_fd))\n-                saved_errno = errno;\n-          }\n-        else if (!ISSET(FTS_NOCHDIR))\n-          {\n-            /* Return to original directory, save errno if necessary. */\n-            if (fchdir(sp->fts_rfd))\n-              saved_errno = errno;\n-\n-            /* If close fails, record errno only if saved_errno is zero,\n-               so that we report the probably-more-meaningful fchdir errno.  */\n-            if (close (sp->fts_rfd))\n-              if (saved_errno == 0)\n-                saved_errno = errno;\n-          }\n-\n-        fd_ring_clear (&sp->fts_fd_ring);\n-\n-        if (sp->fts_leaf_optimization_works_ht)\n-          hash_free (sp->fts_leaf_optimization_works_ht);\n-\n-        free_dir (sp);\n-\n-        /* Free up the stream pointer. */\n-        free(sp);\n-\n-        /* Set errno and return. */\n-        if (saved_errno) {\n-                __set_errno (saved_errno);\n-                return (-1);\n-        }\n-\n-        return (0);\n-}\n-\n-/* Minimum link count of a traditional Unix directory.  When leaf\n-   optimization is OK and a directory's st_nlink == MIN_DIR_NLINK,\n-   then the directory has no subdirectories.  */\n-enum { MIN_DIR_NLINK = 2 };\n-\n-/* Whether leaf optimization is OK for a directory.  */\n-enum leaf_optimization\n-  {\n-    /* st_nlink is not reliable for this directory's subdirectories.  */\n-    NO_LEAF_OPTIMIZATION,\n-\n-    /* st_nlink == 2 means the directory lacks subdirectories.  */\n-    OK_LEAF_OPTIMIZATION\n-  };\n-\n-#if (defined __linux__ || defined __ANDROID__) \\\n-  && HAVE_SYS_VFS_H && HAVE_FSTATFS && HAVE_STRUCT_STATFS_F_TYPE\n-\n-# include <sys/vfs.h>\n-\n-/* Linux-specific constants from coreutils' src/fs.h */\n-# define S_MAGIC_AFS 0x5346414F\n-# define S_MAGIC_CIFS 0xFF534D42\n-# define S_MAGIC_LUSTRE 0x0BD00BD0\n-# define S_MAGIC_NFS 0x6969\n-# define S_MAGIC_PROC 0x9FA0\n-# define S_MAGIC_TMPFS 0x1021994\n-\n-# ifdef HAVE___FSWORD_T\n-typedef __fsword_t fsword;\n-# else\n-typedef long int fsword;\n-# endif\n-\n-/* Map a stat.st_dev number to a file system type number f_ftype.  */\n-struct dev_type\n-{\n-  dev_t st_dev;\n-  fsword f_type;\n-};\n-\n-/* Use a tiny initial size.  If a traversal encounters more than\n-   a few devices, the cost of growing/rehashing this table will be\n-   rendered negligible by the number of inodes processed.  */\n-enum { DEV_TYPE_HT_INITIAL_SIZE = 13 };\n-\n-static size_t\n-dev_type_hash (void const *x, size_t table_size)\n-{\n-  struct dev_type const *ax = x;\n-  uintmax_t dev = ax->st_dev;\n-  return dev % table_size;\n-}\n-\n-static bool\n-dev_type_compare (void const *x, void const *y)\n-{\n-  struct dev_type const *ax = x;\n-  struct dev_type const *ay = y;\n-  return ax->st_dev == ay->st_dev;\n-}\n-\n-/* Return the file system type of P with file descriptor FD, or 0 if not known.\n-   If FD is negative, P's file descriptor is unavailable.\n-   Try to cache known values.  */\n-\n-static fsword\n-filesystem_type (FTSENTRY const *p, int fd)\n-{\n-  FTSOBJ *sp = FTSENT_FTS(p);\n-\n-  /* If we're not in CWDFD mode, don't bother with this optimization,\n-     since the caller is not serious about performance.  */\n-  if (!ISSET (FTS_CWDFD))\n-    return 0;\n-\n-  Hash_table *h = sp->fts_leaf_optimization_works_ht;\n-  if (! h)\n-    h = sp->fts_leaf_optimization_works_ht\n-      = hash_initialize (DEV_TYPE_HT_INITIAL_SIZE, NULL, dev_type_hash,\n-                         dev_type_compare, free);\n-\n-  if (h)\n-    {\n-      struct dev_type tmp;\n-      tmp.st_dev = p->fts_statp->st_dev;\n-      struct dev_type *ent = hash_lookup (h, &tmp);\n-      if (ent)\n-        return ent->f_type;\n-    }\n-\n-  /* Look-up failed.  Query directly and cache the result.  */\n-  struct STRUCT_STATFS fs_buf;\n-  if (fd < 0 || FSTATFS (fd, &fs_buf) != 0)\n-    return 0;\n-\n-  if (h)\n-    {\n-      struct dev_type *t2 = malloc (sizeof *t2);\n-      if (t2)\n-        {\n-          t2->st_dev = p->fts_statp->st_dev;\n-          t2->f_type = fs_buf.f_type;\n-\n-          struct dev_type *ent = hash_insert (h, t2);\n-          if (ent)\n-            fts_assert (ent == t2);\n-          else\n-            free (t2);\n-        }\n-    }\n-\n-  return fs_buf.f_type;\n-}\n-\n-/* Return true if sorting dirents on inode numbers is known to improve\n-   traversal performance for the directory P with descriptor DIR_FD.\n-   Return false otherwise.  When in doubt, return true.\n-   DIR_FD is negative if unavailable.  */\n-static bool\n-dirent_inode_sort_may_be_useful (FTSENTRY const *p, int dir_fd)\n-{\n-  /* Skip the sort only if we can determine efficiently\n-     that skipping it is the right thing to do.\n-     The cost of performing an unnecessary sort is negligible,\n-     while the cost of *not* performing it can be O(N^2) with\n-     a very large constant.  */\n-\n-  switch (filesystem_type (p, dir_fd))\n-    {\n-    case S_MAGIC_LUSTRE:\n-      /* On Lustre, sorting directory entries interferes with its ability to\n-         prefetch file metadata (via statahead).  This would make a command\n-         like 'du' around 9 times slower.  See\n-         <https://bugs.gnu.org/80106>.  */\n-    case S_MAGIC_CIFS:\n-    case S_MAGIC_NFS:\n-    case S_MAGIC_TMPFS:\n-      /* On a file system of any of these types, sorting\n-         is unnecessary, and hence wasteful.  */\n-      return false;\n-\n-    default:\n-      return true;\n-    }\n-}\n-\n-/* Given an FTS entry P for a directory with descriptor DIR_FD,\n-   return whether it is valid to apply leaf optimization.\n-   The optimization is valid if a directory's st_nlink value equal\n-   to MIN_DIR_NLINK means the directory has no subdirectories.\n-   DIR_FD is negative if unavailable.  */\n-static enum leaf_optimization\n-leaf_optimization (FTSENTRY const *p, int dir_fd)\n-{\n-  switch (filesystem_type (p, dir_fd))\n-    {\n-    case 0:\n-      /* Leaf optimization is unsafe if the file system type is unknown.  */\n-      FALLTHROUGH;\n-    case S_MAGIC_AFS:\n-      /* Although AFS mount points are not counted in st_nlink, they\n-         act like directories.  See <https://bugs.debian.org/143111>.  */\n-      FALLTHROUGH;\n-    case S_MAGIC_CIFS:\n-      /* Leaf optimization causes 'find' to abort.  See\n-         <https://lists.gnu.org/r/bug-gnulib/2018-04/msg00015.html>.  */\n-      FALLTHROUGH;\n-    case S_MAGIC_NFS:\n-      /* NFS provides usable dirent.d_type but not necessarily for all entries\n-         of large directories, so as per <https://bugzilla.redhat.com/1252549>\n-         NFS should return true.  However st_nlink values are not accurate on\n-         all implementations as per <https://bugzilla.redhat.com/1299169>.  */\n-      FALLTHROUGH;\n-    case S_MAGIC_PROC:\n-      /* Per <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=143111> /proc\n-         may have bogus stat.st_nlink values.  */\n-      return NO_LEAF_OPTIMIZATION;\n-\n-    default:\n-      return OK_LEAF_OPTIMIZATION;\n-    }\n-}\n-\n-#else\n-static bool\n-dirent_inode_sort_may_be_useful (_GL_UNUSED FTSENTRY const *p,\n-                                 _GL_UNUSED int dir_fd)\n-{\n-  return true;\n-}\n-static enum leaf_optimization\n-leaf_optimization (_GL_UNUSED FTSENTRY const *p, _GL_UNUSED int dir_fd)\n-{\n-  return NO_LEAF_OPTIMIZATION;\n-}\n-#endif\n-\n-/*\n- * Special case of \"/\" at the end of the file name so that slashes aren't\n- * appended which would cause file names to be written as \"....//foo\".\n- */\n-#define NAPPEND(p)                                                      \\\n-        (p->fts_path[p->fts_pathlen - 1] == '/'                         \\\n-            ? p->fts_pathlen - 1 : p->fts_pathlen)\n-\n-FTSENTRY *\n-FTS_READ (FTSOBJ *sp)\n-{\n-        /* If finished or unrecoverable error, return NULL. */\n-        if (sp->fts_cur == NULL || ISSET(FTS_STOP))\n-                return (NULL);\n-\n-        /* Set current node pointer. */\n-        register FTSENTRY *p = sp->fts_cur;\n-\n-        /* Save and zero out user instructions. */\n-        register unsigned short int instr = p->fts_instr;\n-        p->fts_instr = FTS_NOINSTR;\n-\n-        /* Any type of file may be re-visited; re-stat and re-turn. */\n-        if (instr == FTS_AGAIN) {\n-                p->fts_info = fts_stat(sp, p, false);\n-                return (p);\n-        }\n-        Dprintf ((\"fts_read: p=%s\\n\",\n-                  p->fts_info == FTS_INIT ? \"\" : p->fts_path));\n-\n-        /*\n-         * Following a symlink -- SLNONE test allows application to see\n-         * SLNONE and recover.  If indirecting through a symlink, have\n-         * keep a pointer to current location.  If unable to get that\n-         * pointer, follow fails.\n-         */\n-        if (instr == FTS_FOLLOW &&\n-            (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {\n-                p->fts_info = fts_stat(sp, p, true);\n-                if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {\n-                        if ((p->fts_symfd = diropen (sp, \".\")) < 0) {\n-                                p->fts_errno = errno;\n-                                p->fts_info = FTS_ERR;\n-                        } else\n-                                p->fts_flags |= FTS_SYMFOLLOW;\n-                }\n-                goto check_for_dir;\n-        }\n-\n-        /* Directory in pre-order. */\n-        if (p->fts_info == FTS_D) {\n-                /* If skipped or crossed mount point, do post-order visit. */\n-                if (instr == FTS_SKIP ||\n-                    (ISSET(FTS_XDEV) && p->fts_statp->st_dev != sp->fts_dev)) {\n-                        if (p->fts_flags & FTS_SYMFOLLOW)\n-                                (void)close(p->fts_symfd);\n-                        if (sp->fts_child) {\n-                                fts_lfree(sp->fts_child);\n-                                sp->fts_child = NULL;\n-                        }\n-                        p->fts_info = FTS_DP;\n-                        LEAVE_DIR (sp, p, \"1\");\n-                        return (p);\n-                }\n-\n-                /* Rebuild if only read the names and now traversing. */\n-                if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {\n-                        CLR(FTS_NAMEONLY);\n-                        fts_lfree(sp->fts_child);\n-                        sp->fts_child = NULL;\n-                }\n-\n-                /*\n-                 * Cd to the subdirectory.\n-                 *\n-                 * If have already read and now fail to chdir, whack the list\n-                 * to make the names come out right, and set the parent errno\n-                 * so the application will eventually get an error condition.\n-                 * Set the FTS_DONTCHDIR flag so that when we logically change\n-                 * directories back to the parent we don't do a chdir.\n-                 *\n-                 * If haven't read do so.  If the read fails, fts_build sets\n-                 * FTS_STOP or the fts_info field of the node.\n-                 */\n-                if (sp->fts_child != NULL) {\n-                        if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {\n-                                p->fts_errno = errno;\n-                                p->fts_flags |= FTS_DONTCHDIR;\n-                                for (p = sp->fts_child; p != NULL;\n-                                     p = p->fts_link)\n-                                        p->fts_accpath =\n-                                            p->fts_parent->fts_accpath;\n-                        }\n-                } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {\n-                        if (ISSET(FTS_STOP))\n-                                return (NULL);\n-                        /* If fts_build's call to fts_safe_changedir failed\n-                           because it was not able to fchdir into a\n-                           subdirectory, tell the caller.  */\n-                        if (p->fts_errno && p->fts_info != FTS_DNR)\n-                                p->fts_info = FTS_ERR;\n-                        LEAVE_DIR (sp, p, \"2\");\n-                        return (p);\n-                }\n-                p = sp->fts_child;\n-                sp->fts_child = NULL;\n-                goto name;\n-        }\n-\n-        /* Move to the next node on this level. */\n-next: ;\n-        register FTSENTRY *tmp = p;\n-\n-        /* If we have so many directory entries that we're reading them\n-           in batches, and we've reached the end of the current batch,\n-           read in a new batch.  */\n-        if (p->fts_link == NULL && FTSENT_DIRP(p->fts_parent))\n-          {\n-            p = tmp->fts_parent;\n-            sp->fts_cur = p;\n-            sp->fts_path[p->fts_pathlen] = '\\0';\n-\n-            if ((p = fts_build (sp, BREAD)) == NULL)\n-              {\n-                if (ISSET(FTS_STOP))\n-                  return NULL;\n-                goto cd_dot_dot;\n-              }\n-\n-            free(FTSENT_WRAPPER(tmp));\n-            goto name;\n-          }\n-\n-        if ((p = p->fts_link) != NULL) {\n-                sp->fts_cur = p;\n-                free(FTSENT_WRAPPER(tmp));\n-\n-                /*\n-                 * If reached the top, return to the original directory (or\n-                 * the root of the tree), and load the file names for the next\n-                 * root.\n-                 */\n-                if (p->fts_level == FTS_ROOTLEVEL) {\n-                        if (restore_initial_cwd(sp)) {\n-                                SET(FTS_STOP);\n-                                return (NULL);\n-                        }\n-                        free_dir(sp);\n-                        fts_load(sp, p);\n-                        if (! setup_dir(sp)) {\n-                                free_dir(sp);\n-                                return (NULL);\n-                        }\n-                        goto check_for_dir;\n-                }\n-\n-                /*\n-                 * User may have called fts_set on the node.  If skipped,\n-                 * ignore.  If followed, get a file descriptor so we can\n-                 * get back if necessary.\n-                 */\n-                if (p->fts_instr == FTS_SKIP)\n-                        goto next;\n-                if (p->fts_instr == FTS_FOLLOW) {\n-                        p->fts_info = fts_stat(sp, p, true);\n-                        if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {\n-                                if ((p->fts_symfd = diropen (sp, \".\")) < 0) {\n-                                        p->fts_errno = errno;\n-                                        p->fts_info = FTS_ERR;\n-                                } else\n-                                        p->fts_flags |= FTS_SYMFOLLOW;\n-                        }\n-                        p->fts_instr = FTS_NOINSTR;\n-                }\n-\n-name:           {\n-                  register char *t = sp->fts_path + NAPPEND(p->fts_parent);\n-                  *t++ = '/';\n-                  memmove(t, p->fts_name, p->fts_namelen + 1);\n-                }\n-check_for_dir:\n-                sp->fts_cur = p;\n-                if (p->fts_info == FTS_NSOK)\n-                  {\n-                    if (p->fts_statp->st_size == FTS_STAT_REQUIRED)\n-                      p->fts_info = fts_stat(sp, p, false);\n-                    else\n-                      fts_assert (p->fts_statp->st_size == FTS_NO_STAT_REQUIRED);\n-                  }\n-\n-                /* Skip files with different device numbers when FTS_MOUNT\n-                   is set.  */\n-                if (ISSET (FTS_MOUNT) && p->fts_info != FTS_NS &&\n-                    p->fts_level != FTS_ROOTLEVEL &&\n-                    p->fts_statp->st_dev != sp->fts_dev)\n-                      goto next;\n-\n-                if (p->fts_info == FTS_D)\n-                  {\n-                    /* Now that P->fts_statp is guaranteed to be valid, if\n-                       this is a command-line directory, record its device\n-                       number, to be used for FTS_MOUNT and FTS_XDEV.  */\n-                    if (p->fts_level == FTS_ROOTLEVEL)\n-                      sp->fts_dev = p->fts_statp->st_dev;\n-                    Dprintf ((\"  entering: %s\\n\", p->fts_path));\n-                    if (! enter_dir (sp, p))\n-                      return NULL;\n-                  }\n-                return p;\n-        }\n-cd_dot_dot:\n-\n-        /* Move up to the parent node. */\n-        p = tmp->fts_parent;\n-        sp->fts_cur = p;\n-        free(FTSENT_WRAPPER(tmp));\n-\n-        if (p->fts_level == FTS_ROOTPARENTLEVEL) {\n-                /*\n-                 * Done; free everything up and set errno to 0 so the user\n-                 * can distinguish between error and EOF.\n-                 */\n-                free(FTSENT_WRAPPER(p));\n-                __set_errno (0);\n-                return (sp->fts_cur = NULL);\n-        }\n-\n-        fts_assert (p->fts_info != FTS_NSOK);\n-\n-        /* NUL terminate the file name.  */\n-        sp->fts_path[p->fts_pathlen] = '\\0';\n-\n-        /*\n-         * Return to the parent directory.  If at a root node, restore\n-         * the initial working directory.  If we came through a symlink,\n-         * go back through the file descriptor.  Otherwise, move up\n-         * one level, via \"..\".\n-         */\n-        if (p->fts_level == FTS_ROOTLEVEL) {\n-                if (restore_initial_cwd(sp)) {\n-                        p->fts_errno = errno;\n-                        SET(FTS_STOP);\n-                }\n-        } else if (p->fts_flags & FTS_SYMFOLLOW) {\n-                if (FCHDIR(sp, p->fts_symfd)) {\n-                        p->fts_errno = errno;\n-                        SET(FTS_STOP);\n-                }\n-                (void)close(p->fts_symfd);\n-        } else if (!(p->fts_flags & FTS_DONTCHDIR) &&\n-                   fts_safe_changedir(sp, p->fts_parent, -1, \"..\")) {\n-                p->fts_errno = errno;\n-                SET(FTS_STOP);\n-        }\n-\n-        /* If the directory causes a cycle, preserve the FTS_DC flag and keep\n-           the corresponding dev/ino pair in the hash table.  It is going to be\n-           removed when leaving the original directory.  */\n-        if (p->fts_info != FTS_DC) {\n-                p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;\n-                if (p->fts_errno == 0)\n-                        LEAVE_DIR (sp, p, \"3\");\n-        }\n-        return ISSET(FTS_STOP) ? NULL : p;\n-}\n-\n-/*\n- * Fts_set takes the stream as an argument although it's not used in this\n- * implementation; it would be necessary if anyone wanted to add global\n- * semantics to fts using fts_set.  An error return is allowed for similar\n- * reasons.\n- */\n-/* ARGSUSED */\n-int\n-FTS_SET (_GL_UNUSED FTSOBJ *sp, FTSENTRY *p, int instr)\n-{\n-        if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&\n-            instr != FTS_NOINSTR && instr != FTS_SKIP) {\n-                __set_errno (EINVAL);\n-                return (1);\n-        }\n-        p->fts_instr = instr;\n-        return (0);\n-}\n-\n-FTSENTRY *\n-FTS_CHILDREN (FTSOBJ *sp, int instr)\n-{\n-        if (instr != 0 && instr != FTS_NAMEONLY) {\n-                __set_errno (EINVAL);\n-                return (NULL);\n-        }\n-\n-        /* Set current node pointer. */\n-        register FTSENTRY *p = sp->fts_cur;\n-\n-        /*\n-         * Errno set to 0 so user can distinguish empty directory from\n-         * an error.\n-         */\n-        __set_errno (0);\n-\n-        /* Fatal errors stop here. */\n-        if (ISSET(FTS_STOP))\n-                return (NULL);\n-\n-        /* Return logical hierarchy of user's arguments. */\n-        if (p->fts_info == FTS_INIT)\n-                return (p->fts_link);\n-\n-        /*\n-         * If not a directory being visited in pre-order, stop here.  Could\n-         * allow FTS_DNR, assuming the user has fixed the problem, but the\n-         * same effect is available with FTS_AGAIN.\n-         */\n-        if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)\n-                return (NULL);\n-\n-        /* Free up any previous child list. */\n-        if (sp->fts_child != NULL)\n-                fts_lfree(sp->fts_child);\n-\n-        if (instr == FTS_NAMEONLY) {\n-                SET(FTS_NAMEONLY);\n-                instr = BNAMES;\n-        } else\n-                instr = BCHILD;\n-\n-        /*\n-         * If using chdir on a relative file name and called BEFORE fts_read\n-         * does its chdir to the root of a traversal, we can lose -- we need to\n-         * chdir into the subdirectory, and we don't know where the current\n-         * directory is, so we can't get back so that the upcoming chdir by\n-         * fts_read will work.\n-         */\n-        if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||\n-            ISSET(FTS_NOCHDIR))\n-                return (sp->fts_child = fts_build(sp, instr));\n-\n-        int fd = diropen (sp, \".\");\n-        if (fd < 0)\n-                return (sp->fts_child = NULL);\n-        sp->fts_child = fts_build(sp, instr);\n-        if (ISSET(FTS_CWDFD))\n-          {\n-            cwd_advance_fd (sp, fd, true);\n-          }\n-        else\n-          {\n-            if (fchdir(fd))\n-              {\n-                int saved_errno = errno;\n-                close (fd);\n-                __set_errno (saved_errno);\n-                return NULL;\n-              }\n-            close (fd);\n-          }\n-        return (sp->fts_child);\n-}\n-\n-/* A comparison function to sort on increasing inode number.\n-   For some file system types, sorting either way makes a huge\n-   performance difference for a directory with very many entries,\n-   but sorting on increasing values is slightly better than sorting\n-   on decreasing values.  The difference is in the 5% range.  */\n-static int\n-fts_compare_ino (FTSENTRY const **a, FTSENTRY const **b)\n-{\n-  return _GL_CMP (a[0]->fts_statp->st_ino, b[0]->fts_statp->st_ino);\n-}\n-\n-/* Map the dirent.d_type value, DTYPE, to the corresponding stat.st_mode\n-   S_IF* bit and set ST.st_mode, thus clearing all other bits in that field.  */\n-static void\n-set_stat_type (struct STRUCT_STAT *st, unsigned int dtype)\n-{\n-  mode_t type;\n-  switch (dtype)\n-    {\n-    case DT_BLK:\n-      type = S_IFBLK;\n-      break;\n-    case DT_CHR:\n-      type = S_IFCHR;\n-      break;\n-    case DT_DIR:\n-      type = S_IFDIR;\n-      break;\n-    case DT_FIFO:\n-      type = S_IFIFO;\n-      break;\n-    case DT_LNK:\n-      type = S_IFLNK;\n-      break;\n-    case DT_REG:\n-      type = S_IFREG;\n-      break;\n-    case DT_SOCK:\n-      type = S_IFSOCK;\n-      break;\n-    default:\n-      type = 0;\n-    }\n-  st->st_mode = type;\n-}\n-\n-#define closedir_and_clear(dirp)                \\\n-  do                                            \\\n-    {                                           \\\n-      closedir (dirp);                          \\\n-      dirp = NULL;                              \\\n-    }                                           \\\n-  while (0)\n-\n-#define fts_opendir(file, Pdir_fd)                              \\\n-        OPENDIRAT((! ISSET(FTS_NOCHDIR) && ISSET(FTS_CWDFD)     \\\n-                   ? sp->fts_cwd_fd : AT_FDCWD),                \\\n-                  file,                                         \\\n-                  (((ISSET(FTS_PHYSICAL)                        \\\n-                     && ! (ISSET(FTS_COMFOLLOW)                 \\\n-                           && cur->fts_level == FTS_ROOTLEVEL)) \\\n-                    ? O_NOFOLLOW : 0)),                         \\\n-                  Pdir_fd)\n-\n-/*\n- * This is the tricky part -- do not casually change *anything* in here.  The\n- * idea is to build the linked list of entries that are used by fts_children\n- * and fts_read.  There are lots of special cases.\n- *\n- * The real slowdown in walking the tree is the stat calls.  If FTS_NOSTAT is\n- * set and it's a physical walk (so that symbolic links can't be directories),\n- * we can do things quickly.  First, if it's a 4.4BSD file system, the type\n- * of the file is in the directory entry.  Otherwise, we assume that the number\n- * of subdirectories in a node is equal to the number of links to the parent.\n- * The former skips all stat calls.  The latter skips stat calls in any leaf\n- * directories and for any files after the subdirectories in the directory have\n- * been found, cutting the stat calls by about 2/3.\n- */\n-static FTSENTRY *\n-internal_function\n-fts_build (register FTSOBJ *sp, int type)\n-{\n-        FTSENTRY *cur = sp->fts_cur;\n-        bool continue_readdir = !!FTSENT_DIRP(cur);\n-\n-        /* When cur->fts_dirp is non-NULL, that means we should\n-           continue calling readdir on that existing DIR* pointer\n-           rather than opening a new one.  */\n-        int dir_fd;\n-        if (continue_readdir)\n-          {\n-            DIR *dp = FTSENT_DIRP(cur);\n-            dir_fd = dirfd (dp);\n-            if (dir_fd < 0)\n-              {\n-                int dirfd_errno = errno;\n-                closedir_and_clear (FTSENT_DIRP(cur));\n-                if (type == BREAD)\n-                  {\n-                    cur->fts_info = FTS_DNR;\n-                    cur->fts_errno = dirfd_errno;\n-                  }\n-                return NULL;\n-              }\n-          }\n-        else\n-          {\n-            /* Open the directory for reading.  If this fails, we're done.\n-               If being called from fts_read, set the fts_info field. */\n-            if ((FTSENT_DIRP (cur) = fts_opendir(cur->fts_accpath, &dir_fd)) == NULL)\n-              {\n-                if (type == BREAD)\n-                  {\n-                    cur->fts_info = FTS_DNR;\n-                    cur->fts_errno = errno;\n-                  }\n-                return NULL;\n-              }\n-            /* Rather than calling fts_stat for each and every entry encountered\n-               in the readdir loop (below), stat each directory only right after\n-               opening it.  */\n-            bool stat_optimization = cur->fts_info == FTS_NSOK;\n-\n-            if (stat_optimization\n-                /* Also read the stat info again after opening a directory to\n-                   reveal eventual changes caused by a submount triggered by\n-                   the traversal.  But do it only for utilities which use\n-                   FTS_TIGHT_CYCLE_CHECK.  Therefore, only find and du\n-                   benefit/suffer from this feature for now.  */\n-                || ISSET (FTS_TIGHT_CYCLE_CHECK))\n-              {\n-                if (!stat_optimization)\n-                  LEAVE_DIR (sp, cur, \"4\");\n-                if (FSTAT (dir_fd, cur->fts_statp) != 0)\n-                  {\n-                    int fstat_errno = errno;\n-                    closedir_and_clear (FTSENT_DIRP(cur));\n-                    if (type == BREAD)\n-                      {\n-                        cur->fts_errno = fstat_errno;\n-                        cur->fts_info = FTS_NS;\n-                      }\n-                    __set_errno (fstat_errno);\n-                    return NULL;\n-                  }\n-                if (stat_optimization)\n-                  cur->fts_info = FTS_D;\n-                else if (! enter_dir (sp, cur))\n-                  {\n-                    int saved_errno = errno;\n-                    closedir_and_clear (FTSENT_DIRP(cur));\n-                    __set_errno (saved_errno);\n-                    return NULL;\n-                  }\n-              }\n-          }\n-\n-        /* Maximum number of readdir entries to read at one time.  This\n-           limitation is to avoid reading millions of entries into memory\n-           at once.  When an fts_compar function is specified, we have no\n-           choice: we must read all entries into memory before calling that\n-           function.  But when no such function is specified, we can read\n-           entries in batches that are large enough to help us with inode-\n-           sorting, yet not so large that we risk exhausting memory.  */\n-        size_t max_entries = sp->fts_compar ? SIZE_MAX : FTS_MAX_READDIR_ENTRIES;\n-\n-        /*\n-         * If we're going to need to stat anything or we want to descend\n-         * and stay in the directory, chdir.  If this fails we keep going,\n-         * but set a flag so we don't chdir after the post-order visit.\n-         * We won't be able to stat anything, but we can still return the\n-         * names themselves.  Note, that since fts_read won't be able to\n-         * chdir into the directory, it will have to return different file\n-         * names than before, i.e. \"a/b\" instead of \"b\".  Since the node\n-         * has already been visited in pre-order, have to wait until the\n-         * post-order visit to return the error.  There is a special case\n-         * here, if there was nothing to stat then it's not an error to\n-         * not be able to stat.  This is all fairly nasty.  If a program\n-         * needed sorted entries or stat information, they had better be\n-         * checking FTS_NS on the returned nodes.\n-         */\n-        bool descend;\n-        if (continue_readdir)\n-          {\n-            /* When resuming a short readdir run, we already have\n-               the required dirp and dir_fd.  */\n-            descend = true;\n-          }\n-        else\n-          {\n-            /* Try to descend unless it is a names-only fts_children,\n-               or the directory is known to lack subdirectories.  */\n-            descend = (type != BNAMES\n-                       && ! (ISSET (FTS_NOSTAT) && ISSET (FTS_PHYSICAL)\n-                             && ! ISSET (FTS_SEEDOT)\n-                             && cur->fts_statp->st_nlink == MIN_DIR_NLINK\n-                             && (leaf_optimization (cur, dir_fd)\n-                                 != NO_LEAF_OPTIMIZATION)));\n-            if (descend || type == BREAD)\n-              {\n-                if (ISSET(FTS_CWDFD))\n-                  dir_fd = fcntl (dir_fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1);\n-                if (dir_fd < 0 || fts_safe_changedir(sp, cur, dir_fd, NULL)) {\n-                        if (descend && type == BREAD)\n-                                cur->fts_errno = errno;\n-                        cur->fts_flags |= FTS_DONTCHDIR;\n-                        descend = false;\n-                        closedir_and_clear(FTSENT_DIRP(cur));\n-                        if (ISSET(FTS_CWDFD) && 0 <= dir_fd)\n-                                close (dir_fd);\n-                        FTSENT_DIRP(cur) = NULL;\n-                } else\n-                        descend = true;\n-              }\n-          }\n-\n-        /*\n-         * Figure out the max file name length that can be stored in the\n-         * current buffer -- the inner loop allocates more space as necessary.\n-         * We really wouldn't have to do the maxlen calculations here, we\n-         * could do them in fts_read before returning the name, but it's a\n-         * lot easier here since the length is part of the dirent structure.\n-         *\n-         * If not changing directories set a pointer so that can just append\n-         * each new component into the file name.\n-         */\n-        size_t len = NAPPEND(cur);\n-        char *cp;\n-        if (ISSET(FTS_NOCHDIR)) {\n-                cp = sp->fts_path + len;\n-                *cp++ = '/';\n-        } else {\n-                /* GCC, you're too verbose. */\n-                cp = NULL;\n-        }\n-        len++;\n-        size_t maxlen = sp->fts_pathlen - len;\n-\n-        ptrdiff_t level = cur->fts_level + 1;\n-\n-        /* Read the directory, attaching each entry to the \"link\" pointer. */\n-        bool doadjust = false;\n-        register FTSENTRY *head = NULL;\n-        FTSENTRY *tail = NULL;\n-        register size_t nitems = 0;\n-        bool sort_by_inode = false;\n-        while (FTSENT_DIRP(cur)) {\n-                __set_errno (0);\n-                struct dirent *dp = readdir(FTSENT_DIRP(cur));\n-                if (dp == NULL) {\n-                        /* Some readdir()s do not absorb ENOENT (dir\n-                           deleted but open).  This bug was fixed in\n-                           glibc 2.3 (2002).  */\n-#if ! (2 < __GLIBC__ + (3 <= __GLIBC_MINOR__))\n-                        if (errno == ENOENT)\n-                          errno = 0;\n-#endif\n-                        if (errno) {\n-                                cur->fts_errno = errno;\n-                                /* If we've not read any items yet, treat\n-                                   the error as if we can't access the dir.  */\n-                                cur->fts_info = (continue_readdir || nitems)\n-                                                ? FTS_ERR : FTS_DNR;\n-                        }\n-                        closedir_and_clear(FTSENT_DIRP(cur));\n-                        break;\n-                }\n-                if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))\n-                        continue;\n-\n-                size_t d_namelen = _D_EXACT_NAMLEN (dp);\n-                register FTSENTRY *p = fts_alloc (sp, dp->d_name, d_namelen);\n-                if (!p)\n-                        goto mem1;\n-                if (d_namelen >= maxlen) {\n-                        /* include space for NUL */\n-                        uintptr_t oldaddr = (uintptr_t) sp->fts_path;\n-                        if (! fts_palloc(sp, d_namelen + len + 1)) {\n-                                /*\n-                                 * No more memory.  Save\n-                                 * errno, free up the current structure and the\n-                                 * structures already allocated.\n-                                 */\n-mem1: ;\n-                                int saved_errno = errno;\n-                                free(FTSENT_WRAPPER(p));\n-                                fts_lfree(head);\n-                                closedir_and_clear(FTSENT_DIRP(cur));\n-                                cur->fts_info = FTS_ERR;\n-                                SET(FTS_STOP);\n-                                __set_errno (saved_errno);\n-                                return (NULL);\n-                        }\n-                        /* Did realloc() change the pointer? */\n-                        if (oldaddr != (uintptr_t) sp->fts_path) {\n-                                doadjust = true;\n-                                if (ISSET(FTS_NOCHDIR))\n-                                        cp = sp->fts_path + len;\n-                        }\n-                        maxlen = sp->fts_pathlen - len;\n-                }\n-\n-                size_t new_len = len + d_namelen;\n-                if (new_len < len) {\n-                        /*\n-                         * In the unlikely event that we would end up\n-                         * with a file name longer than SIZE_MAX, free up\n-                         * the current structure and the structures already\n-                         * allocated, then error out with ENAMETOOLONG.\n-                         */\n-                        free(FTSENT_WRAPPER(p));\n-                        fts_lfree(head);\n-                        closedir_and_clear(FTSENT_DIRP(cur));\n-                        cur->fts_info = FTS_ERR;\n-                        SET(FTS_STOP);\n-                        __set_errno (ENAMETOOLONG);\n-                        return (NULL);\n-                }\n-                p->fts_level = level;\n-                p->fts_parent = sp->fts_cur;\n-                p->fts_pathlen = new_len;\n-\n-                /* Store dirent.d_ino, in case we need to sort\n-                   entries before processing them.  */\n-                p->fts_statp->st_ino = D_INO (dp);\n-\n-                /* Build a file name for fts_stat to stat. */\n-                if (ISSET(FTS_NOCHDIR)) {\n-                        p->fts_accpath = p->fts_path;\n-                        memmove(cp, p->fts_name, p->fts_namelen + 1);\n-                } else\n-                        p->fts_accpath = p->fts_name;\n-\n-                if (sp->fts_compar == NULL || ISSET(FTS_DEFER_STAT)) {\n-                        /* Record what fts_read will have to do with this\n-                           entry. In many cases, it will simply fts_stat it,\n-                           but we can take advantage of any d_type information\n-                           to optimize away the unnecessary stat calls.  I.e.,\n-                           if FTS_NOSTAT is in effect, we don't need device\n-                           numbers unconditionally (FTS_MOUNT) and we're not\n-                           following symlinks (FTS_PHYSICAL) and d_type\n-                           indicates this is *not* a directory, then we won't\n-                           have to stat it  at all.  If it *is* a directory,\n-                           then (currently) we stat it regardless, in order to\n-                           get device and inode numbers.  Some day we might\n-                           optimize that away, too, for directories where\n-                           d_ino is known to be valid.  */\n-                        bool skip_stat = (ISSET(FTS_NOSTAT)\n-                                          && DT_IS_KNOWN(dp)\n-                                          && ! DT_MUST_BE(dp, DT_DIR)\n-                                          && (ISSET(FTS_PHYSICAL)\n-                                              || ! DT_MUST_BE(dp, DT_LNK))\n-                                          && ! ISSET(FTS_MOUNT));\n-                        p->fts_info = FTS_NSOK;\n-                        /* Propagate dirent.d_type information back\n-                           to caller, when possible.  */\n-                        set_stat_type (p->fts_statp, D_TYPE (dp));\n-                        fts_set_stat_required(p, !skip_stat);\n-                } else {\n-                        p->fts_info = fts_stat(sp, p, false);\n-                }\n-\n-                /* We walk in directory order so \"ls -f\" doesn't get upset. */\n-                p->fts_link = NULL;\n-                if (head == NULL)\n-                        head = tail = p;\n-                else {\n-                        tail->fts_link = p;\n-                        tail = p;\n-                }\n-\n-                /* If there are many entries, no sorting function has been\n-                   specified, and this file system is of a type that may be\n-                   slow with a large number of entries, arrange to sort the\n-                   directory entries on increasing inode numbers.\n-\n-                   The NITEMS comparison uses ==, not >, because the test\n-                   needs to be tried at most once once, and NITEMS will exceed\n-                   the threshold after it is incremented below.  */\n-                if (nitems == _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD\n-                    && !sp->fts_compar)\n-                  sort_by_inode = dirent_inode_sort_may_be_useful (cur, dir_fd);\n-\n-                ++nitems;\n-                if (max_entries <= nitems) {\n-                        /* When there are too many dir entries, leave\n-                           fts_dirp open, so that a subsequent fts_read\n-                           can take up where we leave off.  */\n-                        break;\n-                }\n-        }\n-\n-        /*\n-         * If realloc() changed the address of the file name, adjust the\n-         * addresses for the rest of the tree and the dir list.\n-         */\n-        if (doadjust)\n-                fts_padjust(sp, head);\n-\n-        /*\n-         * If not changing directories, reset the file name back to original\n-         * state.\n-         */\n-        if (ISSET(FTS_NOCHDIR)) {\n-                if (len == sp->fts_pathlen || nitems == 0)\n-                        --cp;\n-                *cp = '\\0';\n-        }\n-\n-        /*\n-         * If descended after called from fts_children or after called from\n-         * fts_read and nothing found, get back.  At the root level we use\n-         * the saved fd; if one of fts_open()'s arguments is a relative name\n-         * to an empty directory, we wind up here with no other way back.  If\n-         * can't get back, we're done.\n-         */\n-        if (!continue_readdir && descend && (type == BCHILD || !nitems) &&\n-            (cur->fts_level == FTS_ROOTLEVEL\n-             ? restore_initial_cwd(sp)\n-             : fts_safe_changedir(sp, cur->fts_parent, -1, \"..\"))) {\n-                cur->fts_info = FTS_ERR;\n-                SET(FTS_STOP);\n-                fts_lfree(head);\n-                return (NULL);\n-        }\n-\n-        /* If didn't find anything, return NULL. */\n-        if (!nitems) {\n-                if (type == BREAD\n-                    && cur->fts_info != FTS_DNR && cur->fts_info != FTS_ERR)\n-                        cur->fts_info = FTS_DP;\n-                fts_lfree(head);\n-                return (NULL);\n-        }\n-\n-        if (sort_by_inode) {\n-                sp->fts_compar = FTS_COMPAR_CAST (fts_compare_ino);\n-                head = fts_sort (sp, head, nitems);\n-                sp->fts_compar = NULL;\n-        }\n-\n-        /* Sort the entries. */\n-        if (sp->fts_compar && nitems > 1)\n-                head = fts_sort(sp, head, nitems);\n-        return (head);\n-}\n-\n-#if GNULIB_FTS_DEBUG\n-\n-struct devino {\n-  intmax_t dev, ino;\n-};\n-#define PRINT_DEVINO \"(%jd,%jd)\"\n-\n-static struct devino\n-getdevino (int fd)\n-{\n-  struct STRUCT_STAT st;\n-  return (fd == AT_FDCWD\n-          ? (struct devino) { -1, 0 }\n-          : FSTAT (fd, &st) == 0\n-          ? (struct devino) { st.st_dev, st.st_ino }\n-          : (struct devino) { -1, errno });\n-}\n-\n-/* Walk ->fts_parent links starting at E_CURR, until the root of the\n-   current hierarchy.  There should be a directory with dev/inode\n-   matching those of AD.  If not, print a lot of diagnostics.  */\n-static void\n-find_matching_ancestor (FTSENTRY const *e_curr, struct Active_dir const *ad)\n-{\n-  for (FTSENTRY const *ent = e_curr;\n-       ent->fts_level >= FTS_ROOTLEVEL;\n-       ent = ent->fts_parent)\n-    {\n-      if (ad->ino == ent->fts_statp->st_ino\n-          && ad->dev == ent->fts_statp->st_dev)\n-        return;\n-    }\n-  printf (\"ERROR: tree dir, %s, not active\\n\", ad->fts_ent->fts_accpath);\n-  printf (\"active dirs:\\n\");\n-  for (FTSENTRY const *ent = e_curr;\n-       ent->fts_level >= FTS_ROOTLEVEL;\n-       ent = ent->fts_parent)\n-    printf (\"  %s(%\"PRIuMAX\"/%\"PRIuMAX\") to %s(%\"PRIuMAX\"/%\"PRIuMAX\")...\\n\",\n-            ad->fts_ent->fts_accpath,\n-            (uintmax_t) ad->dev,\n-            (uintmax_t) ad->ino,\n-            ent->fts_accpath,\n-            (uintmax_t) ent->fts_statp->st_dev,\n-            (uintmax_t) ent->fts_statp->st_ino);\n-}\n-\n-void\n-fts_cross_check (FTSOBJ const *sp)\n-{\n-  if ( ! ISSET (FTS_TIGHT_CYCLE_CHECK))\n-    return;\n-\n-  FTSENTRY const *ent = sp->fts_cur;\n-\n-  Dprintf ((\"fts-cross-check cur=%s\\n\", ent->fts_path));\n-  /* Make sure every parent dir is in the tree.  */\n-  for (FTSENTRY const *t = ent->fts_parent;\n-       t->fts_level >= FTS_ROOTLEVEL;\n-       t = t->fts_parent)\n-    {\n-      struct Active_dir ad;\n-      ad.ino = t->fts_statp->st_ino;\n-      ad.dev = t->fts_statp->st_dev;\n-      if ( ! hash_lookup (sp->fts_cycle.ht, &ad))\n-        printf (\"ERROR: active dir, %s, not in tree\\n\", t->fts_path);\n-    }\n-\n-  /* Make sure every dir in the tree is an active dir.\n-     But ENT is not necessarily a directory.  If so, just skip this part. */\n-  if (ent->fts_parent->fts_level >= FTS_ROOTLEVEL\n-      && (ent->fts_info == FTS_DP\n-          || ent->fts_info == FTS_D))\n-    for (struct Active_dir *ad = hash_get_first (sp->fts_cycle.ht);\n-         ad != NULL;\n-         ad = hash_get_next (sp->fts_cycle.ht, ad))\n-      {\n-        find_matching_ancestor (ent, ad);\n-      }\n-}\n-\n-static bool\n-same_fd (int fd1, int fd2)\n-{\n-  struct STRUCT_STAT sb1, sb2;\n-  return (FSTAT (fd1, &sb1) == 0\n-          && FSTAT (fd2, &sb2) == 0\n-          && psame_inode (&sb1, &sb2));\n-}\n-\n-static void\n-fd_ring_print (FTSOBJ const *sp, FILE *stream, char const *msg)\n-{\n-  if (!fts_debug)\n-    return;\n-  I_ring const *fd_ring = &sp->fts_fd_ring;\n-  struct devino cwd = getdevino (sp->fts_cwd_fd);\n-  fprintf (stream, \"=== %s ========== \"PRINT_DEVINO\"\\n\", msg, cwd.dev, cwd.ino);\n-  if (i_ring_empty (fd_ring))\n-    return;\n-\n-  unsigned int i = fd_ring->ir_front;\n-  while (true)\n-    {\n-      int fd = fd_ring->ir_data[i];\n-      if (fd < 0)\n-        fprintf (stream, \"%u: %d:\\n\", i, fd);\n-      else\n-        {\n-          struct devino wd = getdevino (fd);\n-          fprintf (stream, \"%u: %d: \"PRINT_DEVINO\"\\n\", i, fd, wd.dev, wd.ino);\n-        }\n-      if (i == fd_ring->ir_back)\n-        break;\n-      i = (i + I_RING_SIZE - 1) % I_RING_SIZE;\n-    }\n-}\n-\n-/* Ensure that each file descriptor on the fd_ring matches a\n-   parent, grandparent, etc. of the current working directory.  */\n-static void\n-fd_ring_check (FTSOBJ const *sp)\n-{\n-  if (!fts_debug)\n-    return;\n-\n-  /* Make a writable copy.  */\n-  I_ring fd_w = sp->fts_fd_ring;\n-\n-  int cwd_fd = sp->fts_cwd_fd;\n-  cwd_fd = fcntl (cwd_fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1);\n-  struct devino dot = getdevino (cwd_fd);\n-  fprintf (stderr, \"===== check ===== cwd: \"PRINT_DEVINO\"\\n\",\n-           dot.dev, dot.ino);\n-  while ( ! i_ring_empty (&fd_w))\n-    {\n-      int fd = i_ring_pop (&fd_w);\n-      if (0 <= fd)\n-        {\n-          int open_flags = O_SEARCH | O_CLOEXEC;\n-          int parent_fd = openat (cwd_fd, \"..\", open_flags);\n-          if (parent_fd < 0)\n-            {\n-              // Warn?\n-              break;\n-            }\n-          if (!same_fd (fd, parent_fd))\n-            {\n-              struct devino cwd = getdevino (fd);\n-              fprintf (stderr, \"ring  : \"PRINT_DEVINO\"\\n\", cwd.dev, cwd.ino);\n-              struct devino c2 = getdevino (parent_fd);\n-              fprintf (stderr, \"parent: \"PRINT_DEVINO\"\\n\", c2.dev, c2.ino);\n-              fts_assert (0);\n-            }\n-          close (cwd_fd);\n-          cwd_fd = parent_fd;\n-        }\n-    }\n-  close (cwd_fd);\n-}\n-#endif\n-\n-static unsigned short int\n-internal_function\n-fts_stat(FTSOBJ *sp, register FTSENTRY *p, bool follow)\n-{\n-        if (ISSET (FTS_LOGICAL)\n-            || (ISSET (FTS_COMFOLLOW) && p->fts_level == FTS_ROOTLEVEL))\n-                follow = true;\n-\n-        struct STRUCT_STAT *sbp = p->fts_statp;\n-\n-        /*\n-         * If doing a logical walk, or application requested FTS_FOLLOW, do\n-         * a stat(2).  If that fails, check for a nonexistent symlink.  If\n-         * fail, set the errno from the stat call.\n-         */\n-        int flags = follow ? 0 : AT_SYMLINK_NOFOLLOW;\n-        if (FSTATAT (sp->fts_cwd_fd, p->fts_accpath, sbp, flags) < 0)\n-          {\n-            if (follow && errno == ENOENT\n-                && 0 <= FSTATAT (sp->fts_cwd_fd, p->fts_accpath, sbp,\n-                                 AT_SYMLINK_NOFOLLOW))\n-              {\n-                __set_errno (0);\n-                return FTS_SLNONE;\n-              }\n-\n-            p->fts_errno = errno;\n-           memset (sbp, 0, sizeof *sbp);\n-            return FTS_NS;\n-          }\n-\n-        if (S_ISDIR(sbp->st_mode)) {\n-                if (ISDOT(p->fts_name)) {\n-                        /* Command-line \".\" and \"..\" are real directories. */\n-                        return (p->fts_level == FTS_ROOTLEVEL ? FTS_D : FTS_DOT);\n-                }\n-\n-                return (FTS_D);\n-        }\n-        if (S_ISLNK(sbp->st_mode))\n-                return (FTS_SL);\n-        if (S_ISREG(sbp->st_mode))\n-                return (FTS_F);\n-        return (FTS_DEFAULT);\n-}\n-\n-static int\n-fts_compar (void const *a, void const *b)\n-{\n-  /* Convert A and B to the correct types, to pacify the compiler, and\n-     for portability to bizarre hosts where \"void const *\" and \"FTSENT\n-     const **\" differ in runtime representation.  The comparison\n-     function cannot modify *a and *b, but there is no compile-time\n-     check for this.  */\n-  FTSENTRY const **pa = (FTSENTRY const **) a;\n-  FTSENTRY const **pb = (FTSENTRY const **) b;\n-  return FTSENT_FTS(pa[0])->fts_compar (pa, pb);\n-}\n-\n-static FTSENTRY *\n-internal_function\n-fts_sort (FTSOBJ *sp, FTSENTRY *head, register size_t nitems)\n-{\n-        register FTSENTRY **ap, *p;\n-\n-        /* On most modern hosts, void * and FTSENT ** have the same\n-           run-time representation, and one can convert sp->fts_compar to\n-           the type qsort expects without problem.  Use the heuristic that\n-           this is OK if the two pointer types are the same size, and if\n-           converting FTSENT ** to uintptr_t is the same as converting\n-           FTSENT ** to void * and then to uintptr_t.  This heuristic isn't\n-           valid in general but we don't know of any counterexamples.  */\n-        FTSENTRY *dummy;\n-        int (*compare) (void const *, void const *) =\n-          ((sizeof &dummy == sizeof (void *)\n-            && (uintptr_t) &dummy == (uintptr_t) (void *) &dummy)\n-           ? (int (*) (void const *, void const *)) sp->fts_compar\n-           : fts_compar);\n-\n-        /*\n-         * Construct an array of pointers to the structures and call qsort(3).\n-         * Reassemble the array in the order returned by qsort.  If unable to\n-         * sort for memory reasons, return the directory entries in their\n-         * current order.  Allocate enough space for the current needs plus\n-         * 40 so don't realloc one entry at a time.\n-         */\n-        if (nitems > sp->fts_nitems) {\n-                sp->fts_nitems = nitems + 40;\n-                FTSENTRY **a;\n-                if (! (a = reallocarray (sp->fts_array,\n-                                         sp->fts_nitems, sizeof *a))) {\n-                        free(sp->fts_array);\n-                        sp->fts_array = NULL;\n-                        sp->fts_nitems = 0;\n-                        return (head);\n-                }\n-                sp->fts_array = a;\n-        }\n-        for (ap = sp->fts_array, p = head; p; p = p->fts_link)\n-                *ap++ = p;\n-        qsort((void *)sp->fts_array, nitems, sizeof(FTSENTRY *), compare);\n-        for (head = *(ap = sp->fts_array); --nitems; ++ap)\n-                ap[0]->fts_link = ap[1];\n-        ap[0]->fts_link = NULL;\n-        return (head);\n-}\n-\n-static FTSENTRY *\n-internal_function\n-fts_alloc (FTSOBJ *sp, const char *name, register size_t namelen)\n-{\n-        /*\n-         * The file name is a variable length array.  Allocate the FTSENT\n-         * structure and the file name in one chunk.\n-         */\n-        size_t len = FLEXSIZEOF(FTSENT, fts_name, namelen + 1);\n-\tregister FTSENTRY *p;\n-#if !_LIBC\n-        p = malloc(len);\n-        if (p == NULL)\n-                return (NULL);\n-#else\n-\t/*\n-\t * For glibc, we use a wrapper struct to provide the extra required\n-\t * fields without changing the FSENT layout.\n-\t */\n-\tlen += sizeof (struct FTSENT_wrapper);\n-\tstruct FTSENT_wrapper *wrapper = malloc(len);\n-\tif (wrapper == NULL)\n-\t\treturn (NULL);\n-\tp = &wrapper->ent;\n-        p->fts_statp = &wrapper->fts_stat;\n-#endif\n-\n-        /* Copy the name and guarantee NUL termination. */\n-        memcpy(p->fts_name, name, namelen);\n-        p->fts_name[namelen] = '\\0';\n-\n-        p->fts_namelen = namelen;\n-        FTSENT_FTS(p)= sp;\n-        p->fts_path = sp->fts_path;\n-        p->fts_errno = 0;\n-        FTSENT_DIRP(p) = NULL;\n-        p->fts_flags = 0;\n-        p->fts_instr = FTS_NOINSTR;\n-        p->fts_number = 0;\n-        p->fts_pointer = NULL;\n-        return (p);\n-}\n-\n-static void\n-internal_function\n-fts_lfree (register FTSENTRY *head)\n-{\n-        int saved_errno = errno;\n-\n-        /* Free a linked list of structures. */\n-        register FTSENTRY *p;\n-        while ((p = head)) {\n-                head = head->fts_link;\n-                if (FTSENT_DIRP(p))\n-                        closedir (FTSENT_DIRP(p));\n-                free(FTSENT_WRAPPER(p));\n-        }\n-\n-        __set_errno (saved_errno);\n-}\n-\n-/*\n- * Allow essentially unlimited file name lengths; find, rm, ls should\n- * all work on any tree.  Most systems will allow creation of file\n- * names much longer than MAXPATHLEN, even though the kernel won't\n- * resolve them.  Add the size (not just what's needed) plus 256 bytes\n- * so don't realloc the file name 2 bytes at a time.\n- */\n-static bool\n-internal_function\n-fts_palloc (FTSOBJ *sp, size_t more)\n-{\n-        size_t new_len = sp->fts_pathlen + more + 256;\n-\n-        /*\n-         * See if fts_pathlen would overflow.\n-         */\n-        if (new_len < sp->fts_pathlen) {\n-                free(sp->fts_path);\n-                sp->fts_path = NULL;\n-                __set_errno (ENAMETOOLONG);\n-                return false;\n-        }\n-        sp->fts_pathlen = new_len;\n-        char *p = realloc(sp->fts_path, sp->fts_pathlen);\n-        if (p == NULL) {\n-                free(sp->fts_path);\n-                sp->fts_path = NULL;\n-                return false;\n-        }\n-        sp->fts_path = p;\n-        return true;\n-}\n-\n-/*\n- * When the file name is realloc'd, have to fix all of the pointers in\n- *  structures already returned.\n- */\n-static void\n-internal_function\n-fts_padjust (FTSOBJ *sp, FTSENTRY *head)\n-{\n-        char *addr = sp->fts_path;\n-\n-        /* This code looks at bit-patterns of freed pointers to\n-           relocate them, so it relies on undefined behavior.  If this\n-           trick does not work on your platform, please report a bug.  */\n-\n-#define ADJUST(p) do {                                                  \\\n-        uintptr_t old_accpath = (uintptr_t) (p)->fts_accpath;           \\\n-        if (old_accpath != (uintptr_t) (p)->fts_name) {                 \\\n-                (p)->fts_accpath =                                      \\\n-                  addr + (old_accpath - (uintptr_t) (p)->fts_path);     \\\n-        }                                                               \\\n-        (p)->fts_path = addr;                                           \\\n-} while (0)\n-        /* Adjust the current set of children. */\n-        for (FTSENTRY *p = sp->fts_child; p; p = p->fts_link)\n-                ADJUST(p);\n-\n-        /* Adjust the rest of the tree, including the current level. */\n-        for (FTSENTRY *p = head; p->fts_level >= FTS_ROOTLEVEL;) {\n-                ADJUST(p);\n-                p = p->fts_link ? p->fts_link : p->fts_parent;\n-        }\n-}\n-\n-static size_t\n-internal_function _GL_ATTRIBUTE_PURE\n-fts_maxarglen (char * const *argv)\n-{\n-        size_t max;\n-\n-        for (max = 0; *argv; ++argv) {\n-                size_t len = strlen(*argv);\n-                if (len > max)\n-                        max = len;\n-        }\n-        return (max + 1);\n-}\n-\n-/*\n- * Change to dir specified by fd or file name without getting\n- * tricked by someone changing the world out from underneath us.\n- * Assumes p->fts_statp->st_dev and p->fts_statp->st_ino are filled in.\n- * If FD is non-negative, expect it to be used after this function returns,\n- * and to be closed eventually.  So don't pass e.g., 'dirfd(dirp)' and then\n- * do closedir(dirp), because that would invalidate the saved FD.\n- * Upon failure, close FD immediately and return nonzero.\n- */\n-static int\n-internal_function\n-fts_safe_changedir (FTSOBJ *sp, FTSENTRY *p, int fd, char const *dir)\n-{\n-        fts_assert (0 <= fd || dir != NULL);\n-        bool is_dotdot = dir && streq (dir, \"..\");\n-\n-        /* This clause handles the unusual case in which FTS_NOCHDIR\n-           is specified, along with FTS_CWDFD.  In that case, there is\n-           no need to change even the virtual cwd file descriptor.\n-           However, if FD is non-negative, we do close it here.  */\n-        if (ISSET (FTS_NOCHDIR))\n-          {\n-            if (ISSET (FTS_CWDFD) && 0 <= fd)\n-              close (fd);\n-            return 0;\n-          }\n-\n-        if (fd < 0 && is_dotdot && ISSET (FTS_CWDFD))\n-          {\n-            /* When possible, skip the diropen and subsequent fstat+dev/ino\n-               comparison.  I.e., when changing to parent directory\n-               (chdir (\"..\")), use a file descriptor from the ring and\n-               save the overhead of diropen+fstat, as well as avoiding\n-               failure when we lack \"x\" access to the virtual cwd.  */\n-            if ( ! i_ring_empty (&sp->fts_fd_ring))\n-              {\n-                int parent_fd;\n-                fd_ring_print (sp, stderr, \"pre-pop\");\n-                parent_fd = i_ring_pop (&sp->fts_fd_ring);\n-                if (0 <= parent_fd)\n-                  {\n-                    fd = parent_fd;\n-                    dir = NULL;\n-                  }\n-              }\n-          }\n-\n-        int newfd = fd;\n-        if (fd < 0 && (newfd = diropen (sp, dir)) < 0)\n-          return -1;\n-\n-        /* The following dev/inode check is necessary if we're doing a\n-           \"logical\" traversal (through symlinks, a la chown -L), if the\n-           system lacks O_NOFOLLOW support, or if we're changing to \"..\"\n-           (but not via a popped file descriptor).  When changing to the\n-           name \"..\", O_NOFOLLOW can't help.  In general, when the target is\n-           not \"..\", diropen's use of O_NOFOLLOW ensures we don't mistakenly\n-           follow a symlink, so we can avoid the expense of this fstat.  */\n-        int ret;\n-        if (ISSET(FTS_LOGICAL) || ! HAVE_WORKING_O_NOFOLLOW\n-            || (dir && streq (dir, \"..\")))\n-          {\n-            struct STRUCT_STAT sb;\n-            if (FSTAT (newfd, &sb))\n-              {\n-                ret = -1;\n-                goto bail;\n-              }\n-            if (p->fts_statp->st_dev != sb.st_dev\n-                || p->fts_statp->st_ino != sb.st_ino)\n-              {\n-                __set_errno (ENOENT);           /* disinformation */\n-                ret = -1;\n-                goto bail;\n-              }\n-          }\n-\n-        if (ISSET(FTS_CWDFD))\n-          {\n-            cwd_advance_fd (sp, newfd, ! is_dotdot);\n-            return 0;\n-          }\n-\n-        ret = fchdir(newfd);\n-bail:\n-        if (fd < 0)\n-          {\n-            int oerrno = errno;\n-            (void)close(newfd);\n-            __set_errno (oerrno);\n-          }\n-        return ret;\n-}\ndiff --git a/io/fts64-time64.c b/io/fts64-time64.c\nindex 6a1053194e..29f2dbc28c 100644\n--- a/io/fts64-time64.c\n+++ b/io/fts64-time64.c\n@@ -33,5 +33,5 @@\n # define STRUCT_STATFS      statfs64\n # define FSTATFS            __fstatfs64\n \n-# include \"fts.c\"\n+# include \"fts-common.c\"\n #endif\ndiff --git a/io/fts64.c b/io/fts64.c\nindex a6f607a873..1efa06ab3b 100644\n--- a/io/fts64.c\n+++ b/io/fts64.c\n@@ -16,11 +16,11 @@\n    License along with the GNU C Library; if not, see\n    <https://www.gnu.org/licenses/>.  */\n \n-#define FTS_OPEN fts64_open\n-#define FTS_CLOSE fts64_close\n-#define FTS_READ fts64_read\n-#define FTS_SET fts64_set\n-#define FTS_CHILDREN fts64_children\n+#define FTS_OPEN __fts64_open\n+#define FTS_CLOSE __fts64_close\n+#define FTS_READ __fts64_read\n+#define FTS_SET __fts64_set\n+#define FTS_CHILDREN __fts64_children\n #define FTSOBJ FTS64\n #define FTSENTRY FTSENT64\n #define INO_T ino64_t\n@@ -30,4 +30,30 @@\n #define STRUCT_STATFS statfs64\n #define FSTATFS __fstatfs64\n \n-#include \"fts.c\"\n+#define fts_open __rename_fts_open\n+#define fts_close __rename_fts_close\n+#define fts_read __rename_fts_read\n+#define fts_set __rename_fts_set\n+#define fts_children __rename_fts_children\n+\n+#include \"fts-common.c\"\n+\n+#undef fts_open\n+#undef fts_close\n+#undef fts_read\n+#undef fts_set\n+#undef fts_children\n+\n+weak_alias (__fts64_open, fts64_open)\n+weak_alias (__fts64_close, fts64_close)\n+weak_alias (__fts64_read, fts64_read)\n+weak_alias (__fts64_set, fts64_set)\n+weak_alias (__fts64_children, fts64_children)\n+\n+#ifdef __OFF_T_MATCHES_OFF64_T\n+weak_alias (__fts64_open, fts_open)\n+weak_alias (__fts64_close, fts_close)\n+weak_alias (__fts64_read, fts_read)\n+weak_alias (__fts64_set, fts_set)\n+weak_alias (__fts64_children, fts_children)\n+#endif\ndiff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fts.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fts.c\ndeleted file mode 100644\nindex d0c62e6195..0000000000\n--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/fts.c\n+++ /dev/null\n@@ -1 +0,0 @@\n-#include <io/fts.c>\ndiff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fts64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fts64.c\ndeleted file mode 100644\nindex 2472f8bf75..0000000000\n--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/fts64.c\n+++ /dev/null\n@@ -1 +0,0 @@\n-#include <io/fts64.c>\ndiff --git a/sysdeps/unix/sysv/linux/x86_64/x32/fts.c b/sysdeps/unix/sysv/linux/x86_64/x32/fts.c\ndeleted file mode 100644\nindex 980573ed68..0000000000\n--- a/sysdeps/unix/sysv/linux/x86_64/x32/fts.c\n+++ /dev/null\n@@ -1 +0,0 @@\n-#include <sysdeps/wordsize-64/fts.c>\ndiff --git a/sysdeps/unix/sysv/linux/x86_64/x32/fts64.c b/sysdeps/unix/sysv/linux/x86_64/x32/fts64.c\ndeleted file mode 100644\nindex 221d1b5608..0000000000\n--- a/sysdeps/unix/sysv/linux/x86_64/x32/fts64.c\n+++ /dev/null\n@@ -1 +0,0 @@\n-#include <sysdeps/wordsize-64/fts64.c>\ndiff --git a/sysdeps/wordsize-64/fts.c b/sysdeps/wordsize-64/fts.c\ndeleted file mode 100644\nindex 159dc1febe..0000000000\n--- a/sysdeps/wordsize-64/fts.c\n+++ /dev/null\n@@ -1,19 +0,0 @@\n-#define fts64_open __rename_fts64_open\n-#define fts64_close __rename_fts64_close\n-#define fts64_read __rename_fts64_read\n-#define fts64_set __rename_fts64_set\n-#define fts64_children __rename_fts64_children\n-\n-#include \"../../io/fts.c\"\n-\n-#undef fts64_open\n-#undef fts64_close\n-#undef fts64_read\n-#undef fts64_set\n-#undef fts64_children\n-\n-weak_alias (fts_open, fts64_open)\n-weak_alias (fts_close, fts64_close)\n-weak_alias (fts_read, fts64_read)\n-weak_alias (fts_set, fts64_set)\n-weak_alias (fts_children, fts64_children)\ndiff --git a/sysdeps/wordsize-64/fts64.c b/sysdeps/wordsize-64/fts64.c\ndeleted file mode 100644\nindex f2848fc3e4..0000000000\n--- a/sysdeps/wordsize-64/fts64.c\n+++ /dev/null\n@@ -1 +0,0 @@\n-/* Defined in fts.c.  */\n",
    "prefixes": [
        "1/3"
    ]
}