From: Baruch Siach Date: Fri, 8 Jun 2018 06:21:57 +0000 (+0300) Subject: elfutils: bump to version 0.171 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f0335b0cf78dee43df93b9ee17d86f1443990cca;p=buildroot.git elfutils: bump to version 0.171 Drop the po/ disable patch; not needed anymore. Drop the __mempcpy compatibility patch; __mempcpy is not used anymore. Refresh the -Werror removal patch; still needed, unfortunately. Renumber the remaining patches. Add GPLv3 license file. Add license files hash. [Peter: drop security reference, was added post-release] Cc: Stefan Fröberg Signed-off-by: Baruch Siach Signed-off-by: Peter Korsgaard --- diff --git a/package/elfutils/0001-Add-a-enable-disable-progs-configure-option.patch b/package/elfutils/0001-Add-a-enable-disable-progs-configure-option.patch new file mode 100644 index 0000000000..3f80fe60df --- /dev/null +++ b/package/elfutils/0001-Add-a-enable-disable-progs-configure-option.patch @@ -0,0 +1,62 @@ +From dfea82b761b2ea4708fbf9370a5467ae4be525ca Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Mon, 29 May 2017 23:03:48 +0300 +Subject: [PATCH] Add a --{enable,disable}-progs configure option + +Add a --{enable,disable}-progs configuration option to elfutils. This +allows to selectively disable the compilation of the elfutils programs +(in which case only the libraries are built and installed). This is +useful because the programs are often not needed, and also because +building the programs against uClibc causes several issues (lack of +obstack_printf() in uClibc for example). + +Based on the former patch by Thomas Petazzoni. + +[Vincent: tweak patch for 0.166] + +Signed-off-by: Thomas Petazzoni +Signed-off-by: Vicente Olivert Riera +--- + Makefile.am | 6 +++++- + configure.ac | 6 ++++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/Makefile.am b/Makefile.am +index 2ff444e7bf1d..70443abb4fb6 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -26,9 +26,13 @@ AM_MAKEFLAGS = --no-print-directory + + pkginclude_HEADERS = version.h + ++if ENABLE_PROGS ++PROGS_SUBDIR = src ++endif ++ + # Add doc back when we have some real content. + SUBDIRS = config m4 lib libelf libebl libdwelf libdwfl libdw libcpu libasm \ +- backends src po tests ++ backends $(PROGS_SUBDIR) po tests + + EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING \ + COPYING COPYING-GPLV2 COPYING-LGPLV3 +diff --git a/configure.ac b/configure.ac +index c2c1d90b2133..7b4c38381cca 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -259,6 +259,12 @@ AC_SUBST([LIBEBL_SUBDIR]) + AC_DEFINE_UNQUOTED(LIBEBL_SUBDIR, "$LIBEBL_SUBDIR") + AH_TEMPLATE([LIBEBL_SUBDIR], [$libdir subdirectory containing libebl modules.]) + ++AC_ARG_ENABLE([progs], ++ AS_HELP_STRING([--enable-progs], [enable progs]), ++ enable_progs=$enableval, ++ enable_progs=yes) ++AM_CONDITIONAL(ENABLE_PROGS, test "$enable_progs" = yes) ++ + dnl zlib is mandatory. + save_LIBS="$LIBS" + LIBS= +-- +2.11.0 + diff --git a/package/elfutils/0002-Add-an-implementation-of-the-fts_-functions.patch b/package/elfutils/0002-Add-an-implementation-of-the-fts_-functions.patch new file mode 100644 index 0000000000..cf5ba25c82 --- /dev/null +++ b/package/elfutils/0002-Add-an-implementation-of-the-fts_-functions.patch @@ -0,0 +1,1332 @@ +From 098760f7eac1fb86b3f6871d5bb10f9f44468f2d Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Mon, 29 May 2017 23:08:05 +0300 +Subject: [PATCH] Add an implementation of the fts_*() functions + +The fts_*() functions are optional in uClibc, and not compiled in our +default configuration. The best option would be to migrate this +elfutils code to the nftw family of functions, but it requires quite +some work. + +So we have several options here: + + *) Enable fts_*() functions in our default uClibc configuration. Not + nice since only one package needs them (the help text of uClibc + for fts_*() functions explicitly mention that they have been added + to be able to build elfutils). + + *) Use gnulib, but it is quite heavy to setup, requires modifications + to configure.ac, and other things. + + *) Copy the fts function from uClibc into elfutils source code. This + is the solution used below. uClibc is LGPL, and elfutils is + LGPL/GPL, so there should not be any licensing issue. + +Of course, the fts_*() functions are only built if they are not +already provided by the C library. + +Based on the former patch by Thomas Petazzoni. + +[Vincent: tweak patch for 0.166] + +Signed-off-by: Thomas Petazzoni +Signed-off-by: Vicente Olivert Riera +--- + configure.ac | 4 + + libdwfl/Makefile.am | 3 + + libdwfl/fts.c | 1095 ++++++++++++++++++++++++++++++++++++++++ + libdwfl/fts_.h | 131 +++++ + libdwfl/linux-kernel-modules.c | 4 + + 5 files changed, 1237 insertions(+) + create mode 100644 libdwfl/fts.c + create mode 100644 libdwfl/fts_.h + +diff --git a/configure.ac b/configure.ac +index 7b4c38381cca..bcebb05fa532 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -265,6 +265,10 @@ AC_ARG_ENABLE([progs], + enable_progs=yes) + AM_CONDITIONAL(ENABLE_PROGS, test "$enable_progs" = yes) + ++AC_CHECK_HEADER([fts.h], ++ AC_DEFINE([HAVE_FTS_H], [], [Define if is available in C library])) ++AM_CONDITIONAL(HAVE_FTS, test "$ac_cv_header_fts_h" = yes) ++ + dnl zlib is mandatory. + save_LIBS="$LIBS" + LIBS= +diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am +index 89ca92ed8110..a5a5615c5f94 100644 +--- a/libdwfl/Makefile.am ++++ b/libdwfl/Makefile.am +@@ -77,6 +77,9 @@ endif + if LZMA + libdwfl_a_SOURCES += lzma.c + endif ++if !HAVE_FTS ++libdwfl_a_SOURCES += fts.c ++endif + + libdwfl = $(libdw) + libdw = ../libdw/libdw.so +diff --git a/libdwfl/fts.c b/libdwfl/fts.c +new file mode 100644 +index 000000000000..f34cc03bd963 +--- /dev/null ++++ b/libdwfl/fts.c +@@ -0,0 +1,1095 @@ ++/*- ++ * Copyright (c) 1990, 1993, 1994 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 4. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "fts_.h" ++#include ++#include ++#include ++ ++/* Largest alignment size needed, minus one. ++ Usually long double is the worst case. */ ++#ifndef ALIGNBYTES ++#define ALIGNBYTES (__alignof__ (long double) - 1) ++#endif ++/* Align P to that size. */ ++#ifndef ALIGN ++#define ALIGN(p) (((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES) ++#endif ++ ++ ++static FTSENT *fts_alloc (FTS *, const char *, size_t); ++static FTSENT *fts_build (FTS *, int); ++static void fts_lfree (FTSENT *); ++static void fts_load (FTS *, FTSENT *); ++static size_t fts_maxarglen (char * const *); ++static void fts_padjust (FTS *, FTSENT *); ++static int fts_palloc (FTS *, size_t); ++static FTSENT *fts_sort (FTS *, FTSENT *, int); ++static u_short fts_stat (FTS *, FTSENT *, int); ++static int fts_safe_changedir (FTS *, FTSENT *, int, const char *); ++ ++#ifndef MAX ++#define MAX(a, b) ({ __typeof__ (a) _a = (a); \ ++ __typeof__ (b) _b = (b); \ ++ _a > _b ? _a : _b; }) ++#endif ++ ++#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) ++ ++#define CLR(opt) (sp->fts_options &= ~(opt)) ++#define ISSET(opt) (sp->fts_options & (opt)) ++#define SET(opt) (sp->fts_options |= (opt)) ++ ++#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) ++ ++/* fts_build flags */ ++#define BCHILD 1 /* fts_children */ ++#define BNAMES 2 /* fts_children, names only */ ++#define BREAD 3 /* fts_read */ ++ ++FTS * ++fts_open( char * const *argv, register int options, ++ int (*compar) (const FTSENT **, const FTSENT **)) ++{ ++ register FTS *sp; ++ register FTSENT *p, *root; ++ register int nitems; ++ FTSENT *parent = NULL; ++ FTSENT *tmp = NULL; ++ ++ /* Options check. */ ++ if (options & ~FTS_OPTIONMASK) { ++ errno = EINVAL; ++ return (NULL); ++ } ++ ++ /* Allocate/initialize the stream */ ++ if ((sp = malloc((u_int)sizeof(FTS))) == NULL) ++ return (NULL); ++ memset(sp, 0, sizeof(FTS)); ++ sp->fts_compar = (int (*) (const void *, const void *)) compar; ++ sp->fts_options = options; ++ ++ /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ ++ if (ISSET(FTS_LOGICAL)) ++ SET(FTS_NOCHDIR); ++ ++ /* ++ * Start out with 1K of path space, and enough, in any case, ++ * to hold the user's paths. ++ */ ++#ifndef MAXPATHLEN ++#define MAXPATHLEN 1024 ++#endif ++ size_t maxarglen = fts_maxarglen(argv); ++ if (fts_palloc(sp, MAX(maxarglen, MAXPATHLEN))) ++ goto mem1; ++ ++ /* Allocate/initialize root's parent. */ ++ if (*argv != NULL) { ++ if ((parent = fts_alloc(sp, "", 0)) == NULL) ++ goto mem2; ++ parent->fts_level = FTS_ROOTPARENTLEVEL; ++ } ++ ++ /* Allocate/initialize root(s). */ ++ for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) { ++ /* Don't allow zero-length paths. */ ++ size_t len = strlen(*argv); ++ if (len == 0) { ++ errno = ENOENT; ++ goto mem3; ++ } ++ ++ p = fts_alloc(sp, *argv, len); ++ p->fts_level = FTS_ROOTLEVEL; ++ p->fts_parent = parent; ++ p->fts_accpath = p->fts_name; ++ p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW)); ++ ++ /* Command-line "." and ".." are real directories. */ ++ if (p->fts_info == FTS_DOT) ++ p->fts_info = FTS_D; ++ ++ /* ++ * If comparison routine supplied, traverse in sorted ++ * order; otherwise traverse in the order specified. ++ */ ++ if (compar) { ++ p->fts_link = root; ++ root = p; ++ } else { ++ p->fts_link = NULL; ++ if (root == NULL) ++ tmp = root = p; ++ else { ++ tmp->fts_link = p; ++ tmp = p; ++ } ++ } ++ } ++ if (compar && nitems > 1) ++ root = fts_sort(sp, root, nitems); ++ ++ /* ++ * Allocate a dummy pointer and make fts_read think that we've just ++ * finished the node before the root(s); set p->fts_info to FTS_INIT ++ * so that everything about the "current" node is ignored. ++ */ ++ if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL) ++ goto mem3; ++ sp->fts_cur->fts_link = root; ++ sp->fts_cur->fts_info = FTS_INIT; ++ ++ /* ++ * If using chdir(2), grab a file descriptor pointing to dot to ensure ++ * that we can get back here; this could be avoided for some paths, ++ * but almost certainly not worth the effort. Slashes, symbolic links, ++ * and ".." are all fairly nasty problems. Note, if we can't get the ++ * descriptor we run anyway, just more slowly. ++ */ ++ if (!ISSET(FTS_NOCHDIR) ++ && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0) ++ SET(FTS_NOCHDIR); ++ ++ return (sp); ++ ++mem3: fts_lfree(root); ++ free(parent); ++mem2: free(sp->fts_path); ++mem1: free(sp); ++ return (NULL); ++} ++ ++static void ++fts_load(FTS *sp, register FTSENT *p) ++{ ++ register int len; ++ register char *cp; ++ ++ /* ++ * Load the stream structure for the next traversal. Since we don't ++ * actually enter the directory until after the preorder visit, set ++ * the fts_accpath field specially so the chdir gets done to the right ++ * place and the user can access the first node. From fts_open it's ++ * known that the path will fit. ++ */ ++ len = p->fts_pathlen = p->fts_namelen; ++ memmove(sp->fts_path, p->fts_name, len + 1); ++ if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) { ++ len = strlen(++cp); ++ memmove(p->fts_name, cp, len + 1); ++ p->fts_namelen = len; ++ } ++ p->fts_accpath = p->fts_path = sp->fts_path; ++ sp->fts_dev = p->fts_dev; ++} ++ ++int ++fts_close(FTS *sp) ++{ ++ register FTSENT *freep, *p; ++ int saved_errno; ++ ++ /* ++ * This still works if we haven't read anything -- the dummy structure ++ * points to the root list, so we step through to the end of the root ++ * list which has a valid parent pointer. ++ */ ++ if (sp->fts_cur) { ++ for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) { ++ freep = p; ++ p = p->fts_link != NULL ? p->fts_link : p->fts_parent; ++ free(freep); ++ } ++ free(p); ++ } ++ ++ /* Free up child linked list, sort array, path buffer. */ ++ if (sp->fts_child) ++ fts_lfree(sp->fts_child); ++ free(sp->fts_array); ++ free(sp->fts_path); ++ ++ /* Return to original directory, save errno if necessary. */ ++ if (!ISSET(FTS_NOCHDIR)) { ++ saved_errno = fchdir(sp->fts_rfd) ? errno : 0; ++ (void)close(sp->fts_rfd); ++ ++ /* Set errno and return. */ ++ if (saved_errno != 0) { ++ /* Free up the stream pointer. */ ++ free(sp); ++ errno = saved_errno; ++ return (-1); ++ } ++ } ++ ++ /* Free up the stream pointer. */ ++ free(sp); ++ return (0); ++} ++ ++/* ++ * Special case of "/" at the end of the path so that slashes aren't ++ * appended which would cause paths to be written as "....//foo". ++ */ ++#define NAPPEND(p) \ ++ (p->fts_path[p->fts_pathlen - 1] == '/' \ ++ ? p->fts_pathlen - 1 : p->fts_pathlen) ++ ++FTSENT * ++fts_read(register FTS *sp) ++{ ++ register FTSENT *p, *tmp; ++ register int instr; ++ register char *t; ++ int saved_errno; ++ ++ /* If finished or unrecoverable error, return NULL. */ ++ if (sp->fts_cur == NULL || ISSET(FTS_STOP)) ++ return (NULL); ++ ++ /* Set current node pointer. */ ++ p = sp->fts_cur; ++ ++ /* Save and zero out user instructions. */ ++ instr = p->fts_instr; ++ p->fts_instr = FTS_NOINSTR; ++ ++ /* Any type of file may be re-visited; re-stat and re-turn. */ ++ if (instr == FTS_AGAIN) { ++ p->fts_info = fts_stat(sp, p, 0); ++ return (p); ++ } ++ ++ /* ++ * Following a symlink -- SLNONE test allows application to see ++ * SLNONE and recover. If indirecting through a symlink, have ++ * keep a pointer to current location. If unable to get that ++ * pointer, follow fails. ++ */ ++ if (instr == FTS_FOLLOW && ++ (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { ++ p->fts_info = fts_stat(sp, p, 1); ++ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { ++ if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) { ++ p->fts_errno = errno; ++ p->fts_info = FTS_ERR; ++ } else ++ p->fts_flags |= FTS_SYMFOLLOW; ++ } ++ return (p); ++ } ++ ++ /* Directory in pre-order. */ ++ if (p->fts_info == FTS_D) { ++ /* If skipped or crossed mount point, do post-order visit. */ ++ if (instr == FTS_SKIP || ++ (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) { ++ if (p->fts_flags & FTS_SYMFOLLOW) ++ (void)close(p->fts_symfd); ++ if (sp->fts_child) { ++ fts_lfree(sp->fts_child); ++ sp->fts_child = NULL; ++ } ++ p->fts_info = FTS_DP; ++ return (p); ++ } ++ ++ /* Rebuild if only read the names and now traversing. */ ++ if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) { ++ CLR(FTS_NAMEONLY); ++ fts_lfree(sp->fts_child); ++ sp->fts_child = NULL; ++ } ++ ++ /* ++ * Cd to the subdirectory. ++ * ++ * If have already read and now fail to chdir, whack the list ++ * to make the names come out right, and set the parent errno ++ * so the application will eventually get an error condition. ++ * Set the FTS_DONTCHDIR flag so that when we logically change ++ * directories back to the parent we don't do a chdir. ++ * ++ * If haven't read do so. If the read fails, fts_build sets ++ * FTS_STOP or the fts_info field of the node. ++ */ ++ if (sp->fts_child != NULL) { ++ if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { ++ p->fts_errno = errno; ++ p->fts_flags |= FTS_DONTCHDIR; ++ for (p = sp->fts_child; p != NULL; ++ p = p->fts_link) ++ p->fts_accpath = ++ p->fts_parent->fts_accpath; ++ } ++ } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) { ++ if (ISSET(FTS_STOP)) ++ return (NULL); ++ return (p); ++ } ++ p = sp->fts_child; ++ sp->fts_child = NULL; ++ sp->fts_cur = p; ++ goto name; ++ } ++ ++ /* Move to the next node on this level. */ ++next: tmp = p; ++ if ((p = p->fts_link) != NULL) { ++ sp->fts_cur = p; ++ free(tmp); ++ ++ /* ++ * If reached the top, return to the original directory (or ++ * the root of the tree), and load the paths for the next root. ++ */ ++ if (p->fts_level == FTS_ROOTLEVEL) { ++ if (FCHDIR(sp, sp->fts_rfd)) { ++ SET(FTS_STOP); ++ return (NULL); ++ } ++ fts_load(sp, p); ++ return p; ++ } ++ ++ /* ++ * User may have called fts_set on the node. If skipped, ++ * ignore. If followed, get a file descriptor so we can ++ * get back if necessary. ++ */ ++ if (p->fts_instr == FTS_SKIP) ++ goto next; ++ if (p->fts_instr == FTS_FOLLOW) { ++ p->fts_info = fts_stat(sp, p, 1); ++ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { ++ if ((p->fts_symfd = ++ open(".", O_RDONLY, 0)) < 0) { ++ p->fts_errno = errno; ++ p->fts_info = FTS_ERR; ++ } else ++ p->fts_flags |= FTS_SYMFOLLOW; ++ } ++ p->fts_instr = FTS_NOINSTR; ++ } ++ ++name: t = sp->fts_path + NAPPEND(p->fts_parent); ++ *t++ = '/'; ++ memmove(t, p->fts_name, p->fts_namelen + 1); ++ return p; ++ } ++ ++ /* Move up to the parent node. */ ++ p = tmp->fts_parent; ++ sp->fts_cur = p; ++ free(tmp); ++ ++ if (p->fts_level == FTS_ROOTPARENTLEVEL) { ++ /* ++ * Done; free everything up and set errno to 0 so the user ++ * can distinguish between error and EOF. ++ */ ++ free(p); ++ errno = 0; ++ return (sp->fts_cur = NULL); ++ } ++ ++ /* NUL terminate the pathname. */ ++ sp->fts_path[p->fts_pathlen] = '\0'; ++ ++ /* ++ * Return to the parent directory. If at a root node or came through ++ * a symlink, go back through the file descriptor. Otherwise, cd up ++ * one directory. ++ */ ++ if (p->fts_level == FTS_ROOTLEVEL) { ++ if (FCHDIR(sp, sp->fts_rfd)) { ++ SET(FTS_STOP); ++ return (NULL); ++ } ++ } else if (p->fts_flags & FTS_SYMFOLLOW) { ++ if (FCHDIR(sp, p->fts_symfd)) { ++ saved_errno = errno; ++ (void)close(p->fts_symfd); ++ errno = saved_errno; ++ SET(FTS_STOP); ++ return (NULL); ++ } ++ (void)close(p->fts_symfd); ++ } else if (!(p->fts_flags & FTS_DONTCHDIR) && ++ fts_safe_changedir(sp, p->fts_parent, -1, "..")) { ++ SET(FTS_STOP); ++ return (NULL); ++ } ++ p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; ++ return p; ++} ++ ++/* ++ * Fts_set takes the stream as an argument although it's not used in this ++ * implementation; it would be necessary if anyone wanted to add global ++ * semantics to fts using fts_set. An error return is allowed for similar ++ * reasons. ++ */ ++/* ARGSUSED */ ++int ++fts_set(FTS *sp, FTSENT *p, int instr) ++{ ++ if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW && ++ instr != FTS_NOINSTR && instr != FTS_SKIP) { ++ errno = EINVAL; ++ return (1); ++ } ++ p->fts_instr = instr; ++ return (0); ++} ++ ++FTSENT * ++fts_children(register FTS *sp, int instr) ++{ ++ register FTSENT *p; ++ int fd; ++ ++ if (instr != 0 && instr != FTS_NAMEONLY) { ++ errno = EINVAL; ++ return (NULL); ++ } ++ ++ /* Set current node pointer. */ ++ p = sp->fts_cur; ++ ++ /* ++ * Errno set to 0 so user can distinguish empty directory from ++ * an error. ++ */ ++ errno = 0; ++ ++ /* Fatal errors stop here. */ ++ if (ISSET(FTS_STOP)) ++ return (NULL); ++ ++ /* Return logical hierarchy of user's arguments. */ ++ if (p->fts_info == FTS_INIT) ++ return (p->fts_link); ++ ++ /* ++ * If not a directory being visited in pre-order, stop here. Could ++ * allow FTS_DNR, assuming the user has fixed the problem, but the ++ * same effect is available with FTS_AGAIN. ++ */ ++ if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */) ++ return (NULL); ++ ++ /* Free up any previous child list. */ ++ if (sp->fts_child != NULL) ++ fts_lfree(sp->fts_child); ++ ++ if (instr == FTS_NAMEONLY) { ++ SET(FTS_NAMEONLY); ++ instr = BNAMES; ++ } else ++ instr = BCHILD; ++ ++ /* ++ * If using chdir on a relative path and called BEFORE fts_read does ++ * its chdir to the root of a traversal, we can lose -- we need to ++ * chdir into the subdirectory, and we don't know where the current ++ * directory is, so we can't get back so that the upcoming chdir by ++ * fts_read will work. ++ */ ++ if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' || ++ ISSET(FTS_NOCHDIR)) ++ return (sp->fts_child = fts_build(sp, instr)); ++ ++ if ((fd = open(".", O_RDONLY, 0)) < 0) ++ return (NULL); ++ sp->fts_child = fts_build(sp, instr); ++ if (fchdir(fd)) ++ return (NULL); ++ (void)close(fd); ++ return (sp->fts_child); ++} ++ ++/* ++ * This is the tricky part -- do not casually change *anything* in here. The ++ * idea is to build the linked list of entries that are used by fts_children ++ * and fts_read. There are lots of special cases. ++ * ++ * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is ++ * set and it's a physical walk (so that symbolic links can't be directories), ++ * we can do things quickly. First, if it's a 4.4BSD file system, the type ++ * of the file is in the directory entry. Otherwise, we assume that the number ++ * of subdirectories in a node is equal to the number of links to the parent. ++ * The former skips all stat calls. The latter skips stat calls in any leaf ++ * directories and for any files after the subdirectories in the directory have ++ * been found, cutting the stat calls by about 2/3. ++ */ ++static FTSENT * ++fts_build(register FTS *sp, int type) ++{ ++ register struct dirent *dp; ++ register FTSENT *p, *head; ++ register int nitems; ++ FTSENT *cur, *tail; ++ DIR *dirp; ++ void *oldaddr; ++ int cderrno, descend, len, level, nlinks, saved_errno, ++ nostat, doadjust; ++ size_t maxlen; ++ char *cp; ++ ++ /* Set current node pointer. */ ++ cur = sp->fts_cur; ++ ++ /* ++ * Open the directory for reading. If this fails, we're done. ++ * If being called from fts_read, set the fts_info field. ++ */ ++#if defined FTS_WHITEOUT && 0 ++ if (ISSET(FTS_WHITEOUT)) ++ oflag = DTF_NODUP|DTF_REWIND; ++ else ++ oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND; ++#else ++# define opendir2(path, flag) opendir(path) ++#endif ++ if ((dirp = opendir2(cur->fts_accpath, oflag)) == NULL) { ++ if (type == BREAD) { ++ cur->fts_info = FTS_DNR; ++ cur->fts_errno = errno; ++ } ++ return (NULL); ++ } ++ ++ /* ++ * Nlinks is the number of possible entries of type directory in the ++ * directory if we're cheating on stat calls, 0 if we're not doing ++ * any stat calls at all, -1 if we're doing stats on everything. ++ */ ++ if (type == BNAMES) { ++ nlinks = 0; ++ /* Be quiet about nostat, GCC. */ ++ nostat = 0; ++ } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) { ++ nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2); ++ nostat = 1; ++ } else { ++ nlinks = -1; ++ nostat = 0; ++ } ++ ++#ifdef notdef ++ (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink); ++ (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n", ++ ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT)); ++#endif ++ /* ++ * If we're going to need to stat anything or we want to descend ++ * and stay in the directory, chdir. If this fails we keep going, ++ * but set a flag so we don't chdir after the post-order visit. ++ * We won't be able to stat anything, but we can still return the ++ * names themselves. Note, that since fts_read won't be able to ++ * chdir into the directory, it will have to return different path ++ * names than before, i.e. "a/b" instead of "b". Since the node ++ * has already been visited in pre-order, have to wait until the ++ * post-order visit to return the error. There is a special case ++ * here, if there was nothing to stat then it's not an error to ++ * not be able to stat. This is all fairly nasty. If a program ++ * needed sorted entries or stat information, they had better be ++ * checking FTS_NS on the returned nodes. ++ */ ++ cderrno = 0; ++ if (nlinks || type == BREAD) { ++ if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { ++ if (nlinks && type == BREAD) ++ cur->fts_errno = errno; ++ cur->fts_flags |= FTS_DONTCHDIR; ++ descend = 0; ++ cderrno = errno; ++ (void)closedir(dirp); ++ dirp = NULL; ++ } else ++ descend = 1; ++ } else ++ descend = 0; ++ ++ /* ++ * Figure out the max file name length that can be stored in the ++ * current path -- the inner loop allocates more path as necessary. ++ * We really wouldn't have to do the maxlen calculations here, we ++ * could do them in fts_read before returning the path, but it's a ++ * lot easier here since the length is part of the dirent structure. ++ * ++ * If not changing directories set a pointer so that can just append ++ * each new name into the path. ++ */ ++ len = NAPPEND(cur); ++ if (ISSET(FTS_NOCHDIR)) { ++ cp = sp->fts_path + len; ++ *cp++ = '/'; ++ } else { ++ /* GCC, you're too verbose. */ ++ cp = NULL; ++ } ++ len++; ++ maxlen = sp->fts_pathlen - len; ++ ++ level = cur->fts_level + 1; ++ ++ /* Read the directory, attaching each entry to the `link' pointer. */ ++ doadjust = 0; ++ for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) { ++ if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) ++ continue; ++ ++ if ((p = fts_alloc(sp, dp->d_name, _D_EXACT_NAMLEN (dp))) == NULL) ++ goto mem1; ++ if (_D_EXACT_NAMLEN (dp) >= maxlen) {/* include space for NUL */ ++ oldaddr = sp->fts_path; ++ if (fts_palloc(sp, _D_EXACT_NAMLEN (dp) + len + 1)) { ++ /* ++ * No more memory for path or structures. Save ++ * errno, free up the current structure and the ++ * structures already allocated. ++ */ ++mem1: saved_errno = errno; ++ free(p); ++ fts_lfree(head); ++ (void)closedir(dirp); ++ cur->fts_info = FTS_ERR; ++ SET(FTS_STOP); ++ errno = saved_errno; ++ return (NULL); ++ } ++ /* Did realloc() change the pointer? */ ++ if (oldaddr != sp->fts_path) { ++ doadjust = 1; ++ if (ISSET(FTS_NOCHDIR)) ++ cp = sp->fts_path + len; ++ } ++ maxlen = sp->fts_pathlen - len; ++ } ++ ++ if (len + _D_EXACT_NAMLEN (dp) >= USHRT_MAX) { ++ /* ++ * In an FTSENT, fts_pathlen is a u_short so it is ++ * possible to wraparound here. If we do, free up ++ * the current structure and the structures already ++ * allocated, then error out with ENAMETOOLONG. ++ */ ++ free(p); ++ fts_lfree(head); ++ (void)closedir(dirp); ++ cur->fts_info = FTS_ERR; ++ SET(FTS_STOP); ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ p->fts_level = level; ++ p->fts_parent = sp->fts_cur; ++ p->fts_pathlen = len + _D_EXACT_NAMLEN (dp); ++ ++#if defined FTS_WHITEOUT && 0 ++ if (dp->d_type == DT_WHT) ++ p->fts_flags |= FTS_ISW; ++#endif ++ ++#if 0 ++ /* Unreachable code. cderrno is only ever set to a nonnull ++ value if dirp is closed at the same time. But then we ++ cannot enter this loop. */ ++ if (cderrno) { ++ if (nlinks) { ++ p->fts_info = FTS_NS; ++ p->fts_errno = cderrno; ++ } else ++ p->fts_info = FTS_NSOK; ++ p->fts_accpath = cur->fts_accpath; ++ } else ++#endif ++ if (nlinks == 0 ++#if defined DT_DIR && defined _DIRENT_HAVE_D_TYPE ++ || (nostat && ++ dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN) ++#endif ++ ) { ++ p->fts_accpath = ++ ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name; ++ p->fts_info = FTS_NSOK; ++ } else { ++ /* Build a file name for fts_stat to stat. */ ++ if (ISSET(FTS_NOCHDIR)) { ++ p->fts_accpath = p->fts_path; ++ memmove(cp, p->fts_name, p->fts_namelen + 1); ++ } else ++ p->fts_accpath = p->fts_name; ++ /* Stat it. */ ++ p->fts_info = fts_stat(sp, p, 0); ++ ++ /* Decrement link count if applicable. */ ++ if (nlinks > 0 && (p->fts_info == FTS_D || ++ p->fts_info == FTS_DC || p->fts_info == FTS_DOT)) ++ --nlinks; ++ } ++ ++ /* We walk in directory order so "ls -f" doesn't get upset. */ ++ p->fts_link = NULL; ++ if (head == NULL) ++ head = tail = p; ++ else { ++ tail->fts_link = p; ++ tail = p; ++ } ++ ++nitems; ++ } ++ if (dirp) ++ (void)closedir(dirp); ++ ++ /* ++ * If realloc() changed the address of the path, adjust the ++ * addresses for the rest of the tree and the dir list. ++ */ ++ if (doadjust) ++ fts_padjust(sp, head); ++ ++ /* ++ * If not changing directories, reset the path back to original ++ * state. ++ */ ++ if (ISSET(FTS_NOCHDIR)) { ++ if (len == sp->fts_pathlen || nitems == 0) ++ --cp; ++ *cp = '\0'; ++ } ++ ++ /* ++ * If descended after called from fts_children or after called from ++ * fts_read and nothing found, get back. At the root level we use ++ * the saved fd; if one of fts_open()'s arguments is a relative path ++ * to an empty directory, we wind up here with no other way back. If ++ * can't get back, we're done. ++ */ ++ if (descend && (type == BCHILD || !nitems) && ++ (cur->fts_level == FTS_ROOTLEVEL ? ++ FCHDIR(sp, sp->fts_rfd) : ++ fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { ++ cur->fts_info = FTS_ERR; ++ SET(FTS_STOP); ++ fts_lfree(head); ++ return (NULL); ++ } ++ ++ /* If didn't find anything, return NULL. */ ++ if (!nitems) { ++ if (type == BREAD) ++ cur->fts_info = FTS_DP; ++ fts_lfree(head); ++ return (NULL); ++ } ++ ++ /* Sort the entries. */ ++ if (sp->fts_compar && nitems > 1) ++ head = fts_sort(sp, head, nitems); ++ return (head); ++} ++ ++static u_short ++fts_stat(FTS *sp, register FTSENT *p, int follow) ++{ ++ register FTSENT *t; ++ register dev_t dev; ++ register ino_t ino; ++ struct stat *sbp, sb; ++ int saved_errno; ++ ++ /* If user needs stat info, stat buffer already allocated. */ ++ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; ++ ++#if defined FTS_WHITEOUT && 0 ++ /* check for whiteout */ ++ if (p->fts_flags & FTS_ISW) { ++ if (sbp != &sb) { ++ memset(sbp, '\0', sizeof (*sbp)); ++ sbp->st_mode = S_IFWHT; ++ } ++ return (FTS_W); ++ } ++#endif ++ ++ /* ++ * If doing a logical walk, or application requested FTS_FOLLOW, do ++ * a stat(2). If that fails, check for a non-existent symlink. If ++ * fail, set the errno from the stat call. ++ */ ++ if (ISSET(FTS_LOGICAL) || follow) { ++ if (stat(p->fts_accpath, sbp)) { ++ saved_errno = errno; ++ if (!lstat(p->fts_accpath, sbp)) { ++ errno = 0; ++ return (FTS_SLNONE); ++ } ++ p->fts_errno = saved_errno; ++ goto err; ++ } ++ } else if (lstat(p->fts_accpath, sbp)) { ++ p->fts_errno = errno; ++err: memset(sbp, 0, sizeof(struct stat)); ++ return (FTS_NS); ++ } ++ ++ if (S_ISDIR(sbp->st_mode)) { ++ /* ++ * Set the device/inode. Used to find cycles and check for ++ * crossing mount points. Also remember the link count, used ++ * in fts_build to limit the number of stat calls. It is ++ * understood that these fields are only referenced if fts_info ++ * is set to FTS_D. ++ */ ++ dev = p->fts_dev = sbp->st_dev; ++ ino = p->fts_ino = sbp->st_ino; ++ p->fts_nlink = sbp->st_nlink; ++ ++ if (ISDOT(p->fts_name)) ++ return (FTS_DOT); ++ ++ /* ++ * Cycle detection is done by brute force when the directory ++ * is first encountered. If the tree gets deep enough or the ++ * number of symbolic links to directories is high enough, ++ * something faster might be worthwhile. ++ */ ++ for (t = p->fts_parent; ++ t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) ++ if (ino == t->fts_ino && dev == t->fts_dev) { ++ p->fts_cycle = t; ++ return (FTS_DC); ++ } ++ return (FTS_D); ++ } ++ if (S_ISLNK(sbp->st_mode)) ++ return (FTS_SL); ++ if (S_ISREG(sbp->st_mode)) ++ return (FTS_F); ++ return (FTS_DEFAULT); ++} ++ ++static FTSENT * ++fts_sort(FTS *sp, FTSENT *head, register int nitems) ++{ ++ register FTSENT **ap, *p; ++ ++ /* ++ * Construct an array of pointers to the structures and call qsort(3). ++ * Reassemble the array in the order returned by qsort. If unable to ++ * sort for memory reasons, return the directory entries in their ++ * current order. Allocate enough space for the current needs plus ++ * 40 so don't realloc one entry at a time. ++ */ ++ if (nitems > sp->fts_nitems) { ++ struct _ftsent **a; ++ ++ sp->fts_nitems = nitems + 40; ++ if ((a = realloc(sp->fts_array, ++ (size_t)(sp->fts_nitems * sizeof(FTSENT *)))) == NULL) { ++ free(sp->fts_array); ++ sp->fts_array = NULL; ++ sp->fts_nitems = 0; ++ return (head); ++ } ++ sp->fts_array = a; ++ } ++ for (ap = sp->fts_array, p = head; p; p = p->fts_link) ++ *ap++ = p; ++ qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar); ++ for (head = *(ap = sp->fts_array); --nitems; ++ap) ++ ap[0]->fts_link = ap[1]; ++ ap[0]->fts_link = NULL; ++ return (head); ++} ++ ++static FTSENT * ++fts_alloc(FTS *sp, const char *name, size_t namelen) ++{ ++ register FTSENT *p; ++ size_t len; ++ ++ /* ++ * The file name is a variable length array and no stat structure is ++ * necessary if the user has set the nostat bit. Allocate the FTSENT ++ * structure, the file name and the stat structure in one chunk, but ++ * be careful that the stat structure is reasonably aligned. Since the ++ * fts_name field is declared to be of size 1, the fts_name pointer is ++ * namelen + 2 before the first possible address of the stat structure. ++ */ ++ len = sizeof(FTSENT) + namelen; ++ if (!ISSET(FTS_NOSTAT)) ++ len += sizeof(struct stat) + ALIGNBYTES; ++ if ((p = malloc(len)) == NULL) ++ return (NULL); ++ ++ /* Copy the name and guarantee NUL termination. */ ++ memmove(p->fts_name, name, namelen); ++ p->fts_name[namelen] = '\0'; ++ ++ if (!ISSET(FTS_NOSTAT)) ++ p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2); ++ p->fts_namelen = namelen; ++ p->fts_path = sp->fts_path; ++ p->fts_errno = 0; ++ p->fts_flags = 0; ++ p->fts_instr = FTS_NOINSTR; ++ p->fts_number = 0; ++ p->fts_pointer = NULL; ++ return (p); ++} ++ ++static void ++fts_lfree(register FTSENT *head) ++{ ++ register FTSENT *p; ++ ++ /* Free a linked list of structures. */ ++ while ((p = head)) { ++ head = head->fts_link; ++ free(p); ++ } ++} ++ ++/* ++ * Allow essentially unlimited paths; find, rm, ls should all work on any tree. ++ * Most systems will allow creation of paths much longer than MAXPATHLEN, even ++ * though the kernel won't resolve them. Add the size (not just what's needed) ++ * plus 256 bytes so don't realloc the path 2 bytes at a time. ++ */ ++static int ++fts_palloc(FTS *sp, size_t more) ++{ ++ char *p; ++ ++ sp->fts_pathlen += more + 256; ++ /* ++ * Check for possible wraparound. In an FTS, fts_pathlen is ++ * a signed int but in an FTSENT it is an unsigned short. ++ * We limit fts_pathlen to USHRT_MAX to be safe in both cases. ++ */ ++ if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) { ++ free(sp->fts_path); ++ sp->fts_path = NULL; ++ errno = ENAMETOOLONG; ++ return (1); ++ } ++ p = realloc(sp->fts_path, sp->fts_pathlen); ++ if (p == NULL) { ++ free(sp->fts_path); ++ sp->fts_path = NULL; ++ return 1; ++ } ++ sp->fts_path = p; ++ return 0; ++} ++ ++/* ++ * When the path is realloc'd, have to fix all of the pointers in structures ++ * already returned. ++ */ ++static void ++fts_padjust(FTS *sp, FTSENT *head) ++{ ++ FTSENT *p; ++ char *addr = sp->fts_path; ++ ++#define ADJUST(p) do { \ ++ if ((p)->fts_accpath != (p)->fts_name) { \ ++ (p)->fts_accpath = \ ++ (char *)addr + ((p)->fts_accpath - (p)->fts_path); \ ++ } \ ++ (p)->fts_path = addr; \ ++} while (0) ++ /* Adjust the current set of children. */ ++ for (p = sp->fts_child; p; p = p->fts_link) ++ ADJUST(p); ++ ++ /* Adjust the rest of the tree, including the current level. */ ++ for (p = head; p->fts_level >= FTS_ROOTLEVEL;) { ++ ADJUST(p); ++ p = p->fts_link ? p->fts_link : p->fts_parent; ++ } ++} ++ ++static size_t ++fts_maxarglen(char * const *argv) ++{ ++ size_t len, max; ++ ++ for (max = 0; *argv; ++argv) ++ if ((len = strlen(*argv)) > max) ++ max = len; ++ return (max + 1); ++} ++ ++/* ++ * Change to dir specified by fd or p->fts_accpath without getting ++ * tricked by someone changing the world out from underneath us. ++ * Assumes p->fts_dev and p->fts_ino are filled in. ++ */ ++static int ++fts_safe_changedir(FTS *sp, FTSENT *p, int fd, const char *path) ++{ ++ int ret, oerrno, newfd; ++ struct stat64 sb; ++ ++ newfd = fd; ++ if (ISSET(FTS_NOCHDIR)) ++ return (0); ++ if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0) ++ return (-1); ++ if (fstat64(newfd, &sb)) { ++ ret = -1; ++ goto bail; ++ } ++ if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) { ++ errno = ENOENT; /* disinformation */ ++ ret = -1; ++ goto bail; ++ } ++ ret = fchdir(newfd); ++bail: ++ oerrno = errno; ++ if (fd < 0) ++ (void)close(newfd); ++ errno = oerrno; ++ return (ret); ++} +diff --git a/libdwfl/fts_.h b/libdwfl/fts_.h +new file mode 100644 +index 000000000000..0a070ba8dce5 +--- /dev/null ++++ b/libdwfl/fts_.h +@@ -0,0 +1,131 @@ ++/* ++ * Copyright (c) 1989, 1993 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 4. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * @(#)fts.h 8.3 (Berkeley) 8/14/94 ++ */ ++ ++#ifndef _FTS_H ++#define _FTS_H 1 ++ ++#include ++#include ++ ++/* The fts interface is incompatible with the LFS interface which ++ transparently uses the 64-bit file access functions. */ ++#ifdef __USE_FILE_OFFSET64 ++# error " cannot be used with -D_FILE_OFFSET_BITS==64" ++#endif ++ ++ ++typedef struct { ++ struct _ftsent *fts_cur; /* current node */ ++ struct _ftsent *fts_child; /* linked list of children */ ++ struct _ftsent **fts_array; /* sort array */ ++ dev_t fts_dev; /* starting device # */ ++ char *fts_path; /* path for this descent */ ++ int fts_rfd; /* fd for root */ ++ int fts_pathlen; /* sizeof(path) */ ++ int fts_nitems; /* elements in the sort array */ ++ int (*fts_compar) (const void *, const void *); /* compare fn */ ++ ++#define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */ ++#define FTS_LOGICAL 0x0002 /* logical walk */ ++#define FTS_NOCHDIR 0x0004 /* don't change directories */ ++#define FTS_NOSTAT 0x0008 /* don't get stat info */ ++#define FTS_PHYSICAL 0x0010 /* physical walk */ ++#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ ++#define FTS_XDEV 0x0040 /* don't cross devices */ ++#define FTS_WHITEOUT 0x0080 /* return whiteout information */ ++#define FTS_OPTIONMASK 0x00ff /* valid user option mask */ ++ ++#define FTS_NAMEONLY 0x0100 /* (private) child names only */ ++#define FTS_STOP 0x0200 /* (private) unrecoverable error */ ++ int fts_options; /* fts_open options, global flags */ ++} FTS; ++ ++typedef struct _ftsent { ++ struct _ftsent *fts_cycle; /* cycle node */ ++ struct _ftsent *fts_parent; /* parent directory */ ++ struct _ftsent *fts_link; /* next file in directory */ ++ long fts_number; /* local numeric value */ ++ void *fts_pointer; /* local address value */ ++ char *fts_accpath; /* access path */ ++ char *fts_path; /* root path */ ++ int fts_errno; /* errno for this node */ ++ int fts_symfd; /* fd for symlink */ ++ u_short fts_pathlen; /* strlen(fts_path) */ ++ u_short fts_namelen; /* strlen(fts_name) */ ++ ++ ino_t fts_ino; /* inode */ ++ dev_t fts_dev; /* device */ ++ nlink_t fts_nlink; /* link count */ ++ ++#define FTS_ROOTPARENTLEVEL -1 ++#define FTS_ROOTLEVEL 0 ++ short fts_level; /* depth (-1 to N) */ ++ ++#define FTS_D 1 /* preorder directory */ ++#define FTS_DC 2 /* directory that causes cycles */ ++#define FTS_DEFAULT 3 /* none of the above */ ++#define FTS_DNR 4 /* unreadable directory */ ++#define FTS_DOT 5 /* dot or dot-dot */ ++#define FTS_DP 6 /* postorder directory */ ++#define FTS_ERR 7 /* error; errno is set */ ++#define FTS_F 8 /* regular file */ ++#define FTS_INIT 9 /* initialized only */ ++#define FTS_NS 10 /* stat(2) failed */ ++#define FTS_NSOK 11 /* no stat(2) requested */ ++#define FTS_SL 12 /* symbolic link */ ++#define FTS_SLNONE 13 /* symbolic link without target */ ++#define FTS_W 14 /* whiteout object */ ++ u_short fts_info; /* user flags for FTSENT structure */ ++ ++#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ ++#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ ++ u_short fts_flags; /* private flags for FTSENT structure */ ++ ++#define FTS_AGAIN 1 /* read node again */ ++#define FTS_FOLLOW 2 /* follow symbolic link */ ++#define FTS_NOINSTR 3 /* no instructions */ ++#define FTS_SKIP 4 /* discard node */ ++ u_short fts_instr; /* fts_set() instructions */ ++ ++ struct stat *fts_statp; /* stat(2) information */ ++ char fts_name[1]; /* file name */ ++} FTSENT; ++ ++__BEGIN_DECLS ++FTSENT *fts_children (FTS *, int); ++int fts_close (FTS *); ++FTS *fts_open (char * const *, int, ++ int (*)(const FTSENT **, const FTSENT **)); ++FTSENT *fts_read (FTS *); ++int fts_set (FTS *, FTSENT *, int) __THROW; ++__END_DECLS ++ ++#endif /* fts.h */ +diff --git a/libdwfl/linux-kernel-modules.c b/libdwfl/linux-kernel-modules.c +index 9d0fef2cf260..47f0e3892294 100644 +--- a/libdwfl/linux-kernel-modules.c ++++ b/libdwfl/linux-kernel-modules.c +@@ -31,10 +31,14 @@ + Everything we need here is fine if its declarations just come first. + Also, include sys/types.h before fts. On some systems fts.h is not self + contained. */ ++#ifdef HAVE_FTS_H + #ifdef BAD_FTS + #include + #include + #endif ++#else ++#include ++#endif + + #include + #include +-- +2.11.0 + diff --git a/package/elfutils/0002-disable-progs.patch b/package/elfutils/0002-disable-progs.patch deleted file mode 100644 index 3f80fe60df..0000000000 --- a/package/elfutils/0002-disable-progs.patch +++ /dev/null @@ -1,62 +0,0 @@ -From dfea82b761b2ea4708fbf9370a5467ae4be525ca Mon Sep 17 00:00:00 2001 -From: Thomas Petazzoni -Date: Mon, 29 May 2017 23:03:48 +0300 -Subject: [PATCH] Add a --{enable,disable}-progs configure option - -Add a --{enable,disable}-progs configuration option to elfutils. This -allows to selectively disable the compilation of the elfutils programs -(in which case only the libraries are built and installed). This is -useful because the programs are often not needed, and also because -building the programs against uClibc causes several issues (lack of -obstack_printf() in uClibc for example). - -Based on the former patch by Thomas Petazzoni. - -[Vincent: tweak patch for 0.166] - -Signed-off-by: Thomas Petazzoni -Signed-off-by: Vicente Olivert Riera ---- - Makefile.am | 6 +++++- - configure.ac | 6 ++++++ - 2 files changed, 11 insertions(+), 1 deletion(-) - -diff --git a/Makefile.am b/Makefile.am -index 2ff444e7bf1d..70443abb4fb6 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -26,9 +26,13 @@ AM_MAKEFLAGS = --no-print-directory - - pkginclude_HEADERS = version.h - -+if ENABLE_PROGS -+PROGS_SUBDIR = src -+endif -+ - # Add doc back when we have some real content. - SUBDIRS = config m4 lib libelf libebl libdwelf libdwfl libdw libcpu libasm \ -- backends src po tests -+ backends $(PROGS_SUBDIR) po tests - - EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING \ - COPYING COPYING-GPLV2 COPYING-LGPLV3 -diff --git a/configure.ac b/configure.ac -index c2c1d90b2133..7b4c38381cca 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -259,6 +259,12 @@ AC_SUBST([LIBEBL_SUBDIR]) - AC_DEFINE_UNQUOTED(LIBEBL_SUBDIR, "$LIBEBL_SUBDIR") - AH_TEMPLATE([LIBEBL_SUBDIR], [$libdir subdirectory containing libebl modules.]) - -+AC_ARG_ENABLE([progs], -+ AS_HELP_STRING([--enable-progs], [enable progs]), -+ enable_progs=$enableval, -+ enable_progs=yes) -+AM_CONDITIONAL(ENABLE_PROGS, test "$enable_progs" = yes) -+ - dnl zlib is mandatory. - save_LIBS="$LIBS" - LIBS= --- -2.11.0 - diff --git a/package/elfutils/0003-Really-make-Werror-conditional-to-BUILD_WERROR.patch b/package/elfutils/0003-Really-make-Werror-conditional-to-BUILD_WERROR.patch new file mode 100644 index 0000000000..21ffa7f31b --- /dev/null +++ b/package/elfutils/0003-Really-make-Werror-conditional-to-BUILD_WERROR.patch @@ -0,0 +1,36 @@ +From 2688a0238eaf825d6659c16c012db0c16f07e197 Mon Sep 17 00:00:00 2001 +From: Vicente Olivert Riera +Date: Mon, 29 May 2017 23:24:42 +0300 +Subject: [PATCH] Really make -Werror conditional to BUILD_WERROR + +Otherwise it will fail with an error message like this one: + +elf_getarsym.c:290:9: error: 'n' may be used uninitialized in this +function [-Werror=maybe-uninitialized] + arsym[n].as_name = NULL; + ^ +cc1: all warnings being treated as errors + +[Vincent: tweak patch for 0.166] + +Signed-off-by: "Yann E. MORIN" +Signed-off-by: Vicente Olivert Riera +--- + config/eu.am | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/config/eu.am b/config/eu.am +index c2cc349ce876..99b368e09060 100644 +--- a/config/eu.am ++++ b/config/eu.am +@@ -73,7 +73,6 @@ AM_CFLAGS = -std=gnu99 -Wall -Wshadow -Wformat=2 \ + -Wold-style-definition -Wstrict-prototypes \ + $(LOGICAL_OP_WARNING) $(DUPLICATED_COND_WARNING) \ + $(NULL_DEREFERENCE_WARNING) $(IMPLICIT_FALLTHROUGH_WARNING) \ +- $(if $($(*F)_no_Werror),,-Werror) \ + $(if $($(*F)_no_Wunused),,-Wunused -Wextra) \ + $(if $($(*F)_no_Wstack_usage),,$(STACK_USAGE_WARNING)) \ + $(if $($(*F)_no_Wpacked_not_aligned),-Wno-packed-not-aligned,) \ +-- +2.17.1 + diff --git a/package/elfutils/0003-fts.patch b/package/elfutils/0003-fts.patch deleted file mode 100644 index cf5ba25c82..0000000000 --- a/package/elfutils/0003-fts.patch +++ /dev/null @@ -1,1332 +0,0 @@ -From 098760f7eac1fb86b3f6871d5bb10f9f44468f2d Mon Sep 17 00:00:00 2001 -From: Thomas Petazzoni -Date: Mon, 29 May 2017 23:08:05 +0300 -Subject: [PATCH] Add an implementation of the fts_*() functions - -The fts_*() functions are optional in uClibc, and not compiled in our -default configuration. The best option would be to migrate this -elfutils code to the nftw family of functions, but it requires quite -some work. - -So we have several options here: - - *) Enable fts_*() functions in our default uClibc configuration. Not - nice since only one package needs them (the help text of uClibc - for fts_*() functions explicitly mention that they have been added - to be able to build elfutils). - - *) Use gnulib, but it is quite heavy to setup, requires modifications - to configure.ac, and other things. - - *) Copy the fts function from uClibc into elfutils source code. This - is the solution used below. uClibc is LGPL, and elfutils is - LGPL/GPL, so there should not be any licensing issue. - -Of course, the fts_*() functions are only built if they are not -already provided by the C library. - -Based on the former patch by Thomas Petazzoni. - -[Vincent: tweak patch for 0.166] - -Signed-off-by: Thomas Petazzoni -Signed-off-by: Vicente Olivert Riera ---- - configure.ac | 4 + - libdwfl/Makefile.am | 3 + - libdwfl/fts.c | 1095 ++++++++++++++++++++++++++++++++++++++++ - libdwfl/fts_.h | 131 +++++ - libdwfl/linux-kernel-modules.c | 4 + - 5 files changed, 1237 insertions(+) - create mode 100644 libdwfl/fts.c - create mode 100644 libdwfl/fts_.h - -diff --git a/configure.ac b/configure.ac -index 7b4c38381cca..bcebb05fa532 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -265,6 +265,10 @@ AC_ARG_ENABLE([progs], - enable_progs=yes) - AM_CONDITIONAL(ENABLE_PROGS, test "$enable_progs" = yes) - -+AC_CHECK_HEADER([fts.h], -+ AC_DEFINE([HAVE_FTS_H], [], [Define if is available in C library])) -+AM_CONDITIONAL(HAVE_FTS, test "$ac_cv_header_fts_h" = yes) -+ - dnl zlib is mandatory. - save_LIBS="$LIBS" - LIBS= -diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am -index 89ca92ed8110..a5a5615c5f94 100644 ---- a/libdwfl/Makefile.am -+++ b/libdwfl/Makefile.am -@@ -77,6 +77,9 @@ endif - if LZMA - libdwfl_a_SOURCES += lzma.c - endif -+if !HAVE_FTS -+libdwfl_a_SOURCES += fts.c -+endif - - libdwfl = $(libdw) - libdw = ../libdw/libdw.so -diff --git a/libdwfl/fts.c b/libdwfl/fts.c -new file mode 100644 -index 000000000000..f34cc03bd963 ---- /dev/null -+++ b/libdwfl/fts.c -@@ -0,0 +1,1095 @@ -+/*- -+ * Copyright (c) 1990, 1993, 1994 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 4. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "fts_.h" -+#include -+#include -+#include -+ -+/* Largest alignment size needed, minus one. -+ Usually long double is the worst case. */ -+#ifndef ALIGNBYTES -+#define ALIGNBYTES (__alignof__ (long double) - 1) -+#endif -+/* Align P to that size. */ -+#ifndef ALIGN -+#define ALIGN(p) (((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES) -+#endif -+ -+ -+static FTSENT *fts_alloc (FTS *, const char *, size_t); -+static FTSENT *fts_build (FTS *, int); -+static void fts_lfree (FTSENT *); -+static void fts_load (FTS *, FTSENT *); -+static size_t fts_maxarglen (char * const *); -+static void fts_padjust (FTS *, FTSENT *); -+static int fts_palloc (FTS *, size_t); -+static FTSENT *fts_sort (FTS *, FTSENT *, int); -+static u_short fts_stat (FTS *, FTSENT *, int); -+static int fts_safe_changedir (FTS *, FTSENT *, int, const char *); -+ -+#ifndef MAX -+#define MAX(a, b) ({ __typeof__ (a) _a = (a); \ -+ __typeof__ (b) _b = (b); \ -+ _a > _b ? _a : _b; }) -+#endif -+ -+#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) -+ -+#define CLR(opt) (sp->fts_options &= ~(opt)) -+#define ISSET(opt) (sp->fts_options & (opt)) -+#define SET(opt) (sp->fts_options |= (opt)) -+ -+#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) -+ -+/* fts_build flags */ -+#define BCHILD 1 /* fts_children */ -+#define BNAMES 2 /* fts_children, names only */ -+#define BREAD 3 /* fts_read */ -+ -+FTS * -+fts_open( char * const *argv, register int options, -+ int (*compar) (const FTSENT **, const FTSENT **)) -+{ -+ register FTS *sp; -+ register FTSENT *p, *root; -+ register int nitems; -+ FTSENT *parent = NULL; -+ FTSENT *tmp = NULL; -+ -+ /* Options check. */ -+ if (options & ~FTS_OPTIONMASK) { -+ errno = EINVAL; -+ return (NULL); -+ } -+ -+ /* Allocate/initialize the stream */ -+ if ((sp = malloc((u_int)sizeof(FTS))) == NULL) -+ return (NULL); -+ memset(sp, 0, sizeof(FTS)); -+ sp->fts_compar = (int (*) (const void *, const void *)) compar; -+ sp->fts_options = options; -+ -+ /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ -+ if (ISSET(FTS_LOGICAL)) -+ SET(FTS_NOCHDIR); -+ -+ /* -+ * Start out with 1K of path space, and enough, in any case, -+ * to hold the user's paths. -+ */ -+#ifndef MAXPATHLEN -+#define MAXPATHLEN 1024 -+#endif -+ size_t maxarglen = fts_maxarglen(argv); -+ if (fts_palloc(sp, MAX(maxarglen, MAXPATHLEN))) -+ goto mem1; -+ -+ /* Allocate/initialize root's parent. */ -+ if (*argv != NULL) { -+ if ((parent = fts_alloc(sp, "", 0)) == NULL) -+ goto mem2; -+ parent->fts_level = FTS_ROOTPARENTLEVEL; -+ } -+ -+ /* Allocate/initialize root(s). */ -+ for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) { -+ /* Don't allow zero-length paths. */ -+ size_t len = strlen(*argv); -+ if (len == 0) { -+ errno = ENOENT; -+ goto mem3; -+ } -+ -+ p = fts_alloc(sp, *argv, len); -+ p->fts_level = FTS_ROOTLEVEL; -+ p->fts_parent = parent; -+ p->fts_accpath = p->fts_name; -+ p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW)); -+ -+ /* Command-line "." and ".." are real directories. */ -+ if (p->fts_info == FTS_DOT) -+ p->fts_info = FTS_D; -+ -+ /* -+ * If comparison routine supplied, traverse in sorted -+ * order; otherwise traverse in the order specified. -+ */ -+ if (compar) { -+ p->fts_link = root; -+ root = p; -+ } else { -+ p->fts_link = NULL; -+ if (root == NULL) -+ tmp = root = p; -+ else { -+ tmp->fts_link = p; -+ tmp = p; -+ } -+ } -+ } -+ if (compar && nitems > 1) -+ root = fts_sort(sp, root, nitems); -+ -+ /* -+ * Allocate a dummy pointer and make fts_read think that we've just -+ * finished the node before the root(s); set p->fts_info to FTS_INIT -+ * so that everything about the "current" node is ignored. -+ */ -+ if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL) -+ goto mem3; -+ sp->fts_cur->fts_link = root; -+ sp->fts_cur->fts_info = FTS_INIT; -+ -+ /* -+ * If using chdir(2), grab a file descriptor pointing to dot to ensure -+ * that we can get back here; this could be avoided for some paths, -+ * but almost certainly not worth the effort. Slashes, symbolic links, -+ * and ".." are all fairly nasty problems. Note, if we can't get the -+ * descriptor we run anyway, just more slowly. -+ */ -+ if (!ISSET(FTS_NOCHDIR) -+ && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0) -+ SET(FTS_NOCHDIR); -+ -+ return (sp); -+ -+mem3: fts_lfree(root); -+ free(parent); -+mem2: free(sp->fts_path); -+mem1: free(sp); -+ return (NULL); -+} -+ -+static void -+fts_load(FTS *sp, register FTSENT *p) -+{ -+ register int len; -+ register char *cp; -+ -+ /* -+ * Load the stream structure for the next traversal. Since we don't -+ * actually enter the directory until after the preorder visit, set -+ * the fts_accpath field specially so the chdir gets done to the right -+ * place and the user can access the first node. From fts_open it's -+ * known that the path will fit. -+ */ -+ len = p->fts_pathlen = p->fts_namelen; -+ memmove(sp->fts_path, p->fts_name, len + 1); -+ if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) { -+ len = strlen(++cp); -+ memmove(p->fts_name, cp, len + 1); -+ p->fts_namelen = len; -+ } -+ p->fts_accpath = p->fts_path = sp->fts_path; -+ sp->fts_dev = p->fts_dev; -+} -+ -+int -+fts_close(FTS *sp) -+{ -+ register FTSENT *freep, *p; -+ int saved_errno; -+ -+ /* -+ * This still works if we haven't read anything -- the dummy structure -+ * points to the root list, so we step through to the end of the root -+ * list which has a valid parent pointer. -+ */ -+ if (sp->fts_cur) { -+ for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) { -+ freep = p; -+ p = p->fts_link != NULL ? p->fts_link : p->fts_parent; -+ free(freep); -+ } -+ free(p); -+ } -+ -+ /* Free up child linked list, sort array, path buffer. */ -+ if (sp->fts_child) -+ fts_lfree(sp->fts_child); -+ free(sp->fts_array); -+ free(sp->fts_path); -+ -+ /* Return to original directory, save errno if necessary. */ -+ if (!ISSET(FTS_NOCHDIR)) { -+ saved_errno = fchdir(sp->fts_rfd) ? errno : 0; -+ (void)close(sp->fts_rfd); -+ -+ /* Set errno and return. */ -+ if (saved_errno != 0) { -+ /* Free up the stream pointer. */ -+ free(sp); -+ errno = saved_errno; -+ return (-1); -+ } -+ } -+ -+ /* Free up the stream pointer. */ -+ free(sp); -+ return (0); -+} -+ -+/* -+ * Special case of "/" at the end of the path so that slashes aren't -+ * appended which would cause paths to be written as "....//foo". -+ */ -+#define NAPPEND(p) \ -+ (p->fts_path[p->fts_pathlen - 1] == '/' \ -+ ? p->fts_pathlen - 1 : p->fts_pathlen) -+ -+FTSENT * -+fts_read(register FTS *sp) -+{ -+ register FTSENT *p, *tmp; -+ register int instr; -+ register char *t; -+ int saved_errno; -+ -+ /* If finished or unrecoverable error, return NULL. */ -+ if (sp->fts_cur == NULL || ISSET(FTS_STOP)) -+ return (NULL); -+ -+ /* Set current node pointer. */ -+ p = sp->fts_cur; -+ -+ /* Save and zero out user instructions. */ -+ instr = p->fts_instr; -+ p->fts_instr = FTS_NOINSTR; -+ -+ /* Any type of file may be re-visited; re-stat and re-turn. */ -+ if (instr == FTS_AGAIN) { -+ p->fts_info = fts_stat(sp, p, 0); -+ return (p); -+ } -+ -+ /* -+ * Following a symlink -- SLNONE test allows application to see -+ * SLNONE and recover. If indirecting through a symlink, have -+ * keep a pointer to current location. If unable to get that -+ * pointer, follow fails. -+ */ -+ if (instr == FTS_FOLLOW && -+ (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { -+ p->fts_info = fts_stat(sp, p, 1); -+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { -+ if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) { -+ p->fts_errno = errno; -+ p->fts_info = FTS_ERR; -+ } else -+ p->fts_flags |= FTS_SYMFOLLOW; -+ } -+ return (p); -+ } -+ -+ /* Directory in pre-order. */ -+ if (p->fts_info == FTS_D) { -+ /* If skipped or crossed mount point, do post-order visit. */ -+ if (instr == FTS_SKIP || -+ (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) { -+ if (p->fts_flags & FTS_SYMFOLLOW) -+ (void)close(p->fts_symfd); -+ if (sp->fts_child) { -+ fts_lfree(sp->fts_child); -+ sp->fts_child = NULL; -+ } -+ p->fts_info = FTS_DP; -+ return (p); -+ } -+ -+ /* Rebuild if only read the names and now traversing. */ -+ if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) { -+ CLR(FTS_NAMEONLY); -+ fts_lfree(sp->fts_child); -+ sp->fts_child = NULL; -+ } -+ -+ /* -+ * Cd to the subdirectory. -+ * -+ * If have already read and now fail to chdir, whack the list -+ * to make the names come out right, and set the parent errno -+ * so the application will eventually get an error condition. -+ * Set the FTS_DONTCHDIR flag so that when we logically change -+ * directories back to the parent we don't do a chdir. -+ * -+ * If haven't read do so. If the read fails, fts_build sets -+ * FTS_STOP or the fts_info field of the node. -+ */ -+ if (sp->fts_child != NULL) { -+ if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { -+ p->fts_errno = errno; -+ p->fts_flags |= FTS_DONTCHDIR; -+ for (p = sp->fts_child; p != NULL; -+ p = p->fts_link) -+ p->fts_accpath = -+ p->fts_parent->fts_accpath; -+ } -+ } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) { -+ if (ISSET(FTS_STOP)) -+ return (NULL); -+ return (p); -+ } -+ p = sp->fts_child; -+ sp->fts_child = NULL; -+ sp->fts_cur = p; -+ goto name; -+ } -+ -+ /* Move to the next node on this level. */ -+next: tmp = p; -+ if ((p = p->fts_link) != NULL) { -+ sp->fts_cur = p; -+ free(tmp); -+ -+ /* -+ * If reached the top, return to the original directory (or -+ * the root of the tree), and load the paths for the next root. -+ */ -+ if (p->fts_level == FTS_ROOTLEVEL) { -+ if (FCHDIR(sp, sp->fts_rfd)) { -+ SET(FTS_STOP); -+ return (NULL); -+ } -+ fts_load(sp, p); -+ return p; -+ } -+ -+ /* -+ * User may have called fts_set on the node. If skipped, -+ * ignore. If followed, get a file descriptor so we can -+ * get back if necessary. -+ */ -+ if (p->fts_instr == FTS_SKIP) -+ goto next; -+ if (p->fts_instr == FTS_FOLLOW) { -+ p->fts_info = fts_stat(sp, p, 1); -+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { -+ if ((p->fts_symfd = -+ open(".", O_RDONLY, 0)) < 0) { -+ p->fts_errno = errno; -+ p->fts_info = FTS_ERR; -+ } else -+ p->fts_flags |= FTS_SYMFOLLOW; -+ } -+ p->fts_instr = FTS_NOINSTR; -+ } -+ -+name: t = sp->fts_path + NAPPEND(p->fts_parent); -+ *t++ = '/'; -+ memmove(t, p->fts_name, p->fts_namelen + 1); -+ return p; -+ } -+ -+ /* Move up to the parent node. */ -+ p = tmp->fts_parent; -+ sp->fts_cur = p; -+ free(tmp); -+ -+ if (p->fts_level == FTS_ROOTPARENTLEVEL) { -+ /* -+ * Done; free everything up and set errno to 0 so the user -+ * can distinguish between error and EOF. -+ */ -+ free(p); -+ errno = 0; -+ return (sp->fts_cur = NULL); -+ } -+ -+ /* NUL terminate the pathname. */ -+ sp->fts_path[p->fts_pathlen] = '\0'; -+ -+ /* -+ * Return to the parent directory. If at a root node or came through -+ * a symlink, go back through the file descriptor. Otherwise, cd up -+ * one directory. -+ */ -+ if (p->fts_level == FTS_ROOTLEVEL) { -+ if (FCHDIR(sp, sp->fts_rfd)) { -+ SET(FTS_STOP); -+ return (NULL); -+ } -+ } else if (p->fts_flags & FTS_SYMFOLLOW) { -+ if (FCHDIR(sp, p->fts_symfd)) { -+ saved_errno = errno; -+ (void)close(p->fts_symfd); -+ errno = saved_errno; -+ SET(FTS_STOP); -+ return (NULL); -+ } -+ (void)close(p->fts_symfd); -+ } else if (!(p->fts_flags & FTS_DONTCHDIR) && -+ fts_safe_changedir(sp, p->fts_parent, -1, "..")) { -+ SET(FTS_STOP); -+ return (NULL); -+ } -+ p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; -+ return p; -+} -+ -+/* -+ * Fts_set takes the stream as an argument although it's not used in this -+ * implementation; it would be necessary if anyone wanted to add global -+ * semantics to fts using fts_set. An error return is allowed for similar -+ * reasons. -+ */ -+/* ARGSUSED */ -+int -+fts_set(FTS *sp, FTSENT *p, int instr) -+{ -+ if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW && -+ instr != FTS_NOINSTR && instr != FTS_SKIP) { -+ errno = EINVAL; -+ return (1); -+ } -+ p->fts_instr = instr; -+ return (0); -+} -+ -+FTSENT * -+fts_children(register FTS *sp, int instr) -+{ -+ register FTSENT *p; -+ int fd; -+ -+ if (instr != 0 && instr != FTS_NAMEONLY) { -+ errno = EINVAL; -+ return (NULL); -+ } -+ -+ /* Set current node pointer. */ -+ p = sp->fts_cur; -+ -+ /* -+ * Errno set to 0 so user can distinguish empty directory from -+ * an error. -+ */ -+ errno = 0; -+ -+ /* Fatal errors stop here. */ -+ if (ISSET(FTS_STOP)) -+ return (NULL); -+ -+ /* Return logical hierarchy of user's arguments. */ -+ if (p->fts_info == FTS_INIT) -+ return (p->fts_link); -+ -+ /* -+ * If not a directory being visited in pre-order, stop here. Could -+ * allow FTS_DNR, assuming the user has fixed the problem, but the -+ * same effect is available with FTS_AGAIN. -+ */ -+ if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */) -+ return (NULL); -+ -+ /* Free up any previous child list. */ -+ if (sp->fts_child != NULL) -+ fts_lfree(sp->fts_child); -+ -+ if (instr == FTS_NAMEONLY) { -+ SET(FTS_NAMEONLY); -+ instr = BNAMES; -+ } else -+ instr = BCHILD; -+ -+ /* -+ * If using chdir on a relative path and called BEFORE fts_read does -+ * its chdir to the root of a traversal, we can lose -- we need to -+ * chdir into the subdirectory, and we don't know where the current -+ * directory is, so we can't get back so that the upcoming chdir by -+ * fts_read will work. -+ */ -+ if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' || -+ ISSET(FTS_NOCHDIR)) -+ return (sp->fts_child = fts_build(sp, instr)); -+ -+ if ((fd = open(".", O_RDONLY, 0)) < 0) -+ return (NULL); -+ sp->fts_child = fts_build(sp, instr); -+ if (fchdir(fd)) -+ return (NULL); -+ (void)close(fd); -+ return (sp->fts_child); -+} -+ -+/* -+ * This is the tricky part -- do not casually change *anything* in here. The -+ * idea is to build the linked list of entries that are used by fts_children -+ * and fts_read. There are lots of special cases. -+ * -+ * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is -+ * set and it's a physical walk (so that symbolic links can't be directories), -+ * we can do things quickly. First, if it's a 4.4BSD file system, the type -+ * of the file is in the directory entry. Otherwise, we assume that the number -+ * of subdirectories in a node is equal to the number of links to the parent. -+ * The former skips all stat calls. The latter skips stat calls in any leaf -+ * directories and for any files after the subdirectories in the directory have -+ * been found, cutting the stat calls by about 2/3. -+ */ -+static FTSENT * -+fts_build(register FTS *sp, int type) -+{ -+ register struct dirent *dp; -+ register FTSENT *p, *head; -+ register int nitems; -+ FTSENT *cur, *tail; -+ DIR *dirp; -+ void *oldaddr; -+ int cderrno, descend, len, level, nlinks, saved_errno, -+ nostat, doadjust; -+ size_t maxlen; -+ char *cp; -+ -+ /* Set current node pointer. */ -+ cur = sp->fts_cur; -+ -+ /* -+ * Open the directory for reading. If this fails, we're done. -+ * If being called from fts_read, set the fts_info field. -+ */ -+#if defined FTS_WHITEOUT && 0 -+ if (ISSET(FTS_WHITEOUT)) -+ oflag = DTF_NODUP|DTF_REWIND; -+ else -+ oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND; -+#else -+# define opendir2(path, flag) opendir(path) -+#endif -+ if ((dirp = opendir2(cur->fts_accpath, oflag)) == NULL) { -+ if (type == BREAD) { -+ cur->fts_info = FTS_DNR; -+ cur->fts_errno = errno; -+ } -+ return (NULL); -+ } -+ -+ /* -+ * Nlinks is the number of possible entries of type directory in the -+ * directory if we're cheating on stat calls, 0 if we're not doing -+ * any stat calls at all, -1 if we're doing stats on everything. -+ */ -+ if (type == BNAMES) { -+ nlinks = 0; -+ /* Be quiet about nostat, GCC. */ -+ nostat = 0; -+ } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) { -+ nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2); -+ nostat = 1; -+ } else { -+ nlinks = -1; -+ nostat = 0; -+ } -+ -+#ifdef notdef -+ (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink); -+ (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n", -+ ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT)); -+#endif -+ /* -+ * If we're going to need to stat anything or we want to descend -+ * and stay in the directory, chdir. If this fails we keep going, -+ * but set a flag so we don't chdir after the post-order visit. -+ * We won't be able to stat anything, but we can still return the -+ * names themselves. Note, that since fts_read won't be able to -+ * chdir into the directory, it will have to return different path -+ * names than before, i.e. "a/b" instead of "b". Since the node -+ * has already been visited in pre-order, have to wait until the -+ * post-order visit to return the error. There is a special case -+ * here, if there was nothing to stat then it's not an error to -+ * not be able to stat. This is all fairly nasty. If a program -+ * needed sorted entries or stat information, they had better be -+ * checking FTS_NS on the returned nodes. -+ */ -+ cderrno = 0; -+ if (nlinks || type == BREAD) { -+ if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { -+ if (nlinks && type == BREAD) -+ cur->fts_errno = errno; -+ cur->fts_flags |= FTS_DONTCHDIR; -+ descend = 0; -+ cderrno = errno; -+ (void)closedir(dirp); -+ dirp = NULL; -+ } else -+ descend = 1; -+ } else -+ descend = 0; -+ -+ /* -+ * Figure out the max file name length that can be stored in the -+ * current path -- the inner loop allocates more path as necessary. -+ * We really wouldn't have to do the maxlen calculations here, we -+ * could do them in fts_read before returning the path, but it's a -+ * lot easier here since the length is part of the dirent structure. -+ * -+ * If not changing directories set a pointer so that can just append -+ * each new name into the path. -+ */ -+ len = NAPPEND(cur); -+ if (ISSET(FTS_NOCHDIR)) { -+ cp = sp->fts_path + len; -+ *cp++ = '/'; -+ } else { -+ /* GCC, you're too verbose. */ -+ cp = NULL; -+ } -+ len++; -+ maxlen = sp->fts_pathlen - len; -+ -+ level = cur->fts_level + 1; -+ -+ /* Read the directory, attaching each entry to the `link' pointer. */ -+ doadjust = 0; -+ for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) { -+ if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) -+ continue; -+ -+ if ((p = fts_alloc(sp, dp->d_name, _D_EXACT_NAMLEN (dp))) == NULL) -+ goto mem1; -+ if (_D_EXACT_NAMLEN (dp) >= maxlen) {/* include space for NUL */ -+ oldaddr = sp->fts_path; -+ if (fts_palloc(sp, _D_EXACT_NAMLEN (dp) + len + 1)) { -+ /* -+ * No more memory for path or structures. Save -+ * errno, free up the current structure and the -+ * structures already allocated. -+ */ -+mem1: saved_errno = errno; -+ free(p); -+ fts_lfree(head); -+ (void)closedir(dirp); -+ cur->fts_info = FTS_ERR; -+ SET(FTS_STOP); -+ errno = saved_errno; -+ return (NULL); -+ } -+ /* Did realloc() change the pointer? */ -+ if (oldaddr != sp->fts_path) { -+ doadjust = 1; -+ if (ISSET(FTS_NOCHDIR)) -+ cp = sp->fts_path + len; -+ } -+ maxlen = sp->fts_pathlen - len; -+ } -+ -+ if (len + _D_EXACT_NAMLEN (dp) >= USHRT_MAX) { -+ /* -+ * In an FTSENT, fts_pathlen is a u_short so it is -+ * possible to wraparound here. If we do, free up -+ * the current structure and the structures already -+ * allocated, then error out with ENAMETOOLONG. -+ */ -+ free(p); -+ fts_lfree(head); -+ (void)closedir(dirp); -+ cur->fts_info = FTS_ERR; -+ SET(FTS_STOP); -+ errno = ENAMETOOLONG; -+ return (NULL); -+ } -+ p->fts_level = level; -+ p->fts_parent = sp->fts_cur; -+ p->fts_pathlen = len + _D_EXACT_NAMLEN (dp); -+ -+#if defined FTS_WHITEOUT && 0 -+ if (dp->d_type == DT_WHT) -+ p->fts_flags |= FTS_ISW; -+#endif -+ -+#if 0 -+ /* Unreachable code. cderrno is only ever set to a nonnull -+ value if dirp is closed at the same time. But then we -+ cannot enter this loop. */ -+ if (cderrno) { -+ if (nlinks) { -+ p->fts_info = FTS_NS; -+ p->fts_errno = cderrno; -+ } else -+ p->fts_info = FTS_NSOK; -+ p->fts_accpath = cur->fts_accpath; -+ } else -+#endif -+ if (nlinks == 0 -+#if defined DT_DIR && defined _DIRENT_HAVE_D_TYPE -+ || (nostat && -+ dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN) -+#endif -+ ) { -+ p->fts_accpath = -+ ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name; -+ p->fts_info = FTS_NSOK; -+ } else { -+ /* Build a file name for fts_stat to stat. */ -+ if (ISSET(FTS_NOCHDIR)) { -+ p->fts_accpath = p->fts_path; -+ memmove(cp, p->fts_name, p->fts_namelen + 1); -+ } else -+ p->fts_accpath = p->fts_name; -+ /* Stat it. */ -+ p->fts_info = fts_stat(sp, p, 0); -+ -+ /* Decrement link count if applicable. */ -+ if (nlinks > 0 && (p->fts_info == FTS_D || -+ p->fts_info == FTS_DC || p->fts_info == FTS_DOT)) -+ --nlinks; -+ } -+ -+ /* We walk in directory order so "ls -f" doesn't get upset. */ -+ p->fts_link = NULL; -+ if (head == NULL) -+ head = tail = p; -+ else { -+ tail->fts_link = p; -+ tail = p; -+ } -+ ++nitems; -+ } -+ if (dirp) -+ (void)closedir(dirp); -+ -+ /* -+ * If realloc() changed the address of the path, adjust the -+ * addresses for the rest of the tree and the dir list. -+ */ -+ if (doadjust) -+ fts_padjust(sp, head); -+ -+ /* -+ * If not changing directories, reset the path back to original -+ * state. -+ */ -+ if (ISSET(FTS_NOCHDIR)) { -+ if (len == sp->fts_pathlen || nitems == 0) -+ --cp; -+ *cp = '\0'; -+ } -+ -+ /* -+ * If descended after called from fts_children or after called from -+ * fts_read and nothing found, get back. At the root level we use -+ * the saved fd; if one of fts_open()'s arguments is a relative path -+ * to an empty directory, we wind up here with no other way back. If -+ * can't get back, we're done. -+ */ -+ if (descend && (type == BCHILD || !nitems) && -+ (cur->fts_level == FTS_ROOTLEVEL ? -+ FCHDIR(sp, sp->fts_rfd) : -+ fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { -+ cur->fts_info = FTS_ERR; -+ SET(FTS_STOP); -+ fts_lfree(head); -+ return (NULL); -+ } -+ -+ /* If didn't find anything, return NULL. */ -+ if (!nitems) { -+ if (type == BREAD) -+ cur->fts_info = FTS_DP; -+ fts_lfree(head); -+ return (NULL); -+ } -+ -+ /* Sort the entries. */ -+ if (sp->fts_compar && nitems > 1) -+ head = fts_sort(sp, head, nitems); -+ return (head); -+} -+ -+static u_short -+fts_stat(FTS *sp, register FTSENT *p, int follow) -+{ -+ register FTSENT *t; -+ register dev_t dev; -+ register ino_t ino; -+ struct stat *sbp, sb; -+ int saved_errno; -+ -+ /* If user needs stat info, stat buffer already allocated. */ -+ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; -+ -+#if defined FTS_WHITEOUT && 0 -+ /* check for whiteout */ -+ if (p->fts_flags & FTS_ISW) { -+ if (sbp != &sb) { -+ memset(sbp, '\0', sizeof (*sbp)); -+ sbp->st_mode = S_IFWHT; -+ } -+ return (FTS_W); -+ } -+#endif -+ -+ /* -+ * If doing a logical walk, or application requested FTS_FOLLOW, do -+ * a stat(2). If that fails, check for a non-existent symlink. If -+ * fail, set the errno from the stat call. -+ */ -+ if (ISSET(FTS_LOGICAL) || follow) { -+ if (stat(p->fts_accpath, sbp)) { -+ saved_errno = errno; -+ if (!lstat(p->fts_accpath, sbp)) { -+ errno = 0; -+ return (FTS_SLNONE); -+ } -+ p->fts_errno = saved_errno; -+ goto err; -+ } -+ } else if (lstat(p->fts_accpath, sbp)) { -+ p->fts_errno = errno; -+err: memset(sbp, 0, sizeof(struct stat)); -+ return (FTS_NS); -+ } -+ -+ if (S_ISDIR(sbp->st_mode)) { -+ /* -+ * Set the device/inode. Used to find cycles and check for -+ * crossing mount points. Also remember the link count, used -+ * in fts_build to limit the number of stat calls. It is -+ * understood that these fields are only referenced if fts_info -+ * is set to FTS_D. -+ */ -+ dev = p->fts_dev = sbp->st_dev; -+ ino = p->fts_ino = sbp->st_ino; -+ p->fts_nlink = sbp->st_nlink; -+ -+ if (ISDOT(p->fts_name)) -+ return (FTS_DOT); -+ -+ /* -+ * Cycle detection is done by brute force when the directory -+ * is first encountered. If the tree gets deep enough or the -+ * number of symbolic links to directories is high enough, -+ * something faster might be worthwhile. -+ */ -+ for (t = p->fts_parent; -+ t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) -+ if (ino == t->fts_ino && dev == t->fts_dev) { -+ p->fts_cycle = t; -+ return (FTS_DC); -+ } -+ return (FTS_D); -+ } -+ if (S_ISLNK(sbp->st_mode)) -+ return (FTS_SL); -+ if (S_ISREG(sbp->st_mode)) -+ return (FTS_F); -+ return (FTS_DEFAULT); -+} -+ -+static FTSENT * -+fts_sort(FTS *sp, FTSENT *head, register int nitems) -+{ -+ register FTSENT **ap, *p; -+ -+ /* -+ * Construct an array of pointers to the structures and call qsort(3). -+ * Reassemble the array in the order returned by qsort. If unable to -+ * sort for memory reasons, return the directory entries in their -+ * current order. Allocate enough space for the current needs plus -+ * 40 so don't realloc one entry at a time. -+ */ -+ if (nitems > sp->fts_nitems) { -+ struct _ftsent **a; -+ -+ sp->fts_nitems = nitems + 40; -+ if ((a = realloc(sp->fts_array, -+ (size_t)(sp->fts_nitems * sizeof(FTSENT *)))) == NULL) { -+ free(sp->fts_array); -+ sp->fts_array = NULL; -+ sp->fts_nitems = 0; -+ return (head); -+ } -+ sp->fts_array = a; -+ } -+ for (ap = sp->fts_array, p = head; p; p = p->fts_link) -+ *ap++ = p; -+ qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar); -+ for (head = *(ap = sp->fts_array); --nitems; ++ap) -+ ap[0]->fts_link = ap[1]; -+ ap[0]->fts_link = NULL; -+ return (head); -+} -+ -+static FTSENT * -+fts_alloc(FTS *sp, const char *name, size_t namelen) -+{ -+ register FTSENT *p; -+ size_t len; -+ -+ /* -+ * The file name is a variable length array and no stat structure is -+ * necessary if the user has set the nostat bit. Allocate the FTSENT -+ * structure, the file name and the stat structure in one chunk, but -+ * be careful that the stat structure is reasonably aligned. Since the -+ * fts_name field is declared to be of size 1, the fts_name pointer is -+ * namelen + 2 before the first possible address of the stat structure. -+ */ -+ len = sizeof(FTSENT) + namelen; -+ if (!ISSET(FTS_NOSTAT)) -+ len += sizeof(struct stat) + ALIGNBYTES; -+ if ((p = malloc(len)) == NULL) -+ return (NULL); -+ -+ /* Copy the name and guarantee NUL termination. */ -+ memmove(p->fts_name, name, namelen); -+ p->fts_name[namelen] = '\0'; -+ -+ if (!ISSET(FTS_NOSTAT)) -+ p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2); -+ p->fts_namelen = namelen; -+ p->fts_path = sp->fts_path; -+ p->fts_errno = 0; -+ p->fts_flags = 0; -+ p->fts_instr = FTS_NOINSTR; -+ p->fts_number = 0; -+ p->fts_pointer = NULL; -+ return (p); -+} -+ -+static void -+fts_lfree(register FTSENT *head) -+{ -+ register FTSENT *p; -+ -+ /* Free a linked list of structures. */ -+ while ((p = head)) { -+ head = head->fts_link; -+ free(p); -+ } -+} -+ -+/* -+ * Allow essentially unlimited paths; find, rm, ls should all work on any tree. -+ * Most systems will allow creation of paths much longer than MAXPATHLEN, even -+ * though the kernel won't resolve them. Add the size (not just what's needed) -+ * plus 256 bytes so don't realloc the path 2 bytes at a time. -+ */ -+static int -+fts_palloc(FTS *sp, size_t more) -+{ -+ char *p; -+ -+ sp->fts_pathlen += more + 256; -+ /* -+ * Check for possible wraparound. In an FTS, fts_pathlen is -+ * a signed int but in an FTSENT it is an unsigned short. -+ * We limit fts_pathlen to USHRT_MAX to be safe in both cases. -+ */ -+ if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) { -+ free(sp->fts_path); -+ sp->fts_path = NULL; -+ errno = ENAMETOOLONG; -+ return (1); -+ } -+ p = realloc(sp->fts_path, sp->fts_pathlen); -+ if (p == NULL) { -+ free(sp->fts_path); -+ sp->fts_path = NULL; -+ return 1; -+ } -+ sp->fts_path = p; -+ return 0; -+} -+ -+/* -+ * When the path is realloc'd, have to fix all of the pointers in structures -+ * already returned. -+ */ -+static void -+fts_padjust(FTS *sp, FTSENT *head) -+{ -+ FTSENT *p; -+ char *addr = sp->fts_path; -+ -+#define ADJUST(p) do { \ -+ if ((p)->fts_accpath != (p)->fts_name) { \ -+ (p)->fts_accpath = \ -+ (char *)addr + ((p)->fts_accpath - (p)->fts_path); \ -+ } \ -+ (p)->fts_path = addr; \ -+} while (0) -+ /* Adjust the current set of children. */ -+ for (p = sp->fts_child; p; p = p->fts_link) -+ ADJUST(p); -+ -+ /* Adjust the rest of the tree, including the current level. */ -+ for (p = head; p->fts_level >= FTS_ROOTLEVEL;) { -+ ADJUST(p); -+ p = p->fts_link ? p->fts_link : p->fts_parent; -+ } -+} -+ -+static size_t -+fts_maxarglen(char * const *argv) -+{ -+ size_t len, max; -+ -+ for (max = 0; *argv; ++argv) -+ if ((len = strlen(*argv)) > max) -+ max = len; -+ return (max + 1); -+} -+ -+/* -+ * Change to dir specified by fd or p->fts_accpath without getting -+ * tricked by someone changing the world out from underneath us. -+ * Assumes p->fts_dev and p->fts_ino are filled in. -+ */ -+static int -+fts_safe_changedir(FTS *sp, FTSENT *p, int fd, const char *path) -+{ -+ int ret, oerrno, newfd; -+ struct stat64 sb; -+ -+ newfd = fd; -+ if (ISSET(FTS_NOCHDIR)) -+ return (0); -+ if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0) -+ return (-1); -+ if (fstat64(newfd, &sb)) { -+ ret = -1; -+ goto bail; -+ } -+ if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) { -+ errno = ENOENT; /* disinformation */ -+ ret = -1; -+ goto bail; -+ } -+ ret = fchdir(newfd); -+bail: -+ oerrno = errno; -+ if (fd < 0) -+ (void)close(newfd); -+ errno = oerrno; -+ return (ret); -+} -diff --git a/libdwfl/fts_.h b/libdwfl/fts_.h -new file mode 100644 -index 000000000000..0a070ba8dce5 ---- /dev/null -+++ b/libdwfl/fts_.h -@@ -0,0 +1,131 @@ -+/* -+ * Copyright (c) 1989, 1993 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 4. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * @(#)fts.h 8.3 (Berkeley) 8/14/94 -+ */ -+ -+#ifndef _FTS_H -+#define _FTS_H 1 -+ -+#include -+#include -+ -+/* The fts interface is incompatible with the LFS interface which -+ transparently uses the 64-bit file access functions. */ -+#ifdef __USE_FILE_OFFSET64 -+# error " cannot be used with -D_FILE_OFFSET_BITS==64" -+#endif -+ -+ -+typedef struct { -+ struct _ftsent *fts_cur; /* current node */ -+ struct _ftsent *fts_child; /* linked list of children */ -+ struct _ftsent **fts_array; /* sort array */ -+ dev_t fts_dev; /* starting device # */ -+ char *fts_path; /* path for this descent */ -+ int fts_rfd; /* fd for root */ -+ int fts_pathlen; /* sizeof(path) */ -+ int fts_nitems; /* elements in the sort array */ -+ int (*fts_compar) (const void *, const void *); /* compare fn */ -+ -+#define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */ -+#define FTS_LOGICAL 0x0002 /* logical walk */ -+#define FTS_NOCHDIR 0x0004 /* don't change directories */ -+#define FTS_NOSTAT 0x0008 /* don't get stat info */ -+#define FTS_PHYSICAL 0x0010 /* physical walk */ -+#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ -+#define FTS_XDEV 0x0040 /* don't cross devices */ -+#define FTS_WHITEOUT 0x0080 /* return whiteout information */ -+#define FTS_OPTIONMASK 0x00ff /* valid user option mask */ -+ -+#define FTS_NAMEONLY 0x0100 /* (private) child names only */ -+#define FTS_STOP 0x0200 /* (private) unrecoverable error */ -+ int fts_options; /* fts_open options, global flags */ -+} FTS; -+ -+typedef struct _ftsent { -+ struct _ftsent *fts_cycle; /* cycle node */ -+ struct _ftsent *fts_parent; /* parent directory */ -+ struct _ftsent *fts_link; /* next file in directory */ -+ long fts_number; /* local numeric value */ -+ void *fts_pointer; /* local address value */ -+ char *fts_accpath; /* access path */ -+ char *fts_path; /* root path */ -+ int fts_errno; /* errno for this node */ -+ int fts_symfd; /* fd for symlink */ -+ u_short fts_pathlen; /* strlen(fts_path) */ -+ u_short fts_namelen; /* strlen(fts_name) */ -+ -+ ino_t fts_ino; /* inode */ -+ dev_t fts_dev; /* device */ -+ nlink_t fts_nlink; /* link count */ -+ -+#define FTS_ROOTPARENTLEVEL -1 -+#define FTS_ROOTLEVEL 0 -+ short fts_level; /* depth (-1 to N) */ -+ -+#define FTS_D 1 /* preorder directory */ -+#define FTS_DC 2 /* directory that causes cycles */ -+#define FTS_DEFAULT 3 /* none of the above */ -+#define FTS_DNR 4 /* unreadable directory */ -+#define FTS_DOT 5 /* dot or dot-dot */ -+#define FTS_DP 6 /* postorder directory */ -+#define FTS_ERR 7 /* error; errno is set */ -+#define FTS_F 8 /* regular file */ -+#define FTS_INIT 9 /* initialized only */ -+#define FTS_NS 10 /* stat(2) failed */ -+#define FTS_NSOK 11 /* no stat(2) requested */ -+#define FTS_SL 12 /* symbolic link */ -+#define FTS_SLNONE 13 /* symbolic link without target */ -+#define FTS_W 14 /* whiteout object */ -+ u_short fts_info; /* user flags for FTSENT structure */ -+ -+#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ -+#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ -+ u_short fts_flags; /* private flags for FTSENT structure */ -+ -+#define FTS_AGAIN 1 /* read node again */ -+#define FTS_FOLLOW 2 /* follow symbolic link */ -+#define FTS_NOINSTR 3 /* no instructions */ -+#define FTS_SKIP 4 /* discard node */ -+ u_short fts_instr; /* fts_set() instructions */ -+ -+ struct stat *fts_statp; /* stat(2) information */ -+ char fts_name[1]; /* file name */ -+} FTSENT; -+ -+__BEGIN_DECLS -+FTSENT *fts_children (FTS *, int); -+int fts_close (FTS *); -+FTS *fts_open (char * const *, int, -+ int (*)(const FTSENT **, const FTSENT **)); -+FTSENT *fts_read (FTS *); -+int fts_set (FTS *, FTSENT *, int) __THROW; -+__END_DECLS -+ -+#endif /* fts.h */ -diff --git a/libdwfl/linux-kernel-modules.c b/libdwfl/linux-kernel-modules.c -index 9d0fef2cf260..47f0e3892294 100644 ---- a/libdwfl/linux-kernel-modules.c -+++ b/libdwfl/linux-kernel-modules.c -@@ -31,10 +31,14 @@ - Everything we need here is fine if its declarations just come first. - Also, include sys/types.h before fts. On some systems fts.h is not self - contained. */ -+#ifdef HAVE_FTS_H - #ifdef BAD_FTS - #include - #include - #endif -+#else -+#include -+#endif - - #include - #include --- -2.11.0 - diff --git a/package/elfutils/0004-disable-po.patch b/package/elfutils/0004-disable-po.patch deleted file mode 100644 index c45c580463..0000000000 --- a/package/elfutils/0004-disable-po.patch +++ /dev/null @@ -1,24 +0,0 @@ -Disable the build of the po/ directory - -Building the po/ directory complains that the scripts in there have -been generated with gettext 0.17, while we use gettext 0.18 in -Buildroot. Since we don't care that much about po files anyway, just -disable the build of this directory. - -Based on the former patch by Thomas Petazzoni. - -Signed-off-by: Thomas Petazzoni -Signed-off-by: Vicente Olivert Riera - -diff -rup a/Makefile.am b/Makefile.am ---- a/Makefile.am 2014-11-07 15:14:39.018060884 +0000 -+++ b/Makefile.am 2014-11-07 15:30:02.864918229 +0000 -@@ -28,7 +28,7 @@ endif - - # Add doc back when we have some real content. - SUBDIRS = config m4 lib libelf libebl libdwelf libdwfl libdw libcpu libasm \ -- backends $(PROGS_SUBDIR) po tests -+ backends $(PROGS_SUBDIR) tests - - EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING \ - COPYING COPYING-GPLV2 COPYING-LGPLV3 diff --git a/package/elfutils/0005-really-make-werror-conditional-to-build-werror.patch b/package/elfutils/0005-really-make-werror-conditional-to-build-werror.patch deleted file mode 100644 index a7017d6e88..0000000000 --- a/package/elfutils/0005-really-make-werror-conditional-to-build-werror.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 1d8f27d73df6369b19ddd6732960df0d4fdec338 Mon Sep 17 00:00:00 2001 -From: Vicente Olivert Riera -Date: Mon, 29 May 2017 23:24:42 +0300 -Subject: [PATCH] Really make -Werror conditional to BUILD_WERROR - -Otherwise it will fail with an error message like this one: - -elf_getarsym.c:290:9: error: 'n' may be used uninitialized in this -function [-Werror=maybe-uninitialized] - arsym[n].as_name = NULL; - ^ -cc1: all warnings being treated as errors - -[Vincent: tweak patch for 0.166] - -Signed-off-by: "Yann E. MORIN" -Signed-off-by: Vicente Olivert Riera ---- - config/eu.am | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/config/eu.am b/config/eu.am -index 8fe1e259f9e2..c5a6209a4e04 100644 ---- a/config/eu.am -+++ b/config/eu.am -@@ -71,7 +71,6 @@ AM_CFLAGS = -std=gnu99 -Wall -Wshadow -Wformat=2 \ - -Wold-style-definition -Wstrict-prototypes \ - $(LOGICAL_OP_WARNING) $(DUPLICATED_COND_WARNING) \ - $(NULL_DEREFERENCE_WARNING) $(IMPLICIT_FALLTHROUGH_WARNING) \ -- $(if $($(*F)_no_Werror),,-Werror) \ - $(if $($(*F)_no_Wunused),,-Wunused -Wextra) \ - $(if $($(*F)_no_Wstack_usage),,$(STACK_USAGE_WARNING)) \ - $($(*F)_CFLAGS) --- -2.11.0 - diff --git a/package/elfutils/0006-memcpy-def.patch b/package/elfutils/0006-memcpy-def.patch deleted file mode 100644 index 509482774c..0000000000 --- a/package/elfutils/0006-memcpy-def.patch +++ /dev/null @@ -1,26 +0,0 @@ -Provide a compatibility alias __memcpy - -For some reason, libelf uses the internal glibc alias __memcpy, which -doesn't exist in uClibc. Add a manual alias so that the build can -proceed with uClibc. - -Based on the former patch by Thomas Petazzoni. - -Signed-off-by: Thomas Petazzoni -Signed-off-by: Vicente Olivert Riera - -diff -rup a/libelf/libelf.h b/libelf/libelf.h ---- a/libelf/libelf.h 2014-08-27 10:25:17.000000000 +0100 -+++ b/libelf/libelf.h 2014-11-07 15:13:08.743508221 +0000 -@@ -34,6 +34,11 @@ - /* Get the ELF types. */ - #include - -+#ifndef _LIBC -+#ifndef __mempcpy -+#define __mempcpy mempcpy -+#endif -+#endif - - /* Known translation types. */ - typedef enum diff --git a/package/elfutils/elfutils.hash b/package/elfutils/elfutils.hash index 76b6dc6458..dc321e9359 100644 --- a/package/elfutils/elfutils.hash +++ b/package/elfutils/elfutils.hash @@ -1,2 +1,6 @@ -# From https://sourceware.org/elfutils/ftp/0.169/sha512.sum -sha512 0a81a20bb2aff533d035d6b76f1403437b2e11bce390db57e34b8c26e4b9b3150346d83dddcbfbbdc58063f046ca3223508dba35c6ce88e375d201e7a777a8b9 elfutils-0.169.tar.bz2 +# From https://sourceware.org/elfutils/ftp/0.171/sha512.sum +sha512 777be2d63ca9b11440bf358a33428d9ca974e2612a880934156c9f7194af596ed627c1ed2d48dbd47a3761c94913b8f39565f9dcb6b62c92bf229f04c96d5ee3 elfutils-0.171.tar.bz2 +# Locally calculated +sha256 8ceb4b9ee5adedde47b31e975c1d90c73ad27b6b165a1dcd80c7c545eb65b903 COPYING +sha256 8177f97513213526df2cf6184d8ff986c675afb514d4e68a404010521b880643 COPYING-GPLV2 +sha256 da7eabb7bafdf7d3ae5e9f223aa5bdc1eece45ac569dc21b3b037520b4464768 COPYING-LGPLV3 diff --git a/package/elfutils/elfutils.mk b/package/elfutils/elfutils.mk index 5570a3b37f..5eaaaeadad 100644 --- a/package/elfutils/elfutils.mk +++ b/package/elfutils/elfutils.mk @@ -4,12 +4,12 @@ # ################################################################################ -ELFUTILS_VERSION = 0.169 +ELFUTILS_VERSION = 0.171 ELFUTILS_SOURCE = elfutils-$(ELFUTILS_VERSION).tar.bz2 ELFUTILS_SITE = https://sourceware.org/elfutils/ftp/$(ELFUTILS_VERSION) ELFUTILS_INSTALL_STAGING = YES ELFUTILS_LICENSE = GPL-2.0+ or LGPL-3.0+ (library) -ELFUTILS_LICENSE_FILES = COPYING-GPLV2 COPYING-LGPLV3 +ELFUTILS_LICENSE_FILES = COPYING COPYING-GPLV2 COPYING-LGPLV3 ELFUTILS_DEPENDENCIES = zlib $(TARGET_NLS_DEPENDENCIES) HOST_ELFUTILS_DEPENDENCIES = host-zlib host-bzip2 host-xz