If wd_sanity_check() discovers that the mount table has changed, remember the updated...
[findutils.git] / find / find.c
blobb27062998429fb1db9eb5e019debd31a88e7d594
1 /* find -- search for files in a directory hierarchy
2 Copyright (C) 1990, 91, 92, 93, 94, 2000, 2003 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 USA.*/
19 /* GNU find was written by Eric Decker <cire@cisco.com>,
20 with enhancements by David MacKenzie <djm@gnu.ai.mit.edu>,
21 Jay Plett <jay@silence.princeton.nj.us>,
22 and Tim Wood <axolotl!tim@toad.com>.
23 The idea for -print0 and xargs -0 came from
24 Dan Bernstein <brnstnd@kramden.acf.nyu.edu>. */
26 #include "defs.h"
28 #include <errno.h>
29 #include <assert.h>
32 #ifdef HAVE_FCNTL_H
33 #include <fcntl.h>
34 #else
35 #include <sys/file.h>
36 #endif
37 #include "../gnulib/lib/xalloc.h"
38 #include "../gnulib/lib/human.h"
39 #include "../gnulib/lib/canonicalize.h"
40 #include <modetype.h>
41 #include "../gnulib/lib/savedir.h"
43 #ifdef HAVE_LOCALE_H
44 #include <locale.h>
45 #endif
47 #if ENABLE_NLS
48 # include <libintl.h>
49 # define _(Text) gettext (Text)
50 #else
51 # define _(Text) Text
52 #define textdomain(Domain)
53 #define bindtextdomain(Package, Directory)
54 #endif
55 #ifdef gettext_noop
56 # define N_(String) gettext_noop (String)
57 #else
58 /* See locate.c for explanation as to why not use (String) */
59 # define N_(String) String
60 #endif
62 #define apply_predicate(pathname, stat_buf_ptr, node) \
63 (*(node)->pred_func)((pathname), (stat_buf_ptr), (node))
66 static void init_mounted_dev_list(void);
67 static void process_top_path PARAMS((char *pathname));
68 static int process_path PARAMS((char *pathname, char *name, boolean leaf, char *parent));
69 static void process_dir PARAMS((char *pathname, char *name, int pathlen, struct stat *statp, char *parent));
70 #if 0
71 static boolean no_side_effects PARAMS((struct predicate *pred));
72 #endif
73 static boolean default_prints PARAMS((struct predicate *pred));
75 /* Name this program was run with. */
76 char *program_name;
78 /* All predicates for each path to process. */
79 struct predicate *predicates;
81 /* The last predicate allocated. */
82 struct predicate *last_pred;
84 /* The root of the evaluation tree. */
85 static struct predicate *eval_tree;
87 /* If true, process directory before contents. True unless -depth given. */
88 boolean do_dir_first;
90 /* If >=0, don't descend more than this many levels of subdirectories. */
91 int maxdepth;
93 /* If >=0, don't process files above this level. */
94 int mindepth;
96 /* Current depth; 0 means current path is a command line arg. */
97 int curdepth;
99 /* Output block size. */
100 int output_block_size;
102 /* Time at start of execution. */
103 time_t start_time;
105 /* Seconds between 00:00 1/1/70 and either one day before now
106 (the default), or the start of today (if -daystart is given). */
107 time_t cur_day_start;
109 /* If true, cur_day_start has been adjusted to the start of the day. */
110 boolean full_days;
112 /* If true, do not assume that files in directories with nlink == 2
113 are non-directories. */
114 boolean no_leaf_check;
116 /* If true, don't cross filesystem boundaries. */
117 boolean stay_on_filesystem;
119 /* If true, don't descend past current directory.
120 Can be set by -prune, -maxdepth, and -xdev/-mount. */
121 boolean stop_at_current_level;
123 /* The full path of the initial working directory, or "." if
124 STARTING_DESC is nonnegative. */
125 char const *starting_dir = ".";
127 /* A file descriptor open to the initial working directory.
128 Doing it this way allows us to work when the i.w.d. has
129 unreadable parents. */
130 int starting_desc;
132 /* The stat buffer of the initial working directory. */
133 struct stat starting_stat_buf;
135 /* If true, we have called stat on the current path. */
136 boolean have_stat;
138 /* The file being operated on, relative to the current directory.
139 Used for stat, readlink, remove, and opendir. */
140 char *rel_pathname;
142 /* Length of current path. */
143 int path_length;
145 /* true if following symlinks. Should be consistent with xstat. */
146 /* boolean dereference; */
147 enum SymlinkOption symlink_handling;
150 /* Pointer to the function used to stat files. */
151 int (*xstat) ();
153 /* Status value to return to system. */
154 int exit_status;
156 /* If true, we ignore the problem where we find that a directory entry
157 * no longer exists by the time we get around to processing it.
159 boolean ignore_readdir_race;
162 /* If true, we issue warning messages
164 boolean warnings;
167 enum TraversalDirection
169 TraversingUp,
170 TraversingDown
174 static int
175 following_links(void)
177 switch (symlink_handling)
179 case SYMLINK_ALWAYS_DEREF:
180 return 1;
181 case SYMLINK_DEREF_ARGSONLY:
182 return (curdepth == 0);
183 case SYMLINK_NEVER_DEREF:
184 default:
185 return 0;
190 /* optionh_stat() implements the stat operation when the -H option is
191 * in effect.
193 * If the item to be examined is a command-line argument, we follow
194 * symbolic links. If the stat() call fails on the command-line item,
195 * we fall back on the properties of the symbolic link.
197 * If the item to be examined is not a command-line argument, we
198 * examine the link itself.
200 int
201 optionh_stat(const char *name, struct stat *p)
203 if (0 == curdepth)
205 /* This file is from the command line; deference the link (if it
206 * is a link).
208 if (0 == stat(name, p))
210 /* success */
211 return 0;
213 else
215 /* fallback - return the information for the link itself. */
216 return lstat(name, p);
219 else
221 /* Not a file on the command line; do not derefernce the link.
223 return lstat(name, p);
227 /* optionl_stat() implements the stat operation when the -L option is
228 * in effect. That option makes us examine the thing the symbolic
229 * link points to, not the symbolic link itself.
231 int
232 optionl_stat(const char *name, struct stat *p)
234 if (0 == stat(name, p))
236 return 0; /* normal case. */
238 else
240 return lstat(name, p); /* can't follow link, return the link itself. */
244 /* optionp_stat() implements the stat operation when the -P option is
245 * in effect (this is also the default). That option makes us examine
246 * the symbolic link itself, not the thing it points to.
248 int
249 optionp_stat(const char *name, struct stat *p)
251 return lstat(name, p);
254 #ifdef DEBUG_STAT
255 static int
256 debug_stat (const char *file, struct stat *bufp)
258 fprintf (stderr, "debug_stat (%s)\n", file);
259 switch (symlink_handling)
261 case SYMLINK_ALWAYS_DEREF:
262 return optionl_stat(file, bufp);
263 case SYMLINK_DEREF_ARGSONLY:
264 return optionh_stat(file, bufp);
265 case SYMLINK_NEVER_DEREF:
266 return optionp_stat(file, bufp);
269 #endif /* DEBUG_STAT */
271 void
272 set_follow_state(enum SymlinkOption opt)
274 switch (opt)
276 case SYMLINK_ALWAYS_DEREF: /* -L */
277 xstat = optionl_stat;
278 no_leaf_check = false;
279 break;
281 case SYMLINK_NEVER_DEREF: /* -P (default) */
282 xstat = optionp_stat;
283 /* Can't turn on no_leaf_check because the user might have specified
284 * -noleaf anyway
286 break;
288 case SYMLINK_DEREF_ARGSONLY: /* -H */
289 xstat = optionh_stat;
290 no_leaf_check = true;
293 /* For DBEUG_STAT, the choice is made at runtime within debug_stat()
294 * by checking the contents of the symlink_handling variable.
296 #if defined(DEBUG_STAT)
297 xstat = debug_stat;
298 #endif /* !DEBUG_STAT */
303 main (int argc, char **argv)
305 int i;
306 PFB parse_function; /* Pointer to the function which parses. */
307 struct predicate *cur_pred;
308 char *predicate_name; /* Name of predicate being parsed. */
309 int end_of_leading_options = 0; /* First arg after any -H/-L etc. */
310 program_name = argv[0];
312 #ifdef HAVE_SETLOCALE
313 setlocale (LC_ALL, "");
314 #endif
315 bindtextdomain (PACKAGE, LOCALEDIR);
316 textdomain (PACKAGE);
318 if (isatty(0))
320 warnings = true;
322 else
324 warnings = false;
328 predicates = NULL;
329 last_pred = NULL;
330 do_dir_first = true;
331 maxdepth = mindepth = -1;
332 start_time = time (NULL);
333 cur_day_start = start_time - DAYSECS;
334 full_days = false;
335 no_leaf_check = false;
336 stay_on_filesystem = false;
337 ignore_readdir_race = false;
338 exit_status = 0;
340 #if defined(DEBUG_STAT)
341 xstat = debug_stat;
342 #endif /* !DEBUG_STAT */
344 #if 0
345 human_block_size (getenv ("FIND_BLOCK_SIZE"), 0, &output_block_size);
346 #else
347 if (getenv("POSIXLY_CORRECT"))
348 output_block_size = 512;
349 else
350 output_block_size = 1024;
352 if (getenv("FIND_BLOCK_SIZE"))
354 error (1, 0, _("The environment variable FIND_BLOCK_SIZE is not supported, the only thing that affects the block size is the POSIXLY_CORRECT environment variable"));
357 set_follow_state(SYMLINK_NEVER_DEREF); /* The default is equivalent to -P. */
359 init_mounted_dev_list();
361 #endif
363 #ifdef DEBUG
364 printf ("cur_day_start = %s", ctime (&cur_day_start));
365 #endif /* DEBUG */
367 /* Check for -P, -H or -L options. */
368 for (i=1; (end_of_leading_options = i) < argc; ++i)
370 if (0 == strcmp("-H", argv[i]))
372 /* Meaning: dereference symbolic links on command line, but nowhere else. */
373 set_follow_state(SYMLINK_DEREF_ARGSONLY);
375 else if (0 == strcmp("-L", argv[i]))
377 /* Meaning: dereference all symbolic links. */
378 set_follow_state(SYMLINK_ALWAYS_DEREF);
380 else if (0 == strcmp("-P", argv[i]))
382 /* Meaning: never dereference symbolic links (default). */
383 set_follow_state(SYMLINK_NEVER_DEREF);
385 else if (0 == strcmp("--", argv[i]))
387 /* -- signifies the end of options. */
388 end_of_leading_options = i+1; /* Next time start with the next option */
389 break;
391 else
393 /* Hmm, must be one of
394 * (a) A path name
395 * (b) A predicate
397 end_of_leading_options = i; /* Next time start with this option */
398 break;
402 /* We are now processing the part of the "find" command line
403 * after the -H/-L options (if any).
406 /* fprintf(stderr, "rest: optind=%ld\n", (long)optind); */
408 /* Find where in ARGV the predicates begin. */
409 for (i = end_of_leading_options; i < argc && strchr ("-!(),", argv[i][0]) == NULL; i++)
411 /* fprintf(stderr, "Looks like %s is not a predicate\n", argv[i]); */
412 /* Do nothing. */ ;
415 /* Enclose the expression in `( ... )' so a default -print will
416 apply to the whole expression. */
417 parse_open (argv, &argc);
418 /* Build the input order list. */
419 while (i < argc)
421 if (strchr ("-!(),", argv[i][0]) == NULL)
422 usage (_("paths must precede expression"));
423 predicate_name = argv[i];
424 parse_function = find_parser (predicate_name);
425 if (parse_function == NULL)
426 /* Command line option not recognized */
427 error (1, 0, _("invalid predicate `%s'"), predicate_name);
428 i++;
429 if (!(*parse_function) (argv, &i))
431 if (argv[i] == NULL)
432 /* Command line option requires an argument */
433 error (1, 0, _("missing argument to `%s'"), predicate_name);
434 else
435 error (1, 0, _("invalid argument `%s' to `%s'"),
436 argv[i], predicate_name);
439 if (predicates->pred_next == NULL)
441 /* No predicates that do something other than set a global variable
442 were given; remove the unneeded initial `(' and add `-print'. */
443 cur_pred = predicates;
444 predicates = last_pred = predicates->pred_next;
445 free ((char *) cur_pred);
446 parse_print (argv, &argc);
448 else if (!default_prints (predicates->pred_next))
450 /* One or more predicates that produce output were given;
451 remove the unneeded initial `('. */
452 cur_pred = predicates;
453 predicates = predicates->pred_next;
454 free ((char *) cur_pred);
456 else
458 /* `( user-supplied-expression ) -print'. */
459 parse_close (argv, &argc);
460 parse_print (argv, &argc);
463 #ifdef DEBUG
464 printf (_("Predicate List:\n"));
465 print_list (predicates);
466 #endif /* DEBUG */
468 /* Done parsing the predicates. Build the evaluation tree. */
469 cur_pred = predicates;
470 eval_tree = get_expr (&cur_pred, NO_PREC);
472 /* Check if we have any left-over predicates (this fixes
473 * Debian bug #185202).
475 if (cur_pred != NULL)
477 error (1, 0, _("unexpected extra predicate"));
480 #ifdef DEBUG
481 printf (_("Eval Tree:\n"));
482 print_tree (eval_tree, 0);
483 #endif /* DEBUG */
485 /* Rearrange the eval tree in optimal-predicate order. */
486 opt_expr (&eval_tree);
488 /* Determine the point, if any, at which to stat the file. */
489 mark_stat (eval_tree);
491 #ifdef DEBUG
492 printf (_("Optimized Eval Tree:\n"));
493 print_tree (eval_tree, 0);
494 #endif /* DEBUG */
496 starting_desc = open (".", O_RDONLY);
497 if (0 <= starting_desc && fchdir (starting_desc) != 0)
499 close (starting_desc);
500 starting_desc = -1;
502 if (starting_desc < 0)
504 starting_dir = xgetcwd ();
505 if (! starting_dir)
506 error (1, errno, _("cannot get current directory"));
508 if ((*xstat) (".", &starting_stat_buf) != 0)
509 error (1, errno, _("cannot get current directory"));
511 /* If no paths are given, default to ".". */
512 for (i = end_of_leading_options; i < argc && strchr ("-!(),", argv[i][0]) == NULL; i++)
514 process_top_path (argv[i]);
517 /* If there were no path arguments, default to ".". */
518 if (i == end_of_leading_options)
521 * We use a temporary variable here because some actions modify
522 * the path temporarily. Hence if we use a string constant,
523 * we get a coredump. The best example of this is if we say
524 * "find -printf %H" (note, not "find . -printf %H").
526 char defaultpath[2] = ".";
527 process_top_path (defaultpath);
531 return exit_status;
535 static char *
536 specific_dirname(const char *dir)
538 char dirname[1024];
540 if (0 == strcmp(".", dir))
542 /* OK, what's '.'? */
543 if (NULL != getcwd(dirname, sizeof(dirname)))
545 return strdup(dirname);
547 else
549 return strdup(dir);
552 else
554 return canonicalize_filename_mode(dir, CAN_EXISTING);
561 #if 0
562 /* list_item_present: Search for NEEDLE in HAYSTACK.
564 * NEEDLE is a normal C string. HAYSTACK is a list of concatenated C strings,
565 * each with a terminating NUL. The last item in the list is identified by
566 * the fact that its terminating NUL is itself followed by a second NUL.
568 * This data structure does not lend itself to fast searching, but we only
569 * do this when wd_sanity_check() thinks that a filesystem might have been
570 * mounted or unmounted. That doesn't happen very often.
572 static int
573 list_item_present(const char *needle, const char *haystack)
575 if (NULL != haystack)
577 const char *s = haystack;
578 while (*s)
580 if (0 == strcmp(s, needle))
582 return 1;
584 else
586 s += strlen(s);
587 ++s; /* skip the first NUL. */
591 return 0;
594 static char *mount_points = NULL;
597 /* Initialise our idea of what the list of mount points is.
598 * this function is called exactly once.
600 static void
601 init_mount_point_list(void)
603 assert(NULL == mount_points);
604 mount_points = get_mounted_filesystems();
607 static void
608 refresh_mount_point_list(void)
610 if (mount_points)
612 free(mount_points);
613 mount_points = NULL;
615 init_mount_point_list();
618 /* Determine if a directory has recently had a filesystem
619 * mounted on it or unmounted from it.
621 static enum MountPointStateChange
622 get_mount_point_state(const char *dir)
624 int was_mounted, is_mounted;
626 was_mounted = list_item_present(dir, mount_points);
627 refresh_mount_point_list();
628 is_mounted = list_item_present(dir, mount_points);
630 if (was_mounted == is_mounted)
631 return MountPointStateUnchanged;
632 else if (is_mounted)
633 return MountPointRecentlyMounted;
634 else
635 return MountPointRecentlyUnmounted;
637 #endif
641 static dev_t *mounted_devices = NULL;
642 static size_t num_mounted_devices = 0u;
645 static void
646 init_mounted_dev_list()
648 assert(NULL == mounted_devices);
649 assert(0 == num_mounted_devices);
650 mounted_devices = get_mounted_devices(&num_mounted_devices);
653 static void
654 refresh_mounted_dev_list(void)
656 if (mounted_devices)
658 free(mounted_devices);
659 mounted_devices = 0;
661 num_mounted_devices = 0u;
662 init_mounted_dev_list();
666 /* Search for device DEV in the array LIST, which is of size N. */
667 static int
668 dev_present(dev_t dev, const dev_t *list, size_t n)
670 if (list)
672 while (n-- > 0u)
674 if ( (*list++) == dev )
675 return 1;
678 return 0;
681 enum MountPointStateChange
683 MountPointRecentlyMounted,
684 MountPointRecentlyUnmounted,
685 MountPointStateUnchanged
690 static enum MountPointStateChange
691 get_mount_state(dev_t newdev)
693 int new_is_present, new_was_present;
695 new_was_present = dev_present(newdev, mounted_devices, num_mounted_devices);
696 refresh_mounted_dev_list();
697 new_is_present = dev_present(newdev, mounted_devices, num_mounted_devices);
699 if (new_was_present == new_is_present)
700 return MountPointStateUnchanged;
701 else if (new_is_present)
702 return MountPointRecentlyMounted;
703 else
704 return MountPointRecentlyUnmounted;
709 /* Examine the results of the stat() of a directory from before we
710 * entered or left it, with the results of stat()ing it afterward. If
711 * these are different, the filesystem tree has been modified while we
712 * were traversing it. That might be an attempt to use a race
713 * condition to persuade find to do something it didn't intend
714 * (e.g. an attempt by an ordinary user to exploit the fact that root
715 * sometimes runs find on the whole filesystem). However, this can
716 * also happen if automount is running (certainly on Solaris). With
717 * automount, moving into a directory can cause a filesystem to be
718 * mounted there.
720 * To cope sensibly with this, we will raise an error if we see the
721 * device number change unless we are chdir()ing into a subdirectory,
722 * and the directory we moved into has been mounted or unmounted "recently".
723 * Here "recently" means since we started "find" or we last re-read
724 * the /etc/mnttab file.
726 * If the device number does not change but the inode does, that is a
727 * problem.
729 * If the device number and inode are both the same, we are happy.
731 * If a filesystem is (un)mounted as we chdir() into the directory, that
732 * may mean that we're now examining a section of the filesystem that might
733 * have been excluded from consideration (via -prune or -quit for example).
734 * Hence we print a warning message to indicate that the output of find
735 * might be inconsistent due to the change in the filesystem.
737 static void
738 wd_sanity_check(const char *thing_to_stat,
739 const char *program_name,
740 const char *what,
741 const struct stat *oldinfo,
742 struct stat *newinfo,
743 int parent,
744 int line_no,
745 enum TraversalDirection direction,
746 boolean *changed) /* output parameter */
748 const char *fstype;
749 char *specific_what = NULL;
750 int isfatal = 1;
752 *changed = false;
754 if ((*xstat) (".", newinfo) != 0)
755 error (1, errno, "%s", thing_to_stat);
757 if (oldinfo->st_dev != newinfo->st_dev)
759 *changed = true;
760 specific_what = specific_dirname(what);
762 /* This condition is rare, so once we are here it is
763 * reasonable to perform an expensive computation to
764 * determine if we should continue or fail.
766 if (TraversingDown == direction)
768 /* We stat()ed a directory, chdir()ed into it (we know this
769 * since direction is TraversingDown), stat()ed it again,
770 * and noticed that the device numbers are different. Check
771 * if the filesystem was recently mounted.
773 * If it was, it looks like chdir()ing into the directory
774 * caused a filesystem to be mounted. Maybe automount is
775 * running. Anyway, that's probably OK - but it happens
776 * only when we are moving downward.
778 * We also allow for the possibility that a similar thing
779 * has happened with the unmounting of a filesystem. This
780 * is much rarer, as it relies on an automounter timeout
781 * occurring at exactly the wrong moment.
783 enum MountPointStateChange transition = get_mount_state(newinfo->st_dev);
784 switch (transition)
786 case MountPointRecentlyUnmounted:
787 isfatal = 0;
788 error (0, 0,
789 _("Warning: filesystem %s has recently been unmounted."),
790 specific_what);
791 break;
793 case MountPointRecentlyMounted:
794 isfatal = 0;
795 error (0, 0,
796 _("Warning: filesystem %s has recently been mounted."),
797 specific_what);
798 break;
800 case MountPointStateUnchanged:
801 isfatal = 1;
802 break;
806 if (isfatal)
808 fstype = filesystem_type(thing_to_stat, ".", newinfo);
809 error (isfatal, 0,
810 _("%s%s changed during execution of %s (old device number %ld, new device number %ld, filesystem type is %s) [ref %ld]"),
811 specific_what,
812 parent ? "/.." : "",
813 program_name,
814 (long) oldinfo->st_dev,
815 (long) newinfo->st_dev,
816 fstype,
817 line_no);
819 else
821 /* Since the device has changed under us, the inode number
822 * will almost certainly also be different. However, we have
823 * already decided that this is not a problem. Hence we return
824 * without checking the inode number.
826 free(specific_what);
827 return;
831 /* Device number was the same, check if the inode has changed. */
832 if (oldinfo->st_ino != newinfo->st_ino)
834 *changed = true;
835 specific_what = specific_dirname(what);
836 fstype = filesystem_type(thing_to_stat, ".", newinfo);
838 error (1, 0,
839 _("%s%s changed during execution of %s (old inode number %ld, new inode number %ld, filesystem type is %s) [ref %ld]"),
840 specific_what,
841 parent ? "/.." : "",
842 program_name,
843 (long) oldinfo->st_ino,
844 (long) newinfo->st_ino,
845 fstype,
846 line_no);
847 free(specific_what);
851 enum SafeChdirStatus
853 SafeChdirOK,
854 SafeChdirFailSymlink,
855 SafeChdirFailStat,
856 SafeChdirFailDefect
859 /* Safely perform a change in directory. */
860 static int
861 safely_chdir(const char *dest, enum TraversalDirection direction)
863 struct stat statbuf_dest, statbuf_arrived;
864 int rv=SafeChdirFailDefect, dotfd=-1;
865 char *name = NULL;
867 errno = 0;
868 dotfd = open(".", O_RDONLY);
869 if (dotfd >= 0)
871 /* Stat the directory we're going to. */
872 if (0 == (following_links() ? stat : lstat)(dest, &statbuf_dest))
874 #ifdef S_ISLNK
875 if (!following_links() && S_ISLNK(statbuf_dest.st_mode))
877 rv = SafeChdirFailSymlink;
878 goto fail;
880 #endif
881 chdir(dest);
883 else
885 rv = SafeChdirFailStat;
886 name = specific_dirname(dest);
887 goto fail;
890 else
894 fail:
895 if (errno)
897 if (NULL == name)
898 name = specific_dirname(".");
899 error(0, errno, "%s", name);
902 free(name);
903 name = NULL;
905 if (dotfd >= 0)
907 close(dotfd);
908 dotfd = -1;
910 return rv;
914 /* Safely go back to the starting directory. */
915 static void
916 chdir_back (void)
918 struct stat stat_buf;
919 boolean dummy;
921 if (starting_desc < 0)
923 if (chdir (starting_dir) != 0)
924 error (1, errno, "%s", starting_dir);
926 wd_sanity_check(starting_dir,
927 program_name, starting_dir,
928 &starting_stat_buf, &stat_buf, 0, __LINE__,
929 TraversingUp, &dummy);
931 else
933 if (fchdir (starting_desc) != 0)
934 error (1, errno, "%s", starting_dir);
938 /* Descend PATHNAME, which is a command-line argument. */
940 static void
941 process_top_path (char *pathname)
943 struct stat stat_buf, cur_stat_buf;
944 boolean dummy;
946 curdepth = 0;
947 path_length = strlen (pathname);
949 /* We stat each pathname given on the command-line twice --
950 once here and once in process_path. It's not too bad, though,
951 since the kernel can read the stat information out of its inode
952 cache the second time. */
953 if ((*xstat) (pathname, &stat_buf) == 0 && S_ISDIR (stat_buf.st_mode))
955 if (chdir (pathname) < 0)
957 if (!ignore_readdir_race || (errno != ENOENT) )
959 error (0, errno, "%s", pathname);
960 exit_status = 1;
962 return;
965 /* Check that we are where we should be. */
966 wd_sanity_check(pathname, program_name,
967 ".",
968 &stat_buf, &cur_stat_buf, 0, __LINE__,
969 TraversingDown, &dummy);
971 process_path (pathname, ".", false, ".");
972 chdir_back ();
974 else
975 process_path (pathname, pathname, false, ".");
978 /* Info on each directory in the current tree branch, to avoid
979 getting stuck in symbolic link loops. */
980 struct dir_id
982 ino_t ino;
983 dev_t dev;
985 static struct dir_id *dir_ids = NULL;
986 /* Entries allocated in `dir_ids'. */
987 static int dir_alloc = 0;
988 /* Index in `dir_ids' of directory currently being searched.
989 This is always the last valid entry. */
990 static int dir_curr = -1;
991 /* (Arbitrary) number of entries to grow `dir_ids' by. */
992 #define DIR_ALLOC_STEP 32
994 /* Recursively descend path PATHNAME, applying the predicates.
995 LEAF is true if PATHNAME is known to be in a directory that has no
996 more unexamined subdirectories, and therefore it is not a directory.
997 Knowing this allows us to avoid calling stat as long as possible for
998 leaf files.
1000 NAME is PATHNAME relative to the current directory. We access NAME
1001 but print PATHNAME.
1003 PARENT is the path of the parent of NAME, relative to find's
1004 starting directory.
1006 Return nonzero iff PATHNAME is a directory. */
1008 static int
1009 process_path (char *pathname, char *name, boolean leaf, char *parent)
1011 struct stat stat_buf;
1012 static dev_t root_dev; /* Device ID of current argument pathname. */
1013 int i;
1015 /* Assume it is a non-directory initially. */
1016 stat_buf.st_mode = 0;
1018 rel_pathname = name;
1020 if (leaf)
1021 have_stat = false;
1022 else
1024 if ((*xstat) (name, &stat_buf) != 0)
1026 if (!ignore_readdir_race || (errno != ENOENT) )
1028 error (0, errno, "%s", pathname);
1029 exit_status = 1;
1031 return 0;
1033 have_stat = true;
1036 if (!S_ISDIR (stat_buf.st_mode))
1038 if (curdepth >= mindepth)
1039 apply_predicate (pathname, &stat_buf, eval_tree);
1040 return 0;
1043 /* From here on, we're working on a directory. */
1045 stop_at_current_level = maxdepth >= 0 && curdepth >= maxdepth;
1047 /* If we've already seen this directory on this branch,
1048 don't descend it again. */
1049 for (i = 0; i <= dir_curr; i++)
1050 if (stat_buf.st_ino == dir_ids[i].ino &&
1051 stat_buf.st_dev == dir_ids[i].dev)
1052 stop_at_current_level = true;
1054 if (dir_alloc <= ++dir_curr)
1056 dir_alloc += DIR_ALLOC_STEP;
1057 dir_ids = (struct dir_id *)
1058 xrealloc ((char *) dir_ids, dir_alloc * sizeof (struct dir_id));
1060 dir_ids[dir_curr].ino = stat_buf.st_ino;
1061 dir_ids[dir_curr].dev = stat_buf.st_dev;
1063 if (stay_on_filesystem)
1065 if (curdepth == 0)
1066 root_dev = stat_buf.st_dev;
1067 else if (stat_buf.st_dev != root_dev)
1068 stop_at_current_level = true;
1071 if (do_dir_first && curdepth >= mindepth)
1072 apply_predicate (pathname, &stat_buf, eval_tree);
1074 #ifdef DEBUG
1075 fprintf(stderr, "pathname = %s, stop_at_current_level = %d\n",
1076 pathname, stop_at_current_level);
1077 #endif /* DEBUG */
1079 if (stop_at_current_level == false)
1080 /* Scan directory on disk. */
1081 process_dir (pathname, name, strlen (pathname), &stat_buf, parent);
1083 if (do_dir_first == false && curdepth >= mindepth)
1085 rel_pathname = name;
1086 apply_predicate (pathname, &stat_buf, eval_tree);
1089 dir_curr--;
1091 return 1;
1094 /* Scan directory PATHNAME and recurse through process_path for each entry.
1096 PATHLEN is the length of PATHNAME.
1098 NAME is PATHNAME relative to the current directory.
1100 STATP is the results of *xstat on it.
1102 PARENT is the path of the parent of NAME, relative to find's
1103 starting directory. */
1105 static void
1106 process_dir (char *pathname, char *name, int pathlen, struct stat *statp, char *parent)
1108 char *name_space; /* Names of files in PATHNAME. */
1109 int subdirs_left; /* Number of unexamined subdirs in PATHNAME. */
1110 struct stat stat_buf;
1112 subdirs_left = statp->st_nlink - 2; /* Account for name and ".". */
1114 errno = 0;
1115 name_space = savedir (name);
1116 if (name_space == NULL)
1118 if (errno)
1120 error (0, errno, "%s", pathname);
1121 exit_status = 1;
1123 else
1124 error (1, 0, _("virtual memory exhausted"));
1126 else
1128 register char *namep; /* Current point in `name_space'. */
1129 char *cur_path; /* Full path of each file to process. */
1130 char *cur_name; /* Base name of each file to process. */
1131 unsigned cur_path_size; /* Bytes allocated for `cur_path'. */
1132 register unsigned file_len; /* Length of each path to process. */
1133 register unsigned pathname_len; /* PATHLEN plus trailing '/'. */
1135 if (pathname[pathlen - 1] == '/')
1136 pathname_len = pathlen + 1; /* For '\0'; already have '/'. */
1137 else
1138 pathname_len = pathlen + 2; /* For '/' and '\0'. */
1139 cur_path_size = 0;
1140 cur_path = NULL;
1142 if (strcmp (name, ".") && chdir (name) < 0)
1144 error (0, errno, "%s", pathname);
1145 exit_status = 1;
1146 return;
1149 /* Check that we are where we should be. */
1150 if (1)
1152 struct stat tmp;
1153 boolean changed;
1155 memset(&tmp, 0, sizeof(tmp));
1156 tmp.st_dev = dir_ids[dir_curr].dev;
1157 tmp.st_ino = dir_ids[dir_curr].ino;
1158 changed = false;
1159 wd_sanity_check(pathname,
1160 program_name,
1161 ".",
1162 &tmp, &stat_buf, 0, __LINE__,
1163 TraversingDown, &changed);
1164 if (changed)
1166 /* If there had been a change but wd_sanity_check()
1167 * accepted it, we need to accept that on the
1168 * way back up as well, so modify our record
1169 * of what we think we should see later.
1171 dir_ids[dir_curr].dev = stat_buf.st_dev;
1172 dir_ids[dir_curr].ino = stat_buf.st_ino;
1176 for (namep = name_space; *namep; namep += file_len - pathname_len + 1)
1178 /* Append this directory entry's name to the path being searched. */
1179 file_len = pathname_len + strlen (namep);
1180 if (file_len > cur_path_size)
1182 while (file_len > cur_path_size)
1183 cur_path_size += 1024;
1184 if (cur_path)
1185 free (cur_path);
1186 cur_path = xmalloc (cur_path_size);
1187 strcpy (cur_path, pathname);
1188 cur_path[pathname_len - 2] = '/';
1190 cur_name = cur_path + pathname_len - 1;
1191 strcpy (cur_name, namep);
1193 curdepth++;
1194 if (!no_leaf_check)
1195 /* Normal case optimization.
1196 On normal Unix filesystems, a directory that has no
1197 subdirectories has two links: its name, and ".". Any
1198 additional links are to the ".." entries of its
1199 subdirectories. Once we have processed as many
1200 subdirectories as there are additional links, we know
1201 that the rest of the entries are non-directories --
1202 in other words, leaf files. */
1203 subdirs_left -= process_path (cur_path, cur_name,
1204 subdirs_left == 0, pathname);
1205 else
1206 /* There might be weird (e.g., CD-ROM or MS-DOS) filesystems
1207 mounted, which don't have Unix-like directory link counts. */
1208 process_path (cur_path, cur_name, false, pathname);
1209 curdepth--;
1212 if (strcmp (name, "."))
1214 /* We could go back and do the next command-line arg
1215 instead, maybe using longjmp. */
1216 char const *dir;
1217 boolean deref = following_links() ? true : false;
1219 if (!deref)
1220 dir = "..";
1221 else
1223 chdir_back ();
1224 dir = parent;
1227 if (chdir (dir) != 0)
1228 error (1, errno, "%s", parent);
1230 /* Check that we are where we should be. */
1231 if (1)
1233 boolean changed = false;
1234 struct stat tmp;
1235 int problem_is_with_parent;
1237 memset(&tmp, 0, sizeof(tmp));
1238 if (dir_curr > 0)
1240 tmp.st_dev = dir_ids[dir_curr-1].dev;
1241 tmp.st_ino = dir_ids[dir_curr-1].ino;
1243 else
1245 tmp.st_dev = starting_stat_buf.st_dev;
1246 tmp.st_ino = starting_stat_buf.st_ino;
1249 problem_is_with_parent = deref ? 1 : 0;
1250 wd_sanity_check(pathname,
1251 program_name,
1252 parent,
1253 &tmp, &stat_buf,
1254 problem_is_with_parent, __LINE__,
1255 TraversingUp, &changed);
1259 if (cur_path)
1260 free (cur_path);
1261 free (name_space);
1265 #if 0
1266 /* Return true if there are no side effects in any of the predicates in
1267 predicate list PRED, false if there are any. */
1269 static boolean
1270 no_side_effects (struct predicate *pred)
1272 while (pred != NULL)
1274 if (pred->side_effects)
1275 return (false);
1276 pred = pred->pred_next;
1278 return (true);
1280 #endif
1282 /* Return true if there are no predicates with no_default_print in
1283 predicate list PRED, false if there are any.
1284 Returns true if default print should be performed */
1286 static boolean
1287 default_prints (struct predicate *pred)
1289 while (pred != NULL)
1291 if (pred->no_default_print)
1292 return (false);
1293 pred = pred->pred_next;
1295 return (true);