summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta-oe/recipes-core/uclibc/uclibc-git/fts-support.patch1375
-rw-r--r--meta-oe/recipes-core/uclibc/uclibc-git/uClibc.distro3
-rw-r--r--meta-oe/recipes-core/uclibc/uclibc_git.bb3
3 files changed, 4 insertions, 1377 deletions
diff --git a/meta-oe/recipes-core/uclibc/uclibc-git/fts-support.patch b/meta-oe/recipes-core/uclibc/uclibc-git/fts-support.patch
deleted file mode 100644
index eda25c710b..0000000000
--- a/meta-oe/recipes-core/uclibc/uclibc-git/fts-support.patch
+++ /dev/null
@@ -1,1375 +0,0 @@
1Added fts support for traversing UNIX file hierarchies.
2It is required by libdwfl in elfutils package.
3
4Signed-off-by: Salvatore Cro <salvatore.cro at st.com>
5---
6 extra/Configs/Config.in | 9 +
7 include/fts.h | 131 ++++++
8 libc/misc/Makefile.in | 1 +
9 libc/misc/fts/Makefile | 14 +
10 libc/misc/fts/Makefile.in | 22 +
11 libc/misc/fts/fts.c | 1139 +++++++++++++++++++++++++++++++++++++++++++++
12 6 files changed, 1316 insertions(+), 0 deletions(-)
13 create mode 100644 include/fts.h
14 create mode 100644 libc/misc/fts/Makefile
15 create mode 100644 libc/misc/fts/Makefile.in
16 create mode 100644 libc/misc/fts/fts.c
17
18Index: git/extra/Configs/Config.in
19===================================================================
20--- git.orig/extra/Configs/Config.in
21+++ git/extra/Configs/Config.in
22@@ -1899,6 +1899,15 @@ config UCLIBC_HAS_FTW
23 a pressing need for ftw(), you should probably answer N.
24
25
26+config UCLIBC_HAS_FTS
27+ bool "Support the fts() interface"
28+ default n
29+ help
30+ The fts functions are provided for traversing UNIX file hierarchies.
31+
32+ This interface is currently used by the elfutils, and adds around 7.5k.
33+ Unless you need to build/use elfutils, you should probably answer N.
34+
35 config UCLIBC_HAS_GLOB
36 bool "Support the glob() interface"
37 depends on UCLIBC_HAS_FNMATCH
38Index: git/include/fts.h
39===================================================================
40--- /dev/null
41+++ git/include/fts.h
42@@ -0,0 +1,131 @@
43+/*
44+ * Copyright (c) 1989, 1993
45+ * The Regents of the University of California. All rights reserved.
46+ *
47+ * Redistribution and use in source and binary forms, with or without
48+ * modification, are permitted provided that the following conditions
49+ * are met:
50+ * 1. Redistributions of source code must retain the above copyright
51+ * notice, this list of conditions and the following disclaimer.
52+ * 2. Redistributions in binary form must reproduce the above copyright
53+ * notice, this list of conditions and the following disclaimer in the
54+ * documentation and/or other materials provided with the distribution.
55+ * 4. Neither the name of the University nor the names of its contributors
56+ * may be used to endorse or promote products derived from this software
57+ * without specific prior written permission.
58+ *
59+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69+ * SUCH DAMAGE.
70+ *
71+ * @(#)fts.h 8.3 (Berkeley) 8/14/94
72+ */
73+
74+#ifndef _FTS_H
75+#define _FTS_H 1
76+
77+#include <features.h>
78+#include <sys/types.h>
79+
80+/* The fts interface is incompatible with the LFS interface which
81+ transparently uses the 64-bit file access functions. */
82+#ifdef __USE_FILE_OFFSET64
83+# error "<fts.h> cannot be used with -D_FILE_OFFSET_BITS==64"
84+#endif
85+
86+
87+typedef struct {
88+ struct _ftsent *fts_cur; /* current node */
89+ struct _ftsent *fts_child; /* linked list of children */
90+ struct _ftsent **fts_array; /* sort array */
91+ dev_t fts_dev; /* starting device # */
92+ char *fts_path; /* path for this descent */
93+ int fts_rfd; /* fd for root */
94+ int fts_pathlen; /* sizeof(path) */
95+ int fts_nitems; /* elements in the sort array */
96+ int (*fts_compar) (const void *, const void *); /* compare fn */
97+
98+#define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */
99+#define FTS_LOGICAL 0x0002 /* logical walk */
100+#define FTS_NOCHDIR 0x0004 /* don't change directories */
101+#define FTS_NOSTAT 0x0008 /* don't get stat info */
102+#define FTS_PHYSICAL 0x0010 /* physical walk */
103+#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */
104+#define FTS_XDEV 0x0040 /* don't cross devices */
105+#define FTS_WHITEOUT 0x0080 /* return whiteout information */
106+#define FTS_OPTIONMASK 0x00ff /* valid user option mask */
107+
108+#define FTS_NAMEONLY 0x0100 /* (private) child names only */
109+#define FTS_STOP 0x0200 /* (private) unrecoverable error */
110+ int fts_options; /* fts_open options, global flags */
111+} FTS;
112+
113+typedef struct _ftsent {
114+ struct _ftsent *fts_cycle; /* cycle node */
115+ struct _ftsent *fts_parent; /* parent directory */
116+ struct _ftsent *fts_link; /* next file in directory */
117+ long fts_number; /* local numeric value */
118+ void *fts_pointer; /* local address value */
119+ char *fts_accpath; /* access path */
120+ char *fts_path; /* root path */
121+ int fts_errno; /* errno for this node */
122+ int fts_symfd; /* fd for symlink */
123+ u_short fts_pathlen; /* strlen(fts_path) */
124+ u_short fts_namelen; /* strlen(fts_name) */
125+
126+ ino_t fts_ino; /* inode */
127+ dev_t fts_dev; /* device */
128+ nlink_t fts_nlink; /* link count */
129+
130+#define FTS_ROOTPARENTLEVEL -1
131+#define FTS_ROOTLEVEL 0
132+ short fts_level; /* depth (-1 to N) */
133+
134+#define FTS_D 1 /* preorder directory */
135+#define FTS_DC 2 /* directory that causes cycles */
136+#define FTS_DEFAULT 3 /* none of the above */
137+#define FTS_DNR 4 /* unreadable directory */
138+#define FTS_DOT 5 /* dot or dot-dot */
139+#define FTS_DP 6 /* postorder directory */
140+#define FTS_ERR 7 /* error; errno is set */
141+#define FTS_F 8 /* regular file */
142+#define FTS_INIT 9 /* initialized only */
143+#define FTS_NS 10 /* stat(2) failed */
144+#define FTS_NSOK 11 /* no stat(2) requested */
145+#define FTS_SL 12 /* symbolic link */
146+#define FTS_SLNONE 13 /* symbolic link without target */
147+#define FTS_W 14 /* whiteout object */
148+ u_short fts_info; /* user flags for FTSENT structure */
149+
150+#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */
151+#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */
152+ u_short fts_flags; /* private flags for FTSENT structure */
153+
154+#define FTS_AGAIN 1 /* read node again */
155+#define FTS_FOLLOW 2 /* follow symbolic link */
156+#define FTS_NOINSTR 3 /* no instructions */
157+#define FTS_SKIP 4 /* discard node */
158+ u_short fts_instr; /* fts_set() instructions */
159+
160+ struct stat *fts_statp; /* stat(2) information */
161+ char fts_name[1]; /* file name */
162+} FTSENT;
163+
164+__BEGIN_DECLS
165+FTSENT *fts_children (FTS *, int);
166+int fts_close (FTS *);
167+FTS *fts_open (char * const *, int,
168+ int (*)(const FTSENT **, const FTSENT **));
169+FTSENT *fts_read (FTS *);
170+int fts_set (FTS *, FTSENT *, int) __THROW;
171+__END_DECLS
172+
173+#endif /* fts.h */
174Index: git/libc/misc/Makefile.in
175===================================================================
176--- git.orig/libc/misc/Makefile.in
177+++ git/libc/misc/Makefile.in
178@@ -16,6 +16,7 @@ include $(top_srcdir)libc/misc/elf/Makef
179 include $(top_srcdir)libc/misc/file/Makefile.in
180 include $(top_srcdir)libc/misc/fnmatch/Makefile.in
181 include $(top_srcdir)libc/misc/ftw/Makefile.in
182+include $(top_srcdir)libc/misc/fts/Makefile.in
183 include $(top_srcdir)libc/misc/glob/Makefile.in
184 include $(top_srcdir)libc/misc/gnu/Makefile.in
185 include $(top_srcdir)libc/misc/internals/Makefile.in
186Index: git/libc/misc/fts/Makefile
187===================================================================
188--- /dev/null
189+++ git/libc/misc/fts/Makefile
190@@ -0,0 +1,14 @@
191+# Makefile for uClibc
192+#
193+# Copyright (C) 2009 STMicroelectronics Ltd.
194+# Author: Salvatore Cro <salvatore.cro at st.com>
195+#
196+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
197+#
198+
199+top_srcdir=../../../
200+top_builddir=../../../
201+all: objs
202+include $(top_builddir)Rules.mak
203+include Makefile.in
204+include $(top_srcdir)Makerules
205Index: git/libc/misc/fts/Makefile.in
206===================================================================
207--- /dev/null
208+++ git/libc/misc/fts/Makefile.in
209@@ -0,0 +1,22 @@
210+# FTS Makefile for uClibc
211+#
212+# Copyright (C) 2009 STMicroelectronics Ltd.
213+# Author: Salvatore Cro <salvatore.cro at st.com>
214+#
215+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
216+#
217+
218+CSRC := fts.c
219+
220+MISC_FTS_DIR := $(top_srcdir)libc/misc/fts
221+MISC_FTS_OUT := $(top_builddir)libc/misc/fts
222+
223+MISC_FTS_SRC := $(patsubst %.c,$(MISC_FTS_DIR)/%.c,$(CSRC))
224+MISC_FTS_OBJ := $(patsubst %.c,$(MISC_FTS_OUT)/%.o,$(CSRC))
225+
226+libc-$(UCLIBC_HAS_FTS) += $(MISC_FTS_OBJ)
227+
228+objclean-$(UCLIBC_HAS_FTS) += misc_fts_clean
229+
230+misc_fts_clean:
231+ $(do_rm) $(addprefix $(MISC_FTS_OUT)/*., o os)
232Index: git/libc/misc/fts/fts.c
233===================================================================
234--- /dev/null
235+++ git/libc/misc/fts/fts.c
236@@ -0,0 +1,1139 @@
237+/*-
238+ * Copyright (c) 1990, 1993, 1994
239+ * The Regents of the University of California. All rights reserved.
240+ *
241+ * Redistribution and use in source and binary forms, with or without
242+ * modification, are permitted provided that the following conditions
243+ * are met:
244+ * 1. Redistributions of source code must retain the above copyright
245+ * notice, this list of conditions and the following disclaimer.
246+ * 2. Redistributions in binary form must reproduce the above copyright
247+ * notice, this list of conditions and the following disclaimer in the
248+ * documentation and/or other materials provided with the distribution.
249+ * 4. Neither the name of the University nor the names of its contributors
250+ * may be used to endorse or promote products derived from this software
251+ * without specific prior written permission.
252+ *
253+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
254+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
255+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
256+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
257+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
258+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
259+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
260+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
261+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
262+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
263+ * SUCH DAMAGE.
264+ */
265+
266+#include <sys/param.h>
267+#include <sys/stat.h>
268+#include <fcntl.h>
269+#include <dirent.h>
270+#include <errno.h>
271+#include <fts.h>
272+#include <stdlib.h>
273+#include <string.h>
274+#include <unistd.h>
275+
276+
277+/* Largest alignment size needed, minus one.
278+ Usually long double is the worst case. */
279+#ifndef ALIGNBYTES
280+#define ALIGNBYTES (__alignof__ (long double) - 1)
281+#endif
282+/* Align P to that size. */
283+#ifndef ALIGN
284+#define ALIGN(p) (((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES)
285+#endif
286+
287+
288+static FTSENT *fts_alloc (FTS *, const char *, size_t) internal_function;
289+static FTSENT *fts_build (FTS *, int) internal_function;
290+static void fts_lfree (FTSENT *) internal_function;
291+static void fts_load (FTS *, FTSENT *) internal_function;
292+static size_t fts_maxarglen (char * const *) internal_function;
293+static void fts_padjust (FTS *, FTSENT *) internal_function;
294+static int fts_palloc (FTS *, size_t) internal_function;
295+static FTSENT *fts_sort (FTS *, FTSENT *, int) internal_function;
296+static u_short fts_stat (FTS *, FTSENT *, int) internal_function;
297+static int fts_safe_changedir (FTS *, FTSENT *, int, const char *)
298+ internal_function;
299+
300+#ifndef MAX
301+#define MAX(a, b) ({ __typeof__ (a) _a = (a); \
302+ __typeof__ (b) _b = (b); \
303+ _a > _b ? _a : _b; })
304+#endif
305+
306+#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
307+
308+#define CLR(opt) (sp->fts_options &= ~(opt))
309+#define ISSET(opt) (sp->fts_options & (opt))
310+#define SET(opt) (sp->fts_options |= (opt))
311+
312+#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd))
313+
314+/* fts_build flags */
315+#define BCHILD 1 /* fts_children */
316+#define BNAMES 2 /* fts_children, names only */
317+#define BREAD 3 /* fts_read */
318+
319+FTS *
320+fts_open(argv, options, compar)
321+ char * const *argv;
322+ register int options;
323+ int (*compar) (const FTSENT **, const FTSENT **);
324+{
325+ register FTS *sp;
326+ register FTSENT *p, *root;
327+ register int nitems;
328+ FTSENT *parent = NULL;
329+ FTSENT *tmp = NULL;
330+
331+ /* Options check. */
332+ if (options & ~FTS_OPTIONMASK) {
333+ __set_errno (EINVAL);
334+ return (NULL);
335+ }
336+
337+ /* Allocate/initialize the stream */
338+ if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
339+ return (NULL);
340+ memset(sp, 0, sizeof(FTS));
341+ sp->fts_compar = (int (*) (const void *, const void *)) compar;
342+ sp->fts_options = options;
343+
344+ /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
345+ if (ISSET(FTS_LOGICAL))
346+ SET(FTS_NOCHDIR);
347+
348+ /*
349+ * Start out with 1K of path space, and enough, in any case,
350+ * to hold the user's paths.
351+ */
352+#ifndef MAXPATHLEN
353+#define MAXPATHLEN 1024
354+#endif
355+ size_t maxarglen = fts_maxarglen(argv);
356+ if (fts_palloc(sp, MAX(maxarglen, MAXPATHLEN)))
357+ goto mem1;
358+
359+ /* Allocate/initialize root's parent. */
360+ if (*argv != NULL) {
361+ if ((parent = fts_alloc(sp, "", 0)) == NULL)
362+ goto mem2;
363+ parent->fts_level = FTS_ROOTPARENTLEVEL;
364+ }
365+
366+ /* Allocate/initialize root(s). */
367+ for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
368+ /* Don't allow zero-length paths. */
369+ size_t len = strlen(*argv);
370+ if (len == 0) {
371+ __set_errno (ENOENT);
372+ goto mem3;
373+ }
374+
375+ p = fts_alloc(sp, *argv, len);
376+ p->fts_level = FTS_ROOTLEVEL;
377+ p->fts_parent = parent;
378+ p->fts_accpath = p->fts_name;
379+ p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
380+
381+ /* Command-line "." and ".." are real directories. */
382+ if (p->fts_info == FTS_DOT)
383+ p->fts_info = FTS_D;
384+
385+ /*
386+ * If comparison routine supplied, traverse in sorted
387+ * order; otherwise traverse in the order specified.
388+ */
389+ if (compar) {
390+ p->fts_link = root;
391+ root = p;
392+ } else {
393+ p->fts_link = NULL;
394+ if (root == NULL)
395+ tmp = root = p;
396+ else {
397+ tmp->fts_link = p;
398+ tmp = p;
399+ }
400+ }
401+ }
402+ if (compar && nitems > 1)
403+ root = fts_sort(sp, root, nitems);
404+
405+ /*
406+ * Allocate a dummy pointer and make fts_read think that we've just
407+ * finished the node before the root(s); set p->fts_info to FTS_INIT
408+ * so that everything about the "current" node is ignored.
409+ */
410+ if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
411+ goto mem3;
412+ sp->fts_cur->fts_link = root;
413+ sp->fts_cur->fts_info = FTS_INIT;
414+
415+ /*
416+ * If using chdir(2), grab a file descriptor pointing to dot to ensure
417+ * that we can get back here; this could be avoided for some paths,
418+ * but almost certainly not worth the effort. Slashes, symbolic links,
419+ * and ".." are all fairly nasty problems. Note, if we can't get the
420+ * descriptor we run anyway, just more slowly.
421+ */
422+ if (!ISSET(FTS_NOCHDIR)
423+ && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0)
424+ SET(FTS_NOCHDIR);
425+
426+ return (sp);
427+
428+mem3: fts_lfree(root);
429+ free(parent);
430+mem2: free(sp->fts_path);
431+mem1: free(sp);
432+ return (NULL);
433+}
434+
435+static void
436+internal_function
437+fts_load(sp, p)
438+ FTS *sp;
439+ register FTSENT *p;
440+{
441+ register int len;
442+ register char *cp;
443+
444+ /*
445+ * Load the stream structure for the next traversal. Since we don't
446+ * actually enter the directory until after the preorder visit, set
447+ * the fts_accpath field specially so the chdir gets done to the right
448+ * place and the user can access the first node. From fts_open it's
449+ * known that the path will fit.
450+ */
451+ len = p->fts_pathlen = p->fts_namelen;
452+ memmove(sp->fts_path, p->fts_name, len + 1);
453+ if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
454+ len = strlen(++cp);
455+ memmove(p->fts_name, cp, len + 1);
456+ p->fts_namelen = len;
457+ }
458+ p->fts_accpath = p->fts_path = sp->fts_path;
459+ sp->fts_dev = p->fts_dev;
460+}
461+
462+int
463+fts_close(sp)
464+ FTS *sp;
465+{
466+ register FTSENT *freep, *p;
467+ int saved_errno;
468+
469+ /*
470+ * This still works if we haven't read anything -- the dummy structure
471+ * points to the root list, so we step through to the end of the root
472+ * list which has a valid parent pointer.
473+ */
474+ if (sp->fts_cur) {
475+ for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
476+ freep = p;
477+ p = p->fts_link != NULL ? p->fts_link : p->fts_parent;
478+ free(freep);
479+ }
480+ free(p);
481+ }
482+
483+ /* Free up child linked list, sort array, path buffer. */
484+ if (sp->fts_child)
485+ fts_lfree(sp->fts_child);
486+ free(sp->fts_array);
487+ free(sp->fts_path);
488+
489+ /* Return to original directory, save errno if necessary. */
490+ if (!ISSET(FTS_NOCHDIR)) {
491+ saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
492+ (void)close(sp->fts_rfd);
493+
494+ /* Set errno and return. */
495+ if (saved_errno != 0) {
496+ /* Free up the stream pointer. */
497+ free(sp);
498+ __set_errno (saved_errno);
499+ return (-1);
500+ }
501+ }
502+
503+ /* Free up the stream pointer. */
504+ free(sp);
505+ return (0);
506+}
507+
508+/*
509+ * Special case of "/" at the end of the path so that slashes aren't
510+ * appended which would cause paths to be written as "....//foo".
511+ */
512+#define NAPPEND(p) \
513+ (p->fts_path[p->fts_pathlen - 1] == '/' \
514+ ? p->fts_pathlen - 1 : p->fts_pathlen)
515+
516+FTSENT *
517+fts_read(sp)
518+ register FTS *sp;
519+{
520+ register FTSENT *p, *tmp;
521+ register int instr;
522+ register char *t;
523+ int saved_errno;
524+
525+ /* If finished or unrecoverable error, return NULL. */
526+ if (sp->fts_cur == NULL || ISSET(FTS_STOP))
527+ return (NULL);
528+
529+ /* Set current node pointer. */
530+ p = sp->fts_cur;
531+
532+ /* Save and zero out user instructions. */
533+ instr = p->fts_instr;
534+ p->fts_instr = FTS_NOINSTR;
535+
536+ /* Any type of file may be re-visited; re-stat and re-turn. */
537+ if (instr == FTS_AGAIN) {
538+ p->fts_info = fts_stat(sp, p, 0);
539+ return (p);
540+ }
541+
542+ /*
543+ * Following a symlink -- SLNONE test allows application to see
544+ * SLNONE and recover. If indirecting through a symlink, have
545+ * keep a pointer to current location. If unable to get that
546+ * pointer, follow fails.
547+ */
548+ if (instr == FTS_FOLLOW &&
549+ (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
550+ p->fts_info = fts_stat(sp, p, 1);
551+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
552+ if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) {
553+ p->fts_errno = errno;
554+ p->fts_info = FTS_ERR;
555+ } else
556+ p->fts_flags |= FTS_SYMFOLLOW;
557+ }
558+ return (p);
559+ }
560+
561+ /* Directory in pre-order. */
562+ if (p->fts_info == FTS_D) {
563+ /* If skipped or crossed mount point, do post-order visit. */
564+ if (instr == FTS_SKIP ||
565+ (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
566+ if (p->fts_flags & FTS_SYMFOLLOW)
567+ (void)close(p->fts_symfd);
568+ if (sp->fts_child) {
569+ fts_lfree(sp->fts_child);
570+ sp->fts_child = NULL;
571+ }
572+ p->fts_info = FTS_DP;
573+ return (p);
574+ }
575+
576+ /* Rebuild if only read the names and now traversing. */
577+ if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {
578+ CLR(FTS_NAMEONLY);
579+ fts_lfree(sp->fts_child);
580+ sp->fts_child = NULL;
581+ }
582+
583+ /*
584+ * Cd to the subdirectory.
585+ *
586+ * If have already read and now fail to chdir, whack the list
587+ * to make the names come out right, and set the parent errno
588+ * so the application will eventually get an error condition.
589+ * Set the FTS_DONTCHDIR flag so that when we logically change
590+ * directories back to the parent we don't do a chdir.
591+ *
592+ * If haven't read do so. If the read fails, fts_build sets
593+ * FTS_STOP or the fts_info field of the node.
594+ */
595+ if (sp->fts_child != NULL) {
596+ if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
597+ p->fts_errno = errno;
598+ p->fts_flags |= FTS_DONTCHDIR;
599+ for (p = sp->fts_child; p != NULL;
600+ p = p->fts_link)
601+ p->fts_accpath =
602+ p->fts_parent->fts_accpath;
603+ }
604+ } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
605+ if (ISSET(FTS_STOP))
606+ return (NULL);
607+ return (p);
608+ }
609+ p = sp->fts_child;
610+ sp->fts_child = NULL;
611+ sp->fts_cur = p;
612+ goto name;
613+ }
614+
615+ /* Move to the next node on this level. */
616+next: tmp = p;
617+ if ((p = p->fts_link) != NULL) {
618+ sp->fts_cur = p;
619+ free(tmp);
620+
621+ /*
622+ * If reached the top, return to the original directory (or
623+ * the root of the tree), and load the paths for the next root.
624+ */
625+ if (p->fts_level == FTS_ROOTLEVEL) {
626+ if (FCHDIR(sp, sp->fts_rfd)) {
627+ SET(FTS_STOP);
628+ return (NULL);
629+ }
630+ fts_load(sp, p);
631+ return p;
632+ }
633+
634+ /*
635+ * User may have called fts_set on the node. If skipped,
636+ * ignore. If followed, get a file descriptor so we can
637+ * get back if necessary.
638+ */
639+ if (p->fts_instr == FTS_SKIP)
640+ goto next;
641+ if (p->fts_instr == FTS_FOLLOW) {
642+ p->fts_info = fts_stat(sp, p, 1);
643+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
644+ if ((p->fts_symfd =
645+ open(".", O_RDONLY, 0)) < 0) {
646+ p->fts_errno = errno;
647+ p->fts_info = FTS_ERR;
648+ } else
649+ p->fts_flags |= FTS_SYMFOLLOW;
650+ }
651+ p->fts_instr = FTS_NOINSTR;
652+ }
653+
654+name: t = sp->fts_path + NAPPEND(p->fts_parent);
655+ *t++ = '/';
656+ memmove(t, p->fts_name, p->fts_namelen + 1);
657+ return p;
658+ }
659+
660+ /* Move up to the parent node. */
661+ p = tmp->fts_parent;
662+ sp->fts_cur = p;
663+ free(tmp);
664+
665+ if (p->fts_level == FTS_ROOTPARENTLEVEL) {
666+ /*
667+ * Done; free everything up and set errno to 0 so the user
668+ * can distinguish between error and EOF.
669+ */
670+ free(p);
671+ __set_errno (0);
672+ return (sp->fts_cur = NULL);
673+ }
674+
675+ /* NUL terminate the pathname. */
676+ sp->fts_path[p->fts_pathlen] = '\0';
677+
678+ /*
679+ * Return to the parent directory. If at a root node or came through
680+ * a symlink, go back through the file descriptor. Otherwise, cd up
681+ * one directory.
682+ */
683+ if (p->fts_level == FTS_ROOTLEVEL) {
684+ if (FCHDIR(sp, sp->fts_rfd)) {
685+ SET(FTS_STOP);
686+ return (NULL);
687+ }
688+ } else if (p->fts_flags & FTS_SYMFOLLOW) {
689+ if (FCHDIR(sp, p->fts_symfd)) {
690+ saved_errno = errno;
691+ (void)close(p->fts_symfd);
692+ __set_errno (saved_errno);
693+ SET(FTS_STOP);
694+ return (NULL);
695+ }
696+ (void)close(p->fts_symfd);
697+ } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
698+ fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
699+ SET(FTS_STOP);
700+ return (NULL);
701+ }
702+ p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
703+ return p;
704+}
705+
706+/*
707+ * Fts_set takes the stream as an argument although it's not used in this
708+ * implementation; it would be necessary if anyone wanted to add global
709+ * semantics to fts using fts_set. An error return is allowed for similar
710+ * reasons.
711+ */
712+/* ARGSUSED */
713+int
714+fts_set(sp, p, instr)
715+ FTS *sp;
716+ FTSENT *p;
717+ int instr;
718+{
719+ if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
720+ instr != FTS_NOINSTR && instr != FTS_SKIP) {
721+ __set_errno (EINVAL);
722+ return (1);
723+ }
724+ p->fts_instr = instr;
725+ return (0);
726+}
727+
728+FTSENT *
729+fts_children(sp, instr)
730+ register FTS *sp;
731+ int instr;
732+{
733+ register FTSENT *p;
734+ int fd;
735+
736+ if (instr != 0 && instr != FTS_NAMEONLY) {
737+ __set_errno (EINVAL);
738+ return (NULL);
739+ }
740+
741+ /* Set current node pointer. */
742+ p = sp->fts_cur;
743+
744+ /*
745+ * Errno set to 0 so user can distinguish empty directory from
746+ * an error.
747+ */
748+ __set_errno (0);
749+
750+ /* Fatal errors stop here. */
751+ if (ISSET(FTS_STOP))
752+ return (NULL);
753+
754+ /* Return logical hierarchy of user's arguments. */
755+ if (p->fts_info == FTS_INIT)
756+ return (p->fts_link);
757+
758+ /*
759+ * If not a directory being visited in pre-order, stop here. Could
760+ * allow FTS_DNR, assuming the user has fixed the problem, but the
761+ * same effect is available with FTS_AGAIN.
762+ */
763+ if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
764+ return (NULL);
765+
766+ /* Free up any previous child list. */
767+ if (sp->fts_child != NULL)
768+ fts_lfree(sp->fts_child);
769+
770+ if (instr == FTS_NAMEONLY) {
771+ SET(FTS_NAMEONLY);
772+ instr = BNAMES;
773+ } else
774+ instr = BCHILD;
775+
776+ /*
777+ * If using chdir on a relative path and called BEFORE fts_read does
778+ * its chdir to the root of a traversal, we can lose -- we need to
779+ * chdir into the subdirectory, and we don't know where the current
780+ * directory is, so we can't get back so that the upcoming chdir by
781+ * fts_read will work.
782+ */
783+ if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
784+ ISSET(FTS_NOCHDIR))
785+ return (sp->fts_child = fts_build(sp, instr));
786+
787+ if ((fd = open(".", O_RDONLY, 0)) < 0)
788+ return (NULL);
789+ sp->fts_child = fts_build(sp, instr);
790+ if (fchdir(fd))
791+ return (NULL);
792+ (void)close(fd);
793+ return (sp->fts_child);
794+}
795+
796+/*
797+ * This is the tricky part -- do not casually change *anything* in here. The
798+ * idea is to build the linked list of entries that are used by fts_children
799+ * and fts_read. There are lots of special cases.
800+ *
801+ * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is
802+ * set and it's a physical walk (so that symbolic links can't be directories),
803+ * we can do things quickly. First, if it's a 4.4BSD file system, the type
804+ * of the file is in the directory entry. Otherwise, we assume that the number
805+ * of subdirectories in a node is equal to the number of links to the parent.
806+ * The former skips all stat calls. The latter skips stat calls in any leaf
807+ * directories and for any files after the subdirectories in the directory have
808+ * been found, cutting the stat calls by about 2/3.
809+ */
810+static FTSENT *
811+internal_function
812+fts_build(sp, type)
813+ register FTS *sp;
814+ int type;
815+{
816+ register struct dirent *dp;
817+ register FTSENT *p, *head;
818+ register int nitems;
819+ FTSENT *cur, *tail;
820+ DIR *dirp;
821+ void *oldaddr;
822+ int cderrno, descend, len, level, nlinks, saved_errno,
823+ nostat, doadjust;
824+ size_t maxlen;
825+ char *cp;
826+
827+ /* Set current node pointer. */
828+ cur = sp->fts_cur;
829+
830+ /*
831+ * Open the directory for reading. If this fails, we're done.
832+ * If being called from fts_read, set the fts_info field.
833+ */
834+#if defined FTS_WHITEOUT && 0
835+ if (ISSET(FTS_WHITEOUT))
836+ oflag = DTF_NODUP|DTF_REWIND;
837+ else
838+ oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
839+#else
840+# define opendir2(path, flag) opendir(path)
841+#endif
842+ if ((dirp = opendir2(cur->fts_accpath, oflag)) == NULL) {
843+ if (type == BREAD) {
844+ cur->fts_info = FTS_DNR;
845+ cur->fts_errno = errno;
846+ }
847+ return (NULL);
848+ }
849+
850+ /*
851+ * Nlinks is the number of possible entries of type directory in the
852+ * directory if we're cheating on stat calls, 0 if we're not doing
853+ * any stat calls at all, -1 if we're doing stats on everything.
854+ */
855+ if (type == BNAMES) {
856+ nlinks = 0;
857+ /* Be quiet about nostat, GCC. */
858+ nostat = 0;
859+ } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
860+ nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
861+ nostat = 1;
862+ } else {
863+ nlinks = -1;
864+ nostat = 0;
865+ }
866+
867+#ifdef notdef
868+ (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
869+ (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
870+ ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
871+#endif
872+ /*
873+ * If we're going to need to stat anything or we want to descend
874+ * and stay in the directory, chdir. If this fails we keep going,
875+ * but set a flag so we don't chdir after the post-order visit.
876+ * We won't be able to stat anything, but we can still return the
877+ * names themselves. Note, that since fts_read won't be able to
878+ * chdir into the directory, it will have to return different path
879+ * names than before, i.e. "a/b" instead of "b". Since the node
880+ * has already been visited in pre-order, have to wait until the
881+ * post-order visit to return the error. There is a special case
882+ * here, if there was nothing to stat then it's not an error to
883+ * not be able to stat. This is all fairly nasty. If a program
884+ * needed sorted entries or stat information, they had better be
885+ * checking FTS_NS on the returned nodes.
886+ */
887+ cderrno = 0;
888+ if (nlinks || type == BREAD) {
889+ if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
890+ if (nlinks && type == BREAD)
891+ cur->fts_errno = errno;
892+ cur->fts_flags |= FTS_DONTCHDIR;
893+ descend = 0;
894+ cderrno = errno;
895+ (void)closedir(dirp);
896+ dirp = NULL;
897+ } else
898+ descend = 1;
899+ } else
900+ descend = 0;
901+
902+ /*
903+ * Figure out the max file name length that can be stored in the
904+ * current path -- the inner loop allocates more path as necessary.
905+ * We really wouldn't have to do the maxlen calculations here, we
906+ * could do them in fts_read before returning the path, but it's a
907+ * lot easier here since the length is part of the dirent structure.
908+ *
909+ * If not changing directories set a pointer so that can just append
910+ * each new name into the path.
911+ */
912+ len = NAPPEND(cur);
913+ if (ISSET(FTS_NOCHDIR)) {
914+ cp = sp->fts_path + len;
915+ *cp++ = '/';
916+ } else {
917+ /* GCC, you're too verbose. */
918+ cp = NULL;
919+ }
920+ len++;
921+ maxlen = sp->fts_pathlen - len;
922+
923+ level = cur->fts_level + 1;
924+
925+ /* Read the directory, attaching each entry to the `link' pointer. */
926+ doadjust = 0;
927+ for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
928+ if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
929+ continue;
930+
931+ if ((p = fts_alloc(sp, dp->d_name, _D_EXACT_NAMLEN (dp))) == NULL)
932+ goto mem1;
933+ if (_D_EXACT_NAMLEN (dp) >= maxlen) {/* include space for NUL */
934+ oldaddr = sp->fts_path;
935+ if (fts_palloc(sp, _D_EXACT_NAMLEN (dp) + len + 1)) {
936+ /*
937+ * No more memory for path or structures. Save
938+ * errno, free up the current structure and the
939+ * structures already allocated.
940+ */
941+mem1: saved_errno = errno;
942+ free(p);
943+ fts_lfree(head);
944+ (void)closedir(dirp);
945+ cur->fts_info = FTS_ERR;
946+ SET(FTS_STOP);
947+ __set_errno (saved_errno);
948+ return (NULL);
949+ }
950+ /* Did realloc() change the pointer? */
951+ if (oldaddr != sp->fts_path) {
952+ doadjust = 1;
953+ if (ISSET(FTS_NOCHDIR))
954+ cp = sp->fts_path + len;
955+ }
956+ maxlen = sp->fts_pathlen - len;
957+ }
958+
959+ if (len + _D_EXACT_NAMLEN (dp) >= USHRT_MAX) {
960+ /*
961+ * In an FTSENT, fts_pathlen is a u_short so it is
962+ * possible to wraparound here. If we do, free up
963+ * the current structure and the structures already
964+ * allocated, then error out with ENAMETOOLONG.
965+ */
966+ free(p);
967+ fts_lfree(head);
968+ (void)closedir(dirp);
969+ cur->fts_info = FTS_ERR;
970+ SET(FTS_STOP);
971+ __set_errno (ENAMETOOLONG);
972+ return (NULL);
973+ }
974+ p->fts_level = level;
975+ p->fts_parent = sp->fts_cur;
976+ p->fts_pathlen = len + _D_EXACT_NAMLEN (dp);
977+
978+#if defined FTS_WHITEOUT && 0
979+ if (dp->d_type == DT_WHT)
980+ p->fts_flags |= FTS_ISW;
981+#endif
982+
983+#if 0
984+ /* Unreachable code. cderrno is only ever set to a nonnull
985+ value if dirp is closed at the same time. But then we
986+ cannot enter this loop. */
987+ if (cderrno) {
988+ if (nlinks) {
989+ p->fts_info = FTS_NS;
990+ p->fts_errno = cderrno;
991+ } else
992+ p->fts_info = FTS_NSOK;
993+ p->fts_accpath = cur->fts_accpath;
994+ } else
995+#endif
996+ if (nlinks == 0
997+#if defined DT_DIR && defined _DIRENT_HAVE_D_TYPE
998+ || (nostat &&
999+ dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
1000+#endif
1001+ ) {
1002+ p->fts_accpath =
1003+ ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
1004+ p->fts_info = FTS_NSOK;
1005+ } else {
1006+ /* Build a file name for fts_stat to stat. */
1007+ if (ISSET(FTS_NOCHDIR)) {
1008+ p->fts_accpath = p->fts_path;
1009+ memmove(cp, p->fts_name, p->fts_namelen + 1);
1010+ } else
1011+ p->fts_accpath = p->fts_name;
1012+ /* Stat it. */
1013+ p->fts_info = fts_stat(sp, p, 0);
1014+
1015+ /* Decrement link count if applicable. */
1016+ if (nlinks > 0 && (p->fts_info == FTS_D ||
1017+ p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
1018+ --nlinks;
1019+ }
1020+
1021+ /* We walk in directory order so "ls -f" doesn't get upset. */
1022+ p->fts_link = NULL;
1023+ if (head == NULL)
1024+ head = tail = p;
1025+ else {
1026+ tail->fts_link = p;
1027+ tail = p;
1028+ }
1029+ ++nitems;
1030+ }
1031+ if (dirp)
1032+ (void)closedir(dirp);
1033+
1034+ /*
1035+ * If realloc() changed the address of the path, adjust the
1036+ * addresses for the rest of the tree and the dir list.
1037+ */
1038+ if (doadjust)
1039+ fts_padjust(sp, head);
1040+
1041+ /*
1042+ * If not changing directories, reset the path back to original
1043+ * state.
1044+ */
1045+ if (ISSET(FTS_NOCHDIR)) {
1046+ if (len == sp->fts_pathlen || nitems == 0)
1047+ --cp;
1048+ *cp = '\0';
1049+ }
1050+
1051+ /*
1052+ * If descended after called from fts_children or after called from
1053+ * fts_read and nothing found, get back. At the root level we use
1054+ * the saved fd; if one of fts_open()'s arguments is a relative path
1055+ * to an empty directory, we wind up here with no other way back. If
1056+ * can't get back, we're done.
1057+ */
1058+ if (descend && (type == BCHILD || !nitems) &&
1059+ (cur->fts_level == FTS_ROOTLEVEL ?
1060+ FCHDIR(sp, sp->fts_rfd) :
1061+ fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
1062+ cur->fts_info = FTS_ERR;
1063+ SET(FTS_STOP);
1064+ fts_lfree(head);
1065+ return (NULL);
1066+ }
1067+
1068+ /* If didn't find anything, return NULL. */
1069+ if (!nitems) {
1070+ if (type == BREAD)
1071+ cur->fts_info = FTS_DP;
1072+ fts_lfree(head);
1073+ return (NULL);
1074+ }
1075+
1076+ /* Sort the entries. */
1077+ if (sp->fts_compar && nitems > 1)
1078+ head = fts_sort(sp, head, nitems);
1079+ return (head);
1080+}
1081+
1082+static u_short
1083+internal_function
1084+fts_stat(sp, p, follow)
1085+ FTS *sp;
1086+ register FTSENT *p;
1087+ int follow;
1088+{
1089+ register FTSENT *t;
1090+ register dev_t dev;
1091+ register ino_t ino;
1092+ struct stat *sbp, sb;
1093+ int saved_errno;
1094+
1095+ /* If user needs stat info, stat buffer already allocated. */
1096+ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
1097+
1098+#if defined FTS_WHITEOUT && 0
1099+ /* check for whiteout */
1100+ if (p->fts_flags & FTS_ISW) {
1101+ if (sbp != &sb) {
1102+ memset(sbp, '\0', sizeof (*sbp));
1103+ sbp->st_mode = S_IFWHT;
1104+ }
1105+ return (FTS_W);
1106+ }
1107+#endif
1108+
1109+ /*
1110+ * If doing a logical walk, or application requested FTS_FOLLOW, do
1111+ * a stat(2). If that fails, check for a non-existent symlink. If
1112+ * fail, set the errno from the stat call.
1113+ */
1114+ if (ISSET(FTS_LOGICAL) || follow) {
1115+ if (stat(p->fts_accpath, sbp)) {
1116+ saved_errno = errno;
1117+ if (!lstat(p->fts_accpath, sbp)) {
1118+ __set_errno (0);
1119+ return (FTS_SLNONE);
1120+ }
1121+ p->fts_errno = saved_errno;
1122+ goto err;
1123+ }
1124+ } else if (lstat(p->fts_accpath, sbp)) {
1125+ p->fts_errno = errno;
1126+err: memset(sbp, 0, sizeof(struct stat));
1127+ return (FTS_NS);
1128+ }
1129+
1130+ if (S_ISDIR(sbp->st_mode)) {
1131+ /*
1132+ * Set the device/inode. Used to find cycles and check for
1133+ * crossing mount points. Also remember the link count, used
1134+ * in fts_build to limit the number of stat calls. It is
1135+ * understood that these fields are only referenced if fts_info
1136+ * is set to FTS_D.
1137+ */
1138+ dev = p->fts_dev = sbp->st_dev;
1139+ ino = p->fts_ino = sbp->st_ino;
1140+ p->fts_nlink = sbp->st_nlink;
1141+
1142+ if (ISDOT(p->fts_name))
1143+ return (FTS_DOT);
1144+
1145+ /*
1146+ * Cycle detection is done by brute force when the directory
1147+ * is first encountered. If the tree gets deep enough or the
1148+ * number of symbolic links to directories is high enough,
1149+ * something faster might be worthwhile.
1150+ */
1151+ for (t = p->fts_parent;
1152+ t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
1153+ if (ino == t->fts_ino && dev == t->fts_dev) {
1154+ p->fts_cycle = t;
1155+ return (FTS_DC);
1156+ }
1157+ return (FTS_D);
1158+ }
1159+ if (S_ISLNK(sbp->st_mode))
1160+ return (FTS_SL);
1161+ if (S_ISREG(sbp->st_mode))
1162+ return (FTS_F);
1163+ return (FTS_DEFAULT);
1164+}
1165+
1166+static FTSENT *
1167+internal_function
1168+fts_sort(sp, head, nitems)
1169+ FTS *sp;
1170+ FTSENT *head;
1171+ register int nitems;
1172+{
1173+ register FTSENT **ap, *p;
1174+
1175+ /*
1176+ * Construct an array of pointers to the structures and call qsort(3).
1177+ * Reassemble the array in the order returned by qsort. If unable to
1178+ * sort for memory reasons, return the directory entries in their
1179+ * current order. Allocate enough space for the current needs plus
1180+ * 40 so don't realloc one entry at a time.
1181+ */
1182+ if (nitems > sp->fts_nitems) {
1183+ struct _ftsent **a;
1184+
1185+ sp->fts_nitems = nitems + 40;
1186+ if ((a = realloc(sp->fts_array,
1187+ (size_t)(sp->fts_nitems * sizeof(FTSENT *)))) == NULL) {
1188+ free(sp->fts_array);
1189+ sp->fts_array = NULL;
1190+ sp->fts_nitems = 0;
1191+ return (head);
1192+ }
1193+ sp->fts_array = a;
1194+ }
1195+ for (ap = sp->fts_array, p = head; p; p = p->fts_link)
1196+ *ap++ = p;
1197+ qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
1198+ for (head = *(ap = sp->fts_array); --nitems; ++ap)
1199+ ap[0]->fts_link = ap[1];
1200+ ap[0]->fts_link = NULL;
1201+ return (head);
1202+}
1203+
1204+static FTSENT *
1205+internal_function
1206+fts_alloc(sp, name, namelen)
1207+ FTS *sp;
1208+ const char *name;
1209+ size_t namelen;
1210+{
1211+ register FTSENT *p;
1212+ size_t len;
1213+
1214+ /*
1215+ * The file name is a variable length array and no stat structure is
1216+ * necessary if the user has set the nostat bit. Allocate the FTSENT
1217+ * structure, the file name and the stat structure in one chunk, but
1218+ * be careful that the stat structure is reasonably aligned. Since the
1219+ * fts_name field is declared to be of size 1, the fts_name pointer is
1220+ * namelen + 2 before the first possible address of the stat structure.
1221+ */
1222+ len = sizeof(FTSENT) + namelen;
1223+ if (!ISSET(FTS_NOSTAT))
1224+ len += sizeof(struct stat) + ALIGNBYTES;
1225+ if ((p = malloc(len)) == NULL)
1226+ return (NULL);
1227+
1228+ /* Copy the name and guarantee NUL termination. */
1229+ memmove(p->fts_name, name, namelen);
1230+ p->fts_name[namelen] = '\0';
1231+
1232+ if (!ISSET(FTS_NOSTAT))
1233+ p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
1234+ p->fts_namelen = namelen;
1235+ p->fts_path = sp->fts_path;
1236+ p->fts_errno = 0;
1237+ p->fts_flags = 0;
1238+ p->fts_instr = FTS_NOINSTR;
1239+ p->fts_number = 0;
1240+ p->fts_pointer = NULL;
1241+ return (p);
1242+}
1243+
1244+static void
1245+internal_function
1246+fts_lfree(head)
1247+ register FTSENT *head;
1248+{
1249+ register FTSENT *p;
1250+
1251+ /* Free a linked list of structures. */
1252+ while ((p = head)) {
1253+ head = head->fts_link;
1254+ free(p);
1255+ }
1256+}
1257+
1258+/*
1259+ * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
1260+ * Most systems will allow creation of paths much longer than MAXPATHLEN, even
1261+ * though the kernel won't resolve them. Add the size (not just what's needed)
1262+ * plus 256 bytes so don't realloc the path 2 bytes at a time.
1263+ */
1264+static int
1265+internal_function
1266+fts_palloc(sp, more)
1267+ FTS *sp;
1268+ size_t more;
1269+{
1270+ char *p;
1271+
1272+ sp->fts_pathlen += more + 256;
1273+ /*
1274+ * Check for possible wraparound. In an FTS, fts_pathlen is
1275+ * a signed int but in an FTSENT it is an unsigned short.
1276+ * We limit fts_pathlen to USHRT_MAX to be safe in both cases.
1277+ */
1278+ if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) {
1279+ free(sp->fts_path);
1280+ sp->fts_path = NULL;
1281+ __set_errno (ENAMETOOLONG);
1282+ return (1);
1283+ }
1284+ p = realloc(sp->fts_path, sp->fts_pathlen);
1285+ if (p == NULL) {
1286+ free(sp->fts_path);
1287+ sp->fts_path = NULL;
1288+ return 1;
1289+ }
1290+ sp->fts_path = p;
1291+ return 0;
1292+}
1293+
1294+/*
1295+ * When the path is realloc'd, have to fix all of the pointers in structures
1296+ * already returned.
1297+ */
1298+static void
1299+internal_function
1300+fts_padjust(sp, head)
1301+ FTS *sp;
1302+ FTSENT *head;
1303+{
1304+ FTSENT *p;
1305+ char *addr = sp->fts_path;
1306+
1307+#define ADJUST(p) do { \
1308+ if ((p)->fts_accpath != (p)->fts_name) { \
1309+ (p)->fts_accpath = \
1310+ (char *)addr + ((p)->fts_accpath - (p)->fts_path); \
1311+ } \
1312+ (p)->fts_path = addr; \
1313+} while (0)
1314+ /* Adjust the current set of children. */
1315+ for (p = sp->fts_child; p; p = p->fts_link)
1316+ ADJUST(p);
1317+
1318+ /* Adjust the rest of the tree, including the current level. */
1319+ for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
1320+ ADJUST(p);
1321+ p = p->fts_link ? p->fts_link : p->fts_parent;
1322+ }
1323+}
1324+
1325+static size_t
1326+internal_function
1327+fts_maxarglen(argv)
1328+ char * const *argv;
1329+{
1330+ size_t len, max;
1331+
1332+ for (max = 0; *argv; ++argv)
1333+ if ((len = strlen(*argv)) > max)
1334+ max = len;
1335+ return (max + 1);
1336+}
1337+
1338+/*
1339+ * Change to dir specified by fd or p->fts_accpath without getting
1340+ * tricked by someone changing the world out from underneath us.
1341+ * Assumes p->fts_dev and p->fts_ino are filled in.
1342+ */
1343+static int
1344+internal_function
1345+fts_safe_changedir(sp, p, fd, path)
1346+ FTS *sp;
1347+ FTSENT *p;
1348+ int fd;
1349+ const char *path;
1350+{
1351+ int ret, oerrno, newfd;
1352+ struct stat64 sb;
1353+
1354+ newfd = fd;
1355+ if (ISSET(FTS_NOCHDIR))
1356+ return (0);
1357+ if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0)
1358+ return (-1);
1359+ if (fstat64(newfd, &sb)) {
1360+ ret = -1;
1361+ goto bail;
1362+ }
1363+ if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
1364+ __set_errno (ENOENT); /* disinformation */
1365+ ret = -1;
1366+ goto bail;
1367+ }
1368+ ret = fchdir(newfd);
1369+bail:
1370+ oerrno = errno;
1371+ if (fd < 0)
1372+ (void)close(newfd);
1373+ __set_errno (oerrno);
1374+ return (ret);
1375+}
diff --git a/meta-oe/recipes-core/uclibc/uclibc-git/uClibc.distro b/meta-oe/recipes-core/uclibc/uclibc-git/uClibc.distro
index e25324d3d1..a1b7813a0b 100644
--- a/meta-oe/recipes-core/uclibc/uclibc-git/uClibc.distro
+++ b/meta-oe/recipes-core/uclibc/uclibc-git/uClibc.distro
@@ -147,6 +147,7 @@ UCLIBC_EXTRA_CFLAGS=""
147# SUPPORT_LD_DEBUG is not set 147# SUPPORT_LD_DEBUG is not set
148# SUPPORT_LD_DEBUG_EARLY is not set 148# SUPPORT_LD_DEBUG_EARLY is not set
149# UCLIBC_MALLOC_DEBUGGING is not set 149# UCLIBC_MALLOC_DEBUGGING is not set
150UCLIBC_HAS_BACKTRACE=y
150WARNINGS="-Wall" 151WARNINGS="-Wall"
151# EXTRA_WARNINGS is not set 152# EXTRA_WARNINGS is not set
152# DOMULTI is not set 153# DOMULTI is not set
@@ -155,3 +156,5 @@ WARNINGS="-Wall"
155# math stuff for perl 156# math stuff for perl
156DO_C99_MATH=y 157DO_C99_MATH=y
157UCLIBC_HAS_LONG_DOUBLE_MATH=y 158UCLIBC_HAS_LONG_DOUBLE_MATH=y
159UCLIBC_HAS_FENV=y
160
diff --git a/meta-oe/recipes-core/uclibc/uclibc_git.bb b/meta-oe/recipes-core/uclibc/uclibc_git.bb
index cba7e03c3e..3719ea24d9 100644
--- a/meta-oe/recipes-core/uclibc/uclibc_git.bb
+++ b/meta-oe/recipes-core/uclibc/uclibc_git.bb
@@ -7,7 +7,7 @@
7# on whether the base patches apply to the selected (SRCDATE) svn release. 7# on whether the base patches apply to the selected (SRCDATE) svn release.
8# 8#
9UCLIBC_BASE ?= "0.9.32" 9UCLIBC_BASE ?= "0.9.32"
10SRCREV="251f2266bf24b1b396f59eef60d0acf41fdd02e4" 10SRCREV="074930dd7f2a18a7013cdb72cc38136f3be39c40"
11PR_append = "+gitr${SRCPV}" 11PR_append = "+gitr${SRCPV}"
12 12
13require uclibc.inc 13require uclibc.inc
@@ -36,7 +36,6 @@ SRC_URI = "git://uclibc.org/uClibc.git;branch=master;protocol=git \
36 file://detect-bx-availibility.patch \ 36 file://detect-bx-availibility.patch \
37 file://remove-eabi-oabi-selection.patch \ 37 file://remove-eabi-oabi-selection.patch \
38 file://powerpc_copysignl.patch \ 38 file://powerpc_copysignl.patch \
39 file://fts-support.patch \
40 file://argp-support.patch \ 39 file://argp-support.patch \
41 file://argp-headers.patch \ 40 file://argp-headers.patch \
42 file://remove_attribute_optimize_Os.patch \ 41 file://remove_attribute_optimize_Os.patch \