source: trunk/essentials/sys-apps/findutils/gnulib/lib/fts.c

Last change on this file was 3179, checked in by bird, 18 years ago

Why can't these guys just use the libc fts when present. crap.

File size: 46.9 KB
Line 
1/* Traverse a file hierarchy.
2
3 Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/*-
20 * Copyright (c) 1990, 1993, 1994
21 * The Regents of the University of California. All rights reserved.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 4. Neither the name of the University nor the names of its contributors
32 * may be used to endorse or promote products derived from this software
33 * without specific prior written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 */
47
48#include <config.h>
49
50#if defined(LIBC_SCCS) && !defined(lint)
51static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
52#endif /* LIBC_SCCS and not lint */
53
54#include "fts_.h"
55
56#if HAVE_SYS_PARAM_H || defined _LIBC
57# include <sys/param.h>
58#endif
59#ifdef _LIBC
60# include <include/sys/stat.h>
61#else
62# include <sys/stat.h>
63#endif
64#include <fcntl.h>
65#include <errno.h>
66#include "dirfd.h"
67#include <stdbool.h>
68#include <stdlib.h>
69#include <string.h>
70#include <unistd.h>
71
72#if ! _LIBC
73# include "fcntl--.h"
74# include "lstat.h"
75# include "openat.h"
76# include "unistd--.h"
77# include "same-inode.h"
78#endif
79
80# if defined(__OS2__) || defined(__NT__) || defined(__WIN__)
81# define NEED_STRRSLASH 1
82# define IS_SLASH(ch) ( (ch) == '/' || (ch) == '\\' )
83#else
84# define IS_SLASH(ch) ( (ch) == '/' )
85#endif
86
87
88#include <dirent.h>
89#ifndef _D_EXACT_NAMLEN
90# define _D_EXACT_NAMLEN(dirent) strlen ((dirent)->d_name)
91#endif
92
93#if HAVE_STRUCT_DIRENT_D_TYPE
94/* True if the type of the directory entry D is known. */
95# define DT_IS_KNOWN(d) ((d)->d_type != DT_UNKNOWN)
96/* True if the type of the directory entry D must be T. */
97# define DT_MUST_BE(d, t) ((d)->d_type == (t))
98#else
99# define DT_IS_KNOWN(d) false
100# define DT_MUST_BE(d, t) false
101#endif
102
103enum Fts_stat
104{
105 FTS_NO_STAT_REQUIRED = 1,
106 FTS_STAT_REQUIRED = 2
107};
108
109#ifdef _LIBC
110# undef close
111# define close __close
112# undef closedir
113# define closedir __closedir
114# undef fchdir
115# define fchdir __fchdir
116# undef open
117# define open __open
118# undef opendir
119# define opendir __opendir
120# undef readdir
121# define readdir __readdir
122#else
123# undef internal_function
124# define internal_function /* empty */
125#endif
126
127#ifndef __set_errno
128# define __set_errno(Val) errno = (Val)
129#endif
130
131#ifndef __attribute__
132# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
133# define __attribute__(x) /* empty */
134# endif
135#endif
136
137#ifndef ATTRIBUTE_UNUSED
138# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
139#endif
140
141/* If this host provides the openat function, then we can avoid
142 attempting to open "." in some initialization code below. */
143#ifdef HAVE_OPENAT
144# define HAVE_OPENAT_SUPPORT 1
145#else
146# define HAVE_OPENAT_SUPPORT 0
147#endif
148
149static FTSENT *fts_alloc (FTS *, const char *, size_t) internal_function;
150static FTSENT *fts_build (FTS *, int) internal_function;
151static void fts_lfree (FTSENT *) internal_function;
152static void fts_load (FTS *, FTSENT *) internal_function;
153static size_t fts_maxarglen (char * const *) internal_function;
154static void fts_padjust (FTS *, FTSENT *) internal_function;
155static bool fts_palloc (FTS *, size_t) internal_function;
156static FTSENT *fts_sort (FTS *, FTSENT *, size_t) internal_function;
157static unsigned short int fts_stat (FTS *, FTSENT *, bool) internal_function;
158static int fts_safe_changedir (FTS *, FTSENT *, int, const char *)
159 internal_function;
160
161#if _LGPL_PACKAGE
162static bool enter_dir (FTS *fts, FTSENT *ent) { return true; }
163static void leave_dir (FTS *fts, FTSENT *ent) {}
164static bool setup_dir (FTS *fts) { return true; }
165static void free_dir (FTS *fts) {}
166#else
167# include "fts-cycle.c"
168#endif
169
170#ifndef MAX
171# define MAX(a,b) ((a) > (b) ? (a) : (b))
172#endif
173
174#ifndef SIZE_MAX
175# define SIZE_MAX ((size_t) -1)
176#endif
177
178#ifndef O_DIRECTORY
179# define O_DIRECTORY 0
180#endif
181
182#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
183#define STREQ(a, b) (strcmp ((a), (b)) == 0)
184
185#define CLR(opt) (sp->fts_options &= ~(opt))
186#define ISSET(opt) (sp->fts_options & (opt))
187#define SET(opt) (sp->fts_options |= (opt))
188
189/* FIXME: make this a function */
190#define RESTORE_INITIAL_CWD(sp) \
191 (fd_ring_clear (&((sp)->fts_fd_ring)), \
192 FCHDIR ((sp), (ISSET (FTS_CWDFD) ? AT_FDCWD : (sp)->fts_rfd)))
193
194/* FIXME: FTS_NOCHDIR is now misnamed.
195 Call it FTS_USE_FULL_RELATIVE_FILE_NAMES instead. */
196#define FCHDIR(sp, fd) \
197 (!ISSET(FTS_NOCHDIR) && (ISSET(FTS_CWDFD) \
198 ? (cwd_advance_fd ((sp), (fd), true), 0) \
199 : fchdir (fd)))
200
201
202/* fts_build flags */
203/* FIXME: make this an enum */
204#define BCHILD 1 /* fts_children */
205#define BNAMES 2 /* fts_children, names only */
206#define BREAD 3 /* fts_read */
207
208#if FTS_DEBUG
209# include <inttypes.h>
210# include <stdint.h>
211# include <stdio.h>
212# include "getcwdat.h"
213bool fts_debug = false;
214# define Dprintf(x) do { if (fts_debug) printf x; } while (false)
215#else
216# define Dprintf(x)
217# define fd_ring_check(x)
218# define fd_ring_print(a, b, c)
219#endif
220
221#define LEAVE_DIR(Fts, Ent, Tag) \
222 do \
223 { \
224 Dprintf ((" %s-leaving: %s\n", Tag, (Ent)->fts_path)); \
225 leave_dir (Fts, Ent); \
226 fd_ring_check (Fts); \
227 } \
228 while (false)
229
230static void
231fd_ring_clear (I_ring *fd_ring)
232{
233 while ( ! i_ring_empty (fd_ring))
234 {
235 int fd = i_ring_pop (fd_ring);
236 if (0 <= fd)
237 close (fd);
238 }
239}
240
241/* Overload the fts_statp->st_size member (otherwise unused, when
242 fts_info is FTS_NSOK) to indicate whether fts_read should stat
243 this entry or not. */
244static void
245fts_set_stat_required (FTSENT *p, bool required)
246{
247 if (p->fts_info != FTS_NSOK)
248 abort ();
249 p->fts_statp->st_size = (required
250 ? FTS_STAT_REQUIRED
251 : FTS_NO_STAT_REQUIRED);
252}
253
254/* file-descriptor-relative opendir. */
255/* FIXME: if others need this function, move it into lib/openat.c */
256static inline DIR *
257internal_function
258opendirat (int fd, char const *dir)
259{
260 int new_fd = openat (fd, dir, O_RDONLY);
261 DIR *dirp;
262
263 if (new_fd < 0)
264 return NULL;
265 dirp = fdopendir (new_fd);
266 if (dirp == NULL)
267 {
268 int saved_errno = errno;
269 close (new_fd);
270 errno = saved_errno;
271 }
272 return dirp;
273}
274
275/* Virtual fchdir. Advance SP's working directory file descriptor,
276 SP->fts_cwd_fd, to FD, and push the previous value onto the fd_ring.
277 CHDIR_DOWN_ONE is true if FD corresponds to an entry in the directory
278 open on sp->fts_cwd_fd; i.e., to move the working directory one level
279 down. */
280static void
281internal_function
282cwd_advance_fd (FTS *sp, int fd, bool chdir_down_one)
283{
284 int old = sp->fts_cwd_fd;
285 if (old == fd && old != AT_FDCWD)
286 abort ();
287
288 if (chdir_down_one)
289 {
290 /* Push "old" onto the ring.
291 If the displaced file descriptor is non-negative, close it. */
292 int prev_fd_in_slot = i_ring_push (&sp->fts_fd_ring, old);
293 fd_ring_print (sp, stderr, "post-push");
294 if (0 <= prev_fd_in_slot)
295 close (prev_fd_in_slot); /* ignore any close failure */
296 }
297 else if ( ! ISSET (FTS_NOCHDIR))
298 {
299 if (0 <= old)
300 close (old); /* ignore any close failure */
301 }
302
303 sp->fts_cwd_fd = fd;
304}
305
306/* Open the directory DIR if possible, and return a file
307 descriptor. Return -1 and set errno on failure. It doesn't matter
308 whether the file descriptor has read or write access. */
309
310static inline int
311internal_function
312diropen (FTS const *sp, char const *dir)
313{
314 int open_flags = (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
315 | (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0));
316
317 return (ISSET (FTS_CWDFD)
318 ? openat (sp->fts_cwd_fd, dir, open_flags)
319 : open (dir, open_flags));
320}
321
322FTS *
323fts_open (char * const *argv,
324 register int options,
325 int (*compar) (FTSENT const **, FTSENT const **))
326{
327 register FTS *sp;
328 register FTSENT *p, *root;
329 register size_t nitems;
330 FTSENT *parent = NULL;
331 FTSENT *tmp = NULL; /* pacify gcc */
332 size_t len;
333 bool defer_stat;
334
335 /* Options check. */
336 if (options & ~FTS_OPTIONMASK) {
337 __set_errno (EINVAL);
338 return (NULL);
339 }
340 if ((options & FTS_NOCHDIR) && (options & FTS_CWDFD)) {
341 __set_errno (EINVAL);
342 return (NULL);
343 }
344 if ( ! (options & (FTS_LOGICAL | FTS_PHYSICAL))) {
345 __set_errno (EINVAL);
346 return (NULL);
347 }
348
349 /* Allocate/initialize the stream */
350 if ((sp = malloc(sizeof(FTS))) == NULL)
351 return (NULL);
352 memset(sp, 0, sizeof(FTS));
353 sp->fts_compar = compar;
354 sp->fts_options = options;
355
356 /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
357 if (ISSET(FTS_LOGICAL)) {
358 SET(FTS_NOCHDIR);
359 CLR(FTS_CWDFD);
360 }
361
362 /* Initialize fts_cwd_fd. */
363 sp->fts_cwd_fd = AT_FDCWD;
364 if ( ISSET(FTS_CWDFD) && ! HAVE_OPENAT_SUPPORT)
365 {
366 /* While it isn't technically necessary to open "." this
367 early, doing it here saves us the trouble of ensuring
368 later (where it'd be messier) that "." can in fact
369 be opened. If not, revert to FTS_NOCHDIR mode. */
370 int fd = open (".", O_RDONLY);
371 if (fd < 0)
372 {
373 /* Even if `.' is unreadable, don't revert to FTS_NOCHDIR mode
374 on systems like Linux+PROC_FS, where our openat emulation
375 is good enough. Note: on a system that emulates
376 openat via /proc, this technique can still fail, but
377 only in extreme conditions, e.g., when the working
378 directory cannot be saved (i.e. save_cwd fails) --
379 and that happens on Linux only when "." is unreadable
380 and the CWD would be longer than PATH_MAX.
381 FIXME: once Linux kernel openat support is well established,
382 replace the above open call and this entire if/else block
383 with the body of the if-block below. */
384 if ( openat_needs_fchdir ())
385 {
386 SET(FTS_NOCHDIR);
387 CLR(FTS_CWDFD);
388 }
389 }
390 else
391 {
392 close (fd);
393 }
394 }
395
396 /*
397 * Start out with 1K of file name space, and enough, in any case,
398 * to hold the user's file names.
399 */
400#ifndef MAXPATHLEN
401# define MAXPATHLEN 1024
402#endif
403 {
404 size_t maxarglen = fts_maxarglen(argv);
405 if (! fts_palloc(sp, MAX(maxarglen, MAXPATHLEN)))
406 goto mem1;
407 }
408
409 /* Allocate/initialize root's parent. */
410 if (*argv != NULL) {
411 if ((parent = fts_alloc(sp, "", 0)) == NULL)
412 goto mem2;
413 parent->fts_level = FTS_ROOTPARENTLEVEL;
414 }
415
416 /* The classic fts implementation would call fts_stat with
417 a new entry for each iteration of the loop below.
418 If the comparison function is not specified or if the
419 FTS_DEFER_STAT option is in effect, don't stat any entry
420 in this loop. This is an attempt to minimize the interval
421 between the initial stat/lstat/fstatat and the point at which
422 a directory argument is first opened. This matters for any
423 directory command line argument that resides on a file system
424 without genuine i-nodes. If you specify FTS_DEFER_STAT along
425 with a comparison function, that function must not access any
426 data via the fts_statp pointer. */
427 defer_stat = (compar == NULL || ISSET(FTS_DEFER_STAT));
428
429 /* Allocate/initialize root(s). */
430 for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
431 /* Don't allow zero-length file names. */
432 if ((len = strlen(*argv)) == 0) {
433 __set_errno (ENOENT);
434 goto mem3;
435 }
436
437 if ((p = fts_alloc(sp, *argv, len)) == NULL)
438 goto mem3;
439 p->fts_level = FTS_ROOTLEVEL;
440 p->fts_parent = parent;
441 p->fts_accpath = p->fts_name;
442 /* Even when defer_stat is true, be sure to stat the first
443 command line argument, since fts_read (at least with
444 FTS_XDEV) requires that. */
445 if (defer_stat && root != NULL) {
446 p->fts_info = FTS_NSOK;
447 fts_set_stat_required(p, true);
448 } else {
449 p->fts_info = fts_stat(sp, p, false);
450 }
451
452 /*
453 * If comparison routine supplied, traverse in sorted
454 * order; otherwise traverse in the order specified.
455 */
456 if (compar) {
457 p->fts_link = root;
458 root = p;
459 } else {
460 p->fts_link = NULL;
461 if (root == NULL)
462 tmp = root = p;
463 else {
464 tmp->fts_link = p;
465 tmp = p;
466 }
467 }
468 }
469 if (compar && nitems > 1)
470 root = fts_sort(sp, root, nitems);
471
472 /*
473 * Allocate a dummy pointer and make fts_read think that we've just
474 * finished the node before the root(s); set p->fts_info to FTS_INIT
475 * so that everything about the "current" node is ignored.
476 */
477 if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
478 goto mem3;
479 sp->fts_cur->fts_link = root;
480 sp->fts_cur->fts_info = FTS_INIT;
481 if (! setup_dir (sp))
482 goto mem3;
483
484 /*
485 * If using chdir(2), grab a file descriptor pointing to dot to ensure
486 * that we can get back here; this could be avoided for some file names,
487 * but almost certainly not worth the effort. Slashes, symbolic links,
488 * and ".." are all fairly nasty problems. Note, if we can't get the
489 * descriptor we run anyway, just more slowly.
490 */
491 if (!ISSET(FTS_NOCHDIR) && !ISSET(FTS_CWDFD)
492 && (sp->fts_rfd = diropen (sp, ".")) < 0)
493 SET(FTS_NOCHDIR);
494
495 i_ring_init (&sp->fts_fd_ring, -1);
496 return (sp);
497
498mem3: fts_lfree(root);
499 free(parent);
500mem2: free(sp->fts_path);
501mem1: free(sp);
502 return (NULL);
503}
504
505#ifdef NEED_STRRSLASH
506static char *strrslash(register char *psz)
507{
508 register char ch;
509 char *pszLast = NULL;
510 for (; (ch = *psz); psz++)
511 switch (ch)
512 {
513 case '/':
514 case '\\':
515 case ':':
516 pszLast = psz;
517 break;
518 }
519 return pszLast;
520}
521#endif
522
523static void
524internal_function
525fts_load (FTS *sp, register FTSENT *p)
526{
527 register size_t len;
528 register char *cp;
529
530 /*
531 * Load the stream structure for the next traversal. Since we don't
532 * actually enter the directory until after the preorder visit, set
533 * the fts_accpath field specially so the chdir gets done to the right
534 * place and the user can access the first node. From fts_open it's
535 * known that the file name will fit.
536 */
537 len = p->fts_pathlen = p->fts_namelen;
538 memmove(sp->fts_path, p->fts_name, len + 1);
539#ifdef NEED_STRRSLASH
540 if ((cp = strrslash(p->fts_name)) && (cp != p->fts_name || cp[1])) {
541#else
542 if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
543#endif
544 len = strlen(++cp);
545 memmove(p->fts_name, cp, len + 1);
546 p->fts_namelen = len;
547 }
548 p->fts_accpath = p->fts_path = sp->fts_path;
549 sp->fts_dev = p->fts_statp->st_dev;
550}
551
552int
553fts_close (FTS *sp)
554{
555 register FTSENT *freep, *p;
556 int saved_errno = 0;
557
558 /*
559 * This still works if we haven't read anything -- the dummy structure
560 * points to the root list, so we step through to the end of the root
561 * list which has a valid parent pointer.
562 */
563 if (sp->fts_cur) {
564 for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
565 freep = p;
566 p = p->fts_link != NULL ? p->fts_link : p->fts_parent;
567 free(freep);
568 }
569 free(p);
570 }
571
572 /* Free up child linked list, sort array, file name buffer. */
573 if (sp->fts_child)
574 fts_lfree(sp->fts_child);
575 free(sp->fts_array);
576 free(sp->fts_path);
577
578 if (ISSET(FTS_CWDFD))
579 {
580 if (0 <= sp->fts_cwd_fd)
581 close (sp->fts_cwd_fd);
582 }
583 else if (!ISSET(FTS_NOCHDIR))
584 {
585 /* Return to original directory, save errno if necessary. */
586 if (fchdir(sp->fts_rfd))
587 saved_errno = errno;
588 close(sp->fts_rfd);
589 }
590
591 fd_ring_clear (&sp->fts_fd_ring);
592 free_dir (sp);
593
594 /* Free up the stream pointer. */
595 free(sp);
596
597 /* Set errno and return. */
598 if (saved_errno) {
599 __set_errno (saved_errno);
600 return (-1);
601 }
602
603 return (0);
604}
605
606/*
607 * Special case of "/" at the end of the file name so that slashes aren't
608 * appended which would cause file names to be written as "....//foo".
609 */
610#define NAPPEND(p) \
611 (IS_SLASH(p->fts_path[p->fts_pathlen - 1]) \
612 ? p->fts_pathlen - 1 : p->fts_pathlen)
613
614FTSENT *
615fts_read (register FTS *sp)
616{
617 register FTSENT *p, *tmp;
618 register unsigned short int instr;
619 register char *t;
620
621 /* If finished or unrecoverable error, return NULL. */
622 if (sp->fts_cur == NULL || ISSET(FTS_STOP))
623 return (NULL);
624
625 /* Set current node pointer. */
626 p = sp->fts_cur;
627
628 /* Save and zero out user instructions. */
629 instr = p->fts_instr;
630 p->fts_instr = FTS_NOINSTR;
631
632 /* Any type of file may be re-visited; re-stat and re-turn. */
633 if (instr == FTS_AGAIN) {
634 p->fts_info = fts_stat(sp, p, false);
635 return (p);
636 }
637 Dprintf (("fts_read: p=%s\n",
638 p->fts_info == FTS_INIT ? "" : p->fts_path));
639
640 /*
641 * Following a symlink -- SLNONE test allows application to see
642 * SLNONE and recover. If indirecting through a symlink, have
643 * keep a pointer to current location. If unable to get that
644 * pointer, follow fails.
645 */
646 if (instr == FTS_FOLLOW &&
647 (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
648 p->fts_info = fts_stat(sp, p, true);
649 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
650 if ((p->fts_symfd = diropen (sp, ".")) < 0) {
651 p->fts_errno = errno;
652 p->fts_info = FTS_ERR;
653 } else
654 p->fts_flags |= FTS_SYMFOLLOW;
655 }
656 goto check_for_dir;
657 }
658
659 /* Directory in pre-order. */
660 if (p->fts_info == FTS_D) {
661 /* If skipped or crossed mount point, do post-order visit. */
662 if (instr == FTS_SKIP ||
663 (ISSET(FTS_XDEV) && p->fts_statp->st_dev != sp->fts_dev)) {
664 if (p->fts_flags & FTS_SYMFOLLOW)
665 (void)close(p->fts_symfd);
666 if (sp->fts_child) {
667 fts_lfree(sp->fts_child);
668 sp->fts_child = NULL;
669 }
670 p->fts_info = FTS_DP;
671 LEAVE_DIR (sp, p, "1");
672 return (p);
673 }
674
675 /* Rebuild if only read the names and now traversing. */
676 if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {
677 CLR(FTS_NAMEONLY);
678 fts_lfree(sp->fts_child);
679 sp->fts_child = NULL;
680 }
681
682 /*
683 * Cd to the subdirectory.
684 *
685 * If have already read and now fail to chdir, whack the list
686 * to make the names come out right, and set the parent errno
687 * so the application will eventually get an error condition.
688 * Set the FTS_DONTCHDIR flag so that when we logically change
689 * directories back to the parent we don't do a chdir.
690 *
691 * If haven't read do so. If the read fails, fts_build sets
692 * FTS_STOP or the fts_info field of the node.
693 */
694 if (sp->fts_child != NULL) {
695 if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
696 p->fts_errno = errno;
697 p->fts_flags |= FTS_DONTCHDIR;
698 for (p = sp->fts_child; p != NULL;
699 p = p->fts_link)
700 p->fts_accpath =
701 p->fts_parent->fts_accpath;
702 }
703 } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
704 if (ISSET(FTS_STOP))
705 return (NULL);
706 /* If fts_build's call to fts_safe_changedir failed
707 because it was not able to fchdir into a
708 subdirectory, tell the caller. */
709 if (p->fts_errno)
710 p->fts_info = FTS_ERR;
711 LEAVE_DIR (sp, p, "2");
712 return (p);
713 }
714 p = sp->fts_child;
715 sp->fts_child = NULL;
716 goto name;
717 }
718
719 /* Move to the next node on this level. */
720next: tmp = p;
721 if ((p = p->fts_link) != NULL) {
722 free(tmp);
723
724 /*
725 * If reached the top, return to the original directory (or
726 * the root of the tree), and load the file names for the next
727 * root.
728 */
729 if (p->fts_level == FTS_ROOTLEVEL) {
730 if (RESTORE_INITIAL_CWD(sp)) {
731 SET(FTS_STOP);
732 sp->fts_cur = p;
733 return (NULL);
734 }
735 fts_load(sp, p);
736 goto check_for_dir;
737 }
738
739 /*
740 * User may have called fts_set on the node. If skipped,
741 * ignore. If followed, get a file descriptor so we can
742 * get back if necessary.
743 */
744 if (p->fts_instr == FTS_SKIP)
745 goto next;
746 if (p->fts_instr == FTS_FOLLOW) {
747 p->fts_info = fts_stat(sp, p, true);
748 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
749 if ((p->fts_symfd = diropen (sp, ".")) < 0) {
750 p->fts_errno = errno;
751 p->fts_info = FTS_ERR;
752 } else
753 p->fts_flags |= FTS_SYMFOLLOW;
754 }
755 p->fts_instr = FTS_NOINSTR;
756 }
757
758name: t = sp->fts_path + NAPPEND(p->fts_parent);
759 *t++ = '/';
760 memmove(t, p->fts_name, p->fts_namelen + 1);
761check_for_dir:
762 if (p->fts_info == FTS_NSOK)
763 {
764 enum Fts_stat need_stat = p->fts_statp->st_size;
765 switch (need_stat)
766 {
767 case FTS_STAT_REQUIRED:
768 p->fts_info = fts_stat(sp, p, false);
769 break;
770 case FTS_NO_STAT_REQUIRED:
771 break;
772 default:
773 abort ();
774 }
775 }
776 sp->fts_cur = p;
777 if (p->fts_info == FTS_D)
778 {
779 Dprintf ((" entering: %s\n", p->fts_path));
780 if (! enter_dir (sp, p))
781 {
782 __set_errno (ENOMEM);
783 return NULL;
784 }
785 }
786 return p;
787 }
788
789 /* Move up to the parent node. */
790 p = tmp->fts_parent;
791 free(tmp);
792
793 if (p->fts_level == FTS_ROOTPARENTLEVEL) {
794 /*
795 * Done; free everything up and set errno to 0 so the user
796 * can distinguish between error and EOF.
797 */
798 free(p);
799 __set_errno (0);
800 return (sp->fts_cur = NULL);
801 }
802
803 if (p->fts_info == FTS_NSOK)
804 abort ();
805
806 /* NUL terminate the file name. */
807 sp->fts_path[p->fts_pathlen] = '\0';
808
809 /*
810 * Return to the parent directory. If at a root node, restore
811 * the initial working directory. If we came through a symlink,
812 * go back through the file descriptor. Otherwise, move up
813 * one level, via "..".
814 */
815 if (p->fts_level == FTS_ROOTLEVEL) {
816 if (RESTORE_INITIAL_CWD(sp)) {
817 p->fts_errno = errno;
818 SET(FTS_STOP);
819 }
820 } else if (p->fts_flags & FTS_SYMFOLLOW) {
821 if (FCHDIR(sp, p->fts_symfd)) {
822 int saved_errno = errno;
823 (void)close(p->fts_symfd);
824 __set_errno (saved_errno);
825 p->fts_errno = errno;
826 SET(FTS_STOP);
827 }
828 (void)close(p->fts_symfd);
829 } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
830 fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
831 p->fts_errno = errno;
832 SET(FTS_STOP);
833 }
834 p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
835 if (p->fts_errno == 0)
836 LEAVE_DIR (sp, p, "3");
837 sp->fts_cur = p;
838 return ISSET(FTS_STOP) ? NULL : p;
839}
840
841/*
842 * Fts_set takes the stream as an argument although it's not used in this
843 * implementation; it would be necessary if anyone wanted to add global
844 * semantics to fts using fts_set. An error return is allowed for similar
845 * reasons.
846 */
847/* ARGSUSED */
848int
849fts_set(FTS *sp ATTRIBUTE_UNUSED, FTSENT *p, int instr)
850{
851 if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
852 instr != FTS_NOINSTR && instr != FTS_SKIP) {
853 __set_errno (EINVAL);
854 return (1);
855 }
856 p->fts_instr = instr;
857 return (0);
858}
859
860FTSENT *
861fts_children (register FTS *sp, int instr)
862{
863 register FTSENT *p;
864 int fd;
865
866 if (instr != 0 && instr != FTS_NAMEONLY) {
867 __set_errno (EINVAL);
868 return (NULL);
869 }
870
871 /* Set current node pointer. */
872 p = sp->fts_cur;
873
874 /*
875 * Errno set to 0 so user can distinguish empty directory from
876 * an error.
877 */
878 __set_errno (0);
879
880 /* Fatal errors stop here. */
881 if (ISSET(FTS_STOP))
882 return (NULL);
883
884 /* Return logical hierarchy of user's arguments. */
885 if (p->fts_info == FTS_INIT)
886 return (p->fts_link);
887
888 /*
889 * If not a directory being visited in pre-order, stop here. Could
890 * allow FTS_DNR, assuming the user has fixed the problem, but the
891 * same effect is available with FTS_AGAIN.
892 */
893 if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
894 return (NULL);
895
896 /* Free up any previous child list. */
897 if (sp->fts_child != NULL)
898 fts_lfree(sp->fts_child);
899
900 if (instr == FTS_NAMEONLY) {
901 SET(FTS_NAMEONLY);
902 instr = BNAMES;
903 } else
904 instr = BCHILD;
905
906 /*
907 * If using chdir on a relative file name and called BEFORE fts_read
908 * does its chdir to the root of a traversal, we can lose -- we need to
909 * chdir into the subdirectory, and we don't know where the current
910 * directory is, so we can't get back so that the upcoming chdir by
911 * fts_read will work.
912 */
913 if (p->fts_level != FTS_ROOTLEVEL || IS_SLASH(p->fts_accpath[0]) ||
914 ISSET(FTS_NOCHDIR))
915 return (sp->fts_child = fts_build(sp, instr));
916
917 if ((fd = diropen (sp, ".")) < 0)
918 return (sp->fts_child = NULL);
919 sp->fts_child = fts_build(sp, instr);
920 if (ISSET(FTS_CWDFD))
921 {
922 cwd_advance_fd (sp, fd, true);
923 }
924 else
925 {
926 if (fchdir(fd))
927 {
928 int saved_errno = errno;
929 close (fd);
930 __set_errno (saved_errno);
931 return NULL;
932 }
933 close (fd);
934 }
935 return (sp->fts_child);
936}
937
938/*
939 * This is the tricky part -- do not casually change *anything* in here. The
940 * idea is to build the linked list of entries that are used by fts_children
941 * and fts_read. There are lots of special cases.
942 *
943 * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is
944 * set and it's a physical walk (so that symbolic links can't be directories),
945 * we can do things quickly. First, if it's a 4.4BSD file system, the type
946 * of the file is in the directory entry. Otherwise, we assume that the number
947 * of subdirectories in a node is equal to the number of links to the parent.
948 * The former skips all stat calls. The latter skips stat calls in any leaf
949 * directories and for any files after the subdirectories in the directory have
950 * been found, cutting the stat calls by about 2/3.
951 */
952static FTSENT *
953internal_function
954fts_build (register FTS *sp, int type)
955{
956 register struct dirent *dp;
957 register FTSENT *p, *head;
958 register size_t nitems;
959 FTSENT *cur, *tail;
960 DIR *dirp;
961 void *oldaddr;
962 int saved_errno;
963 bool descend;
964 bool doadjust;
965 ptrdiff_t level;
966 nlink_t nlinks;
967 bool nostat;
968 size_t len, maxlen, new_len;
969 char *cp;
970
971 /* Set current node pointer. */
972 cur = sp->fts_cur;
973
974 /*
975 * Open the directory for reading. If this fails, we're done.
976 * If being called from fts_read, set the fts_info field.
977 */
978#if defined FTS_WHITEOUT && 0
979 if (ISSET(FTS_WHITEOUT))
980 oflag = DTF_NODUP|DTF_REWIND;
981 else
982 oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
983#else
984# define __opendir2(file, flag) \
985 ( ! ISSET(FTS_NOCHDIR) && ISSET(FTS_CWDFD) \
986 ? opendirat(sp->fts_cwd_fd, file) \
987 : opendir(file))
988#endif
989 if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
990 if (type == BREAD) {
991 cur->fts_info = FTS_DNR;
992 cur->fts_errno = errno;
993 }
994 return (NULL);
995 }
996 /* Rather than calling fts_stat for each and every entry encountered
997 in the readdir loop (below), stat each directory only right after
998 opening it. */
999 if (cur->fts_info == FTS_NSOK)
1000 cur->fts_info = fts_stat(sp, cur, false);
1001
1002 /*
1003 * Nlinks is the number of possible entries of type directory in the
1004 * directory if we're cheating on stat calls, 0 if we're not doing
1005 * any stat calls at all, (nlink_t) -1 if we're statting everything.
1006 */
1007 if (type == BNAMES) {
1008 nlinks = 0;
1009 /* Be quiet about nostat, GCC. */
1010 nostat = false;
1011 } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
1012 nlinks = (cur->fts_statp->st_nlink
1013 - (ISSET(FTS_SEEDOT) ? 0 : 2));
1014 nostat = true;
1015 } else {
1016 nlinks = -1;
1017 nostat = false;
1018 }
1019
1020 /*
1021 * If we're going to need to stat anything or we want to descend
1022 * and stay in the directory, chdir. If this fails we keep going,
1023 * but set a flag so we don't chdir after the post-order visit.
1024 * We won't be able to stat anything, but we can still return the
1025 * names themselves. Note, that since fts_read won't be able to
1026 * chdir into the directory, it will have to return different file
1027 * names than before, i.e. "a/b" instead of "b". Since the node
1028 * has already been visited in pre-order, have to wait until the
1029 * post-order visit to return the error. There is a special case
1030 * here, if there was nothing to stat then it's not an error to
1031 * not be able to stat. This is all fairly nasty. If a program
1032 * needed sorted entries or stat information, they had better be
1033 * checking FTS_NS on the returned nodes.
1034 */
1035 if (nlinks || type == BREAD) {
1036#ifdef __EMX__
1037 if (fts_safe_changedir(sp, cur, -1, cur->fts_accpath)) {
1038#else
1039 int dir_fd = dirfd(dirp);
1040 if (ISSET(FTS_CWDFD) && 0 <= dir_fd)
1041 dir_fd = dup (dir_fd);
1042 if (dir_fd < 0 || fts_safe_changedir(sp, cur, dir_fd, NULL)) {
1043#endif
1044 if (nlinks && type == BREAD)
1045 cur->fts_errno = errno;
1046 cur->fts_flags |= FTS_DONTCHDIR;
1047 descend = false;
1048 closedir(dirp);
1049#ifndef __EMX__
1050 if (ISSET(FTS_CWDFD) && 0 <= dir_fd)
1051 close (dir_fd);
1052#endif
1053 dirp = NULL;
1054 } else
1055 descend = true;
1056 } else
1057 descend = false;
1058
1059 /*
1060 * Figure out the max file name length that can be stored in the
1061 * current buffer -- the inner loop allocates more space as necessary.
1062 * We really wouldn't have to do the maxlen calculations here, we
1063 * could do them in fts_read before returning the name, but it's a
1064 * lot easier here since the length is part of the dirent structure.
1065 *
1066 * If not changing directories set a pointer so that can just append
1067 * each new component into the file name.
1068 */
1069 len = NAPPEND(cur);
1070 if (ISSET(FTS_NOCHDIR)) {
1071 cp = sp->fts_path + len;
1072 *cp++ = '/';
1073 } else {
1074 /* GCC, you're too verbose. */
1075 cp = NULL;
1076 }
1077 len++;
1078 maxlen = sp->fts_pathlen - len;
1079
1080 level = cur->fts_level + 1;
1081
1082 /* Read the directory, attaching each entry to the `link' pointer. */
1083 doadjust = false;
1084 for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
1085 bool is_dir;
1086
1087 if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
1088 continue;
1089
1090 if ((p = fts_alloc (sp, dp->d_name,
1091 _D_EXACT_NAMLEN (dp))) == NULL)
1092 goto mem1;
1093 if (_D_EXACT_NAMLEN (dp) >= maxlen) {
1094 /* include space for NUL */
1095 oldaddr = sp->fts_path;
1096 if (! fts_palloc(sp, _D_EXACT_NAMLEN (dp) + len + 1)) {
1097 /*
1098 * No more memory. Save
1099 * errno, free up the current structure and the
1100 * structures already allocated.
1101 */
1102mem1: saved_errno = errno;
1103 free(p);
1104 fts_lfree(head);
1105 closedir(dirp);
1106 cur->fts_info = FTS_ERR;
1107 SET(FTS_STOP);
1108 __set_errno (saved_errno);
1109 return (NULL);
1110 }
1111 /* Did realloc() change the pointer? */
1112 if (oldaddr != sp->fts_path) {
1113 doadjust = true;
1114 if (ISSET(FTS_NOCHDIR))
1115 cp = sp->fts_path + len;
1116 }
1117 maxlen = sp->fts_pathlen - len;
1118 }
1119
1120 new_len = len + _D_EXACT_NAMLEN (dp);
1121 if (new_len < len) {
1122 /*
1123 * In the unlikely even that we would end up
1124 * with a file name longer than SIZE_MAX, free up
1125 * the current structure and the structures already
1126 * allocated, then error out with ENAMETOOLONG.
1127 */
1128 free(p);
1129 fts_lfree(head);
1130 closedir(dirp);
1131 cur->fts_info = FTS_ERR;
1132 SET(FTS_STOP);
1133 __set_errno (ENAMETOOLONG);
1134 return (NULL);
1135 }
1136 p->fts_level = level;
1137 p->fts_parent = sp->fts_cur;
1138 p->fts_pathlen = new_len;
1139
1140#if defined FTS_WHITEOUT && 0
1141 if (dp->d_type == DT_WHT)
1142 p->fts_flags |= FTS_ISW;
1143#endif
1144
1145 /* Build a file name for fts_stat to stat. */
1146 if (ISSET(FTS_NOCHDIR)) {
1147 p->fts_accpath = p->fts_path;
1148 memmove(cp, p->fts_name, p->fts_namelen + 1);
1149 } else
1150 p->fts_accpath = p->fts_name;
1151
1152 if (sp->fts_compar == NULL || ISSET(FTS_DEFER_STAT)) {
1153 /* Record what fts_read will have to do with this
1154 entry. In many cases, it will simply fts_stat it,
1155 but we can take advantage of any d_type information
1156 to optimize away the unnecessary stat calls. I.e.,
1157 if FTS_NOSTAT is in effect and we're not following
1158 symlinks (FTS_PHYSICAL) and d_type indicates this
1159 is *not* a directory, then we won't have to stat it
1160 at all. If it *is* a directory, then (currently)
1161 we stat it regardless, in order to get device and
1162 inode numbers. Some day we might optimize that
1163 away, too, for directories where d_ino is known to
1164 be valid. */
1165 bool skip_stat = (ISSET(FTS_PHYSICAL)
1166 && ISSET(FTS_NOSTAT)
1167 && DT_IS_KNOWN(dp)
1168 && ! DT_MUST_BE(dp, DT_DIR));
1169 p->fts_info = FTS_NSOK;
1170 fts_set_stat_required(p, !skip_stat);
1171 is_dir = (ISSET(FTS_PHYSICAL) && ISSET(FTS_NOSTAT)
1172 && DT_MUST_BE(dp, DT_DIR));
1173 } else {
1174 p->fts_info = fts_stat(sp, p, false);
1175 is_dir = (p->fts_info == FTS_D
1176 || p->fts_info == FTS_DC
1177 || p->fts_info == FTS_DOT);
1178 }
1179
1180 /* Decrement link count if applicable. */
1181 if (nlinks > 0 && is_dir)
1182 nlinks -= nostat;
1183
1184 /* We walk in directory order so "ls -f" doesn't get upset. */
1185 p->fts_link = NULL;
1186 if (head == NULL)
1187 head = tail = p;
1188 else {
1189 tail->fts_link = p;
1190 tail = p;
1191 }
1192 ++nitems;
1193 }
1194 if (dirp)
1195 closedir(dirp);
1196
1197 /*
1198 * If realloc() changed the address of the file name, adjust the
1199 * addresses for the rest of the tree and the dir list.
1200 */
1201 if (doadjust)
1202 fts_padjust(sp, head);
1203
1204 /*
1205 * If not changing directories, reset the file name back to original
1206 * state.
1207 */
1208 if (ISSET(FTS_NOCHDIR)) {
1209 if (len == sp->fts_pathlen || nitems == 0)
1210 --cp;
1211 *cp = '\0';
1212 }
1213
1214 /*
1215 * If descended after called from fts_children or after called from
1216 * fts_read and nothing found, get back. At the root level we use
1217 * the saved fd; if one of fts_open()'s arguments is a relative name
1218 * to an empty directory, we wind up here with no other way back. If
1219 * can't get back, we're done.
1220 */
1221 if (descend && (type == BCHILD || !nitems) &&
1222 (cur->fts_level == FTS_ROOTLEVEL
1223 ? RESTORE_INITIAL_CWD(sp)
1224 : fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
1225 cur->fts_info = FTS_ERR;
1226 SET(FTS_STOP);
1227 fts_lfree(head);
1228 return (NULL);
1229 }
1230
1231 /* If didn't find anything, return NULL. */
1232 if (!nitems) {
1233 if (type == BREAD)
1234 cur->fts_info = FTS_DP;
1235 fts_lfree(head);
1236 return (NULL);
1237 }
1238
1239 /* Sort the entries. */
1240 if (sp->fts_compar && nitems > 1)
1241 head = fts_sort(sp, head, nitems);
1242 return (head);
1243}
1244
1245#if FTS_DEBUG
1246
1247/* Walk ->fts_parent links starting at E_CURR, until the root of the
1248 current hierarchy. There should be a directory with dev/inode
1249 matching those of AD. If not, print a lot of diagnostics. */
1250static void
1251find_matching_ancestor (FTSENT const *e_curr, struct Active_dir const *ad)
1252{
1253 FTSENT const *ent;
1254 for (ent = e_curr; ent->fts_level >= FTS_ROOTLEVEL; ent = ent->fts_parent)
1255 {
1256 if (ad->ino == ent->fts_statp->st_ino
1257 && ad->dev == ent->fts_statp->st_dev)
1258 return;
1259 }
1260 printf ("ERROR: tree dir, %s, not active\n", ad->fts_ent->fts_accpath);
1261 printf ("active dirs:\n");
1262 for (ent = e_curr;
1263 ent->fts_level >= FTS_ROOTLEVEL; ent = ent->fts_parent)
1264 printf (" %s(%"PRIuMAX"/%"PRIuMAX") to %s(%"PRIuMAX"/%"PRIuMAX")...\n",
1265 ad->fts_ent->fts_accpath,
1266 (uintmax_t) ad->dev,
1267 (uintmax_t) ad->ino,
1268 ent->fts_accpath,
1269 (uintmax_t) ent->fts_statp->st_dev,
1270 (uintmax_t) ent->fts_statp->st_ino);
1271}
1272
1273void
1274fts_cross_check (FTS const *sp)
1275{
1276 FTSENT const *ent = sp->fts_cur;
1277 FTSENT const *t;
1278 if ( ! ISSET (FTS_TIGHT_CYCLE_CHECK))
1279 return;
1280
1281 Dprintf (("fts-cross-check cur=%s\n", ent->fts_path));
1282 /* Make sure every parent dir is in the tree. */
1283 for (t = ent->fts_parent; t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
1284 {
1285 struct Active_dir ad;
1286 ad.ino = t->fts_statp->st_ino;
1287 ad.dev = t->fts_statp->st_dev;
1288 if ( ! hash_lookup (sp->fts_cycle.ht, &ad))
1289 printf ("ERROR: active dir, %s, not in tree\n", t->fts_path);
1290 }
1291
1292 /* Make sure every dir in the tree is an active dir.
1293 But ENT is not necessarily a directory. If so, just skip this part. */
1294 if (ent->fts_parent->fts_level >= FTS_ROOTLEVEL
1295 && (ent->fts_info == FTS_DP
1296 || ent->fts_info == FTS_D))
1297 {
1298 struct Active_dir *ad;
1299 for (ad = hash_get_first (sp->fts_cycle.ht); ad != NULL;
1300 ad = hash_get_next (sp->fts_cycle.ht, ad))
1301 {
1302 find_matching_ancestor (ent, ad);
1303 }
1304 }
1305}
1306
1307static bool
1308same_fd (int fd1, int fd2)
1309{
1310 struct stat sb1, sb2;
1311 return (fstat (fd1, &sb1) == 0
1312 && fstat (fd2, &sb2) == 0
1313 && SAME_INODE (sb1, sb2));
1314}
1315
1316static void
1317fd_ring_print (FTS const *sp, FILE *stream, char const *msg)
1318{
1319 I_ring const *fd_ring = &sp->fts_fd_ring;
1320 unsigned int i = fd_ring->fts_front;
1321 char *cwd = getcwdat (sp->fts_cwd_fd, NULL, 0);
1322 fprintf (stream, "=== %s ========== %s\n", msg, cwd);
1323 free (cwd);
1324 if (i_ring_empty (fd_ring))
1325 return;
1326
1327 while (true)
1328 {
1329 int fd = fd_ring->fts_fd_ring[i];
1330 if (fd < 0)
1331 fprintf (stream, "%d: %d:\n", i, fd);
1332 else
1333 {
1334 char *wd = getcwdat (fd, NULL, 0);
1335 fprintf (stream, "%d: %d: %s\n", i, fd, wd);
1336 free (wd);
1337 }
1338 if (i == fd_ring->fts_back)
1339 break;
1340 i = (i + I_RING_SIZE - 1) % I_RING_SIZE;
1341 }
1342}
1343
1344/* Ensure that each file descriptor on the fd_ring matches a
1345 parent, grandparent, etc. of the current working directory. */
1346static void
1347fd_ring_check (FTS const *sp)
1348{
1349 if (!fts_debug)
1350 return;
1351
1352 /* Make a writable copy. */
1353 I_ring fd_w = sp->fts_fd_ring;
1354
1355 int cwd_fd = sp->fts_cwd_fd;
1356 cwd_fd = dup (cwd_fd);
1357 char *dot = getcwdat (cwd_fd, NULL, 0);
1358 error (0, 0, "===== check ===== cwd: %s", dot);
1359 free (dot);
1360 while ( ! i_ring_empty (&fd_w))
1361 {
1362 int fd = i_ring_pop (&fd_w);
1363 if (0 <= fd)
1364 {
1365 int parent_fd = openat (cwd_fd, "..", O_RDONLY);
1366 if (parent_fd < 0)
1367 {
1368 // Warn?
1369 break;
1370 }
1371 if (!same_fd (fd, parent_fd))
1372 {
1373 char *cwd = getcwdat (fd, NULL, 0);
1374 error (0, errno, "ring : %s", cwd);
1375 char *c2 = getcwdat (parent_fd, NULL, 0);
1376 error (0, errno, "parent: %s", c2);
1377 free (cwd);
1378 free (c2);
1379 abort ();
1380 }
1381 close (cwd_fd);
1382 cwd_fd = parent_fd;
1383 }
1384 }
1385 close (cwd_fd);
1386}
1387#endif
1388
1389static unsigned short int
1390internal_function
1391fts_stat(FTS *sp, register FTSENT *p, bool follow)
1392{
1393 struct stat *sbp = p->fts_statp;
1394 int saved_errno;
1395
1396 if (p->fts_level == FTS_ROOTLEVEL && ISSET(FTS_COMFOLLOW))
1397 follow = true;
1398
1399#if defined FTS_WHITEOUT && 0
1400 /* check for whiteout */
1401 if (p->fts_flags & FTS_ISW) {
1402 memset(sbp, '\0', sizeof (*sbp));
1403 sbp->st_mode = S_IFWHT;
1404 return (FTS_W);
1405 }
1406#endif
1407
1408 /*
1409 * If doing a logical walk, or application requested FTS_FOLLOW, do
1410 * a stat(2). If that fails, check for a non-existent symlink. If
1411 * fail, set the errno from the stat call.
1412 */
1413 if (ISSET(FTS_LOGICAL) || follow) {
1414 if (stat(p->fts_accpath, sbp)) {
1415 saved_errno = errno;
1416 if (errno == ENOENT
1417 && lstat(p->fts_accpath, sbp) == 0) {
1418 __set_errno (0);
1419 return (FTS_SLNONE);
1420 }
1421 p->fts_errno = saved_errno;
1422 goto err;
1423 }
1424 } else if (fstatat(sp->fts_cwd_fd, p->fts_accpath, sbp,
1425 AT_SYMLINK_NOFOLLOW)) {
1426 p->fts_errno = errno;
1427err: memset(sbp, 0, sizeof(struct stat));
1428 return (FTS_NS);
1429 }
1430
1431 if (S_ISDIR(sbp->st_mode)) {
1432 if (ISDOT(p->fts_name)) {
1433 /* Command-line "." and ".." are real directories. */
1434 return (p->fts_level == FTS_ROOTLEVEL ? FTS_D : FTS_DOT);
1435 }
1436
1437#if _LGPL_PACKAGE
1438 {
1439 /*
1440 * Cycle detection is done by brute force when the directory
1441 * is first encountered. If the tree gets deep enough or the
1442 * number of symbolic links to directories is high enough,
1443 * something faster might be worthwhile.
1444 */
1445 FTSENT *t;
1446
1447 for (t = p->fts_parent;
1448 t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
1449 if (sbp->st_ino == t->fts_statp->st_ino
1450 && sbp->st_dev == t->fts_statp->st_dev)
1451 {
1452 p->fts_cycle = t;
1453 return (FTS_DC);
1454 }
1455 }
1456#endif
1457
1458 return (FTS_D);
1459 }
1460 if (S_ISLNK(sbp->st_mode))
1461 return (FTS_SL);
1462 if (S_ISREG(sbp->st_mode))
1463 return (FTS_F);
1464 return (FTS_DEFAULT);
1465}
1466
1467static int
1468fts_compar (void const *a, void const *b)
1469{
1470 /* Convert A and B to the correct types, to pacify the compiler, and
1471 for portability to bizarre hosts where "void const *" and "FTSENT
1472 const **" differ in runtime representation. The comparison
1473 function cannot modify *a and *b, but there is no compile-time
1474 check for this. */
1475 FTSENT const **pa = (FTSENT const **) a;
1476 FTSENT const **pb = (FTSENT const **) b;
1477 return pa[0]->fts_fts->fts_compar (pa, pb);
1478}
1479
1480static FTSENT *
1481internal_function
1482fts_sort (FTS *sp, FTSENT *head, register size_t nitems)
1483{
1484 register FTSENT **ap, *p;
1485
1486 /* On most modern hosts, void * and FTSENT ** have the same
1487 run-time representation, and one can convert sp->fts_compar to
1488 the type qsort expects without problem. Use the heuristic that
1489 this is OK if the two pointer types are the same size, and if
1490 converting FTSENT ** to long int is the same as converting
1491 FTSENT ** to void * and then to long int. This heuristic isn't
1492 valid in general but we don't know of any counterexamples. */
1493 FTSENT *dummy;
1494 int (*compare) (void const *, void const *) =
1495 ((sizeof &dummy == sizeof (void *)
1496 && (long int) &dummy == (long int) (void *) &dummy)
1497 ? (int (*) (void const *, void const *)) sp->fts_compar
1498 : fts_compar);
1499
1500 /*
1501 * Construct an array of pointers to the structures and call qsort(3).
1502 * Reassemble the array in the order returned by qsort. If unable to
1503 * sort for memory reasons, return the directory entries in their
1504 * current order. Allocate enough space for the current needs plus
1505 * 40 so don't realloc one entry at a time.
1506 */
1507 if (nitems > sp->fts_nitems) {
1508 struct _ftsent **a;
1509
1510 sp->fts_nitems = nitems + 40;
1511 if (SIZE_MAX / sizeof *a < sp->fts_nitems
1512 || ! (a = realloc (sp->fts_array,
1513 sp->fts_nitems * sizeof *a))) {
1514 free(sp->fts_array);
1515 sp->fts_array = NULL;
1516 sp->fts_nitems = 0;
1517 return (head);
1518 }
1519 sp->fts_array = a;
1520 }
1521 for (ap = sp->fts_array, p = head; p; p = p->fts_link)
1522 *ap++ = p;
1523 qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), compare);
1524 for (head = *(ap = sp->fts_array); --nitems; ++ap)
1525 ap[0]->fts_link = ap[1];
1526 ap[0]->fts_link = NULL;
1527 return (head);
1528}
1529
1530static FTSENT *
1531internal_function
1532fts_alloc (FTS *sp, const char *name, register size_t namelen)
1533{
1534 register FTSENT *p;
1535 size_t len;
1536
1537 /*
1538 * The file name is a variable length array. Allocate the FTSENT
1539 * structure and the file name in one chunk.
1540 */
1541 len = sizeof(FTSENT) + namelen;
1542 if ((p = malloc(len)) == NULL)
1543 return (NULL);
1544
1545 /* Copy the name and guarantee NUL termination. */
1546 memmove(p->fts_name, name, namelen);
1547 p->fts_name[namelen] = '\0';
1548
1549 p->fts_namelen = namelen;
1550 p->fts_fts = sp;
1551 p->fts_path = sp->fts_path;
1552 p->fts_errno = 0;
1553 p->fts_flags = 0;
1554 p->fts_instr = FTS_NOINSTR;
1555 p->fts_number = 0;
1556 p->fts_pointer = NULL;
1557 return (p);
1558}
1559
1560static void
1561internal_function
1562fts_lfree (register FTSENT *head)
1563{
1564 register FTSENT *p;
1565
1566 /* Free a linked list of structures. */
1567 while ((p = head)) {
1568 head = head->fts_link;
1569 free(p);
1570 }
1571}
1572
1573/*
1574 * Allow essentially unlimited file name lengths; find, rm, ls should
1575 * all work on any tree. Most systems will allow creation of file
1576 * names much longer than MAXPATHLEN, even though the kernel won't
1577 * resolve them. Add the size (not just what's needed) plus 256 bytes
1578 * so don't realloc the file name 2 bytes at a time.
1579 */
1580static bool
1581internal_function
1582fts_palloc (FTS *sp, size_t more)
1583{
1584 char *p;
1585 size_t new_len = sp->fts_pathlen + more + 256;
1586
1587 /*
1588 * See if fts_pathlen would overflow.
1589 */
1590 if (new_len < sp->fts_pathlen) {
1591 free(sp->fts_path);
1592 sp->fts_path = NULL;
1593 __set_errno (ENAMETOOLONG);
1594 return false;
1595 }
1596 sp->fts_pathlen = new_len;
1597 p = realloc(sp->fts_path, sp->fts_pathlen);
1598 if (p == NULL) {
1599 free(sp->fts_path);
1600 sp->fts_path = NULL;
1601 return false;
1602 }
1603 sp->fts_path = p;
1604 return true;
1605}
1606
1607/*
1608 * When the file name is realloc'd, have to fix all of the pointers in
1609 * structures already returned.
1610 */
1611static void
1612internal_function
1613fts_padjust (FTS *sp, FTSENT *head)
1614{
1615 FTSENT *p;
1616 char *addr = sp->fts_path;
1617
1618#define ADJUST(p) do { \
1619 if ((p)->fts_accpath != (p)->fts_name) { \
1620 (p)->fts_accpath = \
1621 (char *)addr + ((p)->fts_accpath - (p)->fts_path); \
1622 } \
1623 (p)->fts_path = addr; \
1624} while (0)
1625 /* Adjust the current set of children. */
1626 for (p = sp->fts_child; p; p = p->fts_link)
1627 ADJUST(p);
1628
1629 /* Adjust the rest of the tree, including the current level. */
1630 for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
1631 ADJUST(p);
1632 p = p->fts_link ? p->fts_link : p->fts_parent;
1633 }
1634}
1635
1636static size_t
1637internal_function
1638fts_maxarglen (char * const *argv)
1639{
1640 size_t len, max;
1641
1642 for (max = 0; *argv; ++argv)
1643 if ((len = strlen(*argv)) > max)
1644 max = len;
1645 return (max + 1);
1646}
1647
1648/*
1649 * Change to dir specified by fd or file name without getting
1650 * tricked by someone changing the world out from underneath us.
1651 * Assumes p->fts_statp->st_dev and p->fts_statp->st_ino are filled in.
1652 * If FD is non-negative, expect it to be used after this function returns,
1653 * and to be closed eventually. So don't pass e.g., `dirfd(dirp)' and then
1654 * do closedir(dirp), because that would invalidate the saved FD.
1655 * Upon failure, close FD immediately and return nonzero.
1656 */
1657static int
1658internal_function
1659fts_safe_changedir (FTS *sp, FTSENT *p, int fd, char const *dir)
1660{
1661 int ret;
1662 bool is_dotdot = dir && STREQ (dir, "..");
1663 int newfd;
1664
1665 /* This clause handles the unusual case in which FTS_NOCHDIR
1666 is specified, along with FTS_CWDFD. In that case, there is
1667 no need to change even the virtual cwd file descriptor.
1668 However, if FD is non-negative, we do close it here. */
1669 if (ISSET (FTS_NOCHDIR))
1670 {
1671 if (ISSET (FTS_CWDFD) && 0 <= fd)
1672 close (fd);
1673 return 0;
1674 }
1675
1676 if (fd < 0 && is_dotdot && ISSET (FTS_CWDFD))
1677 {
1678 /* When possible, skip the diropen and subsequent fstat+dev/ino
1679 comparison. I.e., when changing to parent directory
1680 (chdir ("..")), use a file descriptor from the ring and
1681 save the overhead of diropen+fstat, as well as avoiding
1682 failure when we lack "x" access to the virtual cwd. */
1683 if ( ! i_ring_empty (&sp->fts_fd_ring))
1684 {
1685 int parent_fd;
1686 fd_ring_print (sp, stderr, "pre-pop");
1687 parent_fd = i_ring_pop (&sp->fts_fd_ring);
1688 is_dotdot = true;
1689 if (0 <= parent_fd)
1690 {
1691 fd = parent_fd;
1692 dir = NULL;
1693 }
1694 }
1695 }
1696
1697 newfd = fd;
1698 if (fd < 0 && (newfd = diropen (sp, dir)) < 0)
1699 return -1;
1700
1701 /* The following dev/inode check is necessary if we're doing a
1702 `logical' traversal (through symlinks, a la chown -L), if the
1703 system lacks O_NOFOLLOW support, or if we're changing to ".."
1704 (but not via a popped file descriptor). When changing to the
1705 name "..", O_NOFOLLOW can't help. In general, when the target is
1706 not "..", diropen's use of O_NOFOLLOW ensures we don't mistakenly
1707 follow a symlink, so we can avoid the expense of this fstat. */
1708 if (ISSET(FTS_LOGICAL) || ! HAVE_WORKING_O_NOFOLLOW
1709 || (dir && STREQ (dir, "..")))
1710 {
1711 struct stat sb;
1712 if (fstat(newfd, &sb))
1713 {
1714 ret = -1;
1715 goto bail;
1716 }
1717 if (p->fts_statp->st_dev != sb.st_dev
1718 || p->fts_statp->st_ino != sb.st_ino)
1719 {
1720 __set_errno (ENOENT); /* disinformation */
1721 ret = -1;
1722 goto bail;
1723 }
1724 }
1725
1726 if (ISSET(FTS_CWDFD))
1727 {
1728 cwd_advance_fd (sp, newfd, ! is_dotdot);
1729 return 0;
1730 }
1731
1732 ret = fchdir(newfd);
1733bail:
1734 if (fd < 0)
1735 {
1736 int oerrno = errno;
1737 (void)close(newfd);
1738 __set_errno (oerrno);
1739 }
1740 return ret;
1741}
Note: See TracBrowser for help on using the repository browser.