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)
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,
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>. */
37 #include "../gnulib/lib/human.h"
38 #include "../gnulib/lib/canonicalize.h"
40 #include "../gnulib/lib/savedir.h"
48 # define _(Text) gettext (Text)
51 #define textdomain(Domain)
52 #define bindtextdomain(Package, Directory)
55 # define N_(String) gettext_noop (String)
57 /* See locate.c for explanation as to why not use (String) */
58 # define N_(String) String
61 #define apply_predicate(pathname, stat_buf_ptr, node) \
62 (*(node)->pred_func)((pathname), (stat_buf_ptr), (node))
65 static void init_mounted_dev_list(void);
66 static void process_top_path
PARAMS((char *pathname
));
67 static int process_path
PARAMS((char *pathname
, char *name
, boolean leaf
, char *parent
));
68 static void process_dir
PARAMS((char *pathname
, char *name
, int pathlen
, struct stat
*statp
, char *parent
));
70 static boolean no_side_effects
PARAMS((struct predicate
*pred
));
72 static boolean default_prints
PARAMS((struct predicate
*pred
));
74 /* Name this program was run with. */
77 /* All predicates for each path to process. */
78 struct predicate
*predicates
;
80 /* The last predicate allocated. */
81 struct predicate
*last_pred
;
83 /* The root of the evaluation tree. */
84 static struct predicate
*eval_tree
;
86 /* If true, process directory before contents. True unless -depth given. */
89 /* If >=0, don't descend more than this many levels of subdirectories. */
92 /* If >=0, don't process files above this level. */
95 /* Current depth; 0 means current path is a command line arg. */
98 /* Output block size. */
99 int output_block_size
;
101 /* Time at start of execution. */
104 /* Seconds between 00:00 1/1/70 and either one day before now
105 (the default), or the start of today (if -daystart is given). */
106 time_t cur_day_start
;
108 /* If true, cur_day_start has been adjusted to the start of the day. */
111 /* If true, do not assume that files in directories with nlink == 2
112 are non-directories. */
113 boolean no_leaf_check
;
115 /* If true, don't cross filesystem boundaries. */
116 boolean stay_on_filesystem
;
118 /* If true, don't descend past current directory.
119 Can be set by -prune, -maxdepth, and -xdev/-mount. */
120 boolean stop_at_current_level
;
122 /* The full path of the initial working directory, or "." if
123 STARTING_DESC is nonnegative. */
124 char const *starting_dir
= ".";
126 /* A file descriptor open to the initial working directory.
127 Doing it this way allows us to work when the i.w.d. has
128 unreadable parents. */
131 /* The stat buffer of the initial working directory. */
132 struct stat starting_stat_buf
;
134 /* If true, we have called stat on the current path. */
137 /* The file being operated on, relative to the current directory.
138 Used for stat, readlink, remove, and opendir. */
141 /* Length of current path. */
144 /* true if following symlinks. Should be consistent with xstat. */
145 /* boolean dereference; */
146 enum SymlinkOption symlink_handling
;
149 /* Pointer to the function used to stat files. */
152 /* Status value to return to system. */
155 /* If true, we ignore the problem where we find that a directory entry
156 * no longer exists by the time we get around to processing it.
158 boolean ignore_readdir_race
;
161 /* If true, we issue warning messages
166 enum TraversalDirection
174 following_links(void)
176 switch (symlink_handling
)
178 case SYMLINK_ALWAYS_DEREF
:
180 case SYMLINK_DEREF_ARGSONLY
:
181 return (curdepth
== 0);
182 case SYMLINK_NEVER_DEREF
:
188 /* optionh_stat() implements the stat operation when the -H option is
191 * If the item to be examined is a command-line argument, we follow
192 * symbolic links. If the stat() call fails on the command-line item,
193 * we fall back on the properties of the symbolic link.
195 * If the item to be examined is not a command-line argument, we
196 * examine the link itself.
199 optionh_stat(const char *name
, struct stat
*p
)
203 /* This file is from the command line; deference the link (if it
206 if (0 == stat(name
, p
))
213 /* fallback - return the information for the link itself. */
214 return lstat(name
, p
);
219 /* Not a file on the command line; do not derefernce the link.
221 return lstat(name
, p
);
225 /* optionl_stat() implements the stat operation when the -L option is
226 * in effect. That option makes us examine the thing the symbolic
227 * link points to, not the symbolic link itself.
230 optionl_stat(const char *name
, struct stat
*p
)
232 if (0 == stat(name
, p
))
234 return 0; /* normal case. */
238 return lstat(name
, p
); /* can't follow link, return the link itself. */
242 /* optionp_stat() implements the stat operation when the -P option is
243 * in effect (this is also the default). That option makes us examine
244 * the symbolic link itself, not the thing it points to.
247 optionp_stat(const char *name
, struct stat
*p
)
249 return lstat(name
, p
);
254 debug_stat (const char *file
, struct stat
*bufp
)
256 fprintf (stderr
, "debug_stat (%s)\n", file
);
257 switch (symlink_handling
)
259 case SYMLINK_ALWAYS_DEREF
:
260 return optionl_stat(file
, bufp
);
261 case SYMLINK_DEREF_ARGSONLY
:
262 return optionh_stat(file
, bufp
);
263 case SYMLINK_NEVER_DEREF
:
264 return optionp_stat(file
, bufp
);
267 #endif /* DEBUG_STAT */
270 set_follow_state(enum SymlinkOption opt
)
274 case SYMLINK_ALWAYS_DEREF
: /* -L */
275 xstat
= optionl_stat
;
276 no_leaf_check
= false;
279 case SYMLINK_NEVER_DEREF
: /* -P (default) */
280 xstat
= optionp_stat
;
281 /* Can't turn on no_leaf_check because the user might have specified
286 case SYMLINK_DEREF_ARGSONLY
: /* -H */
287 xstat
= optionh_stat
;
288 no_leaf_check
= true;
291 /* For DBEUG_STAT, the choice is made at runtime within debug_stat()
292 * by checking the contents of the symlink_handling variable.
294 #if defined(DEBUG_STAT)
296 #endif /* !DEBUG_STAT */
301 main (int argc
, char **argv
)
304 PFB parse_function
; /* Pointer to the function which parses. */
305 struct predicate
*cur_pred
;
306 char *predicate_name
; /* Name of predicate being parsed. */
307 int end_of_leading_options
= 0; /* First arg after any -H/-L etc. */
308 program_name
= argv
[0];
310 #ifdef HAVE_SETLOCALE
311 setlocale (LC_ALL
, "");
313 bindtextdomain (PACKAGE
, LOCALEDIR
);
314 textdomain (PACKAGE
);
329 maxdepth
= mindepth
= -1;
330 start_time
= time (NULL
);
331 cur_day_start
= start_time
- DAYSECS
;
333 no_leaf_check
= false;
334 stay_on_filesystem
= false;
335 ignore_readdir_race
= false;
338 #if defined(DEBUG_STAT)
340 #endif /* !DEBUG_STAT */
343 human_block_size (getenv ("FIND_BLOCK_SIZE"), 0, &output_block_size
);
345 if (getenv("POSIXLY_CORRECT"))
346 output_block_size
= 512;
348 output_block_size
= 1024;
350 if (getenv("FIND_BLOCK_SIZE"))
352 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"));
355 set_follow_state(SYMLINK_NEVER_DEREF
); /* The default is equivalent to -P. */
357 init_mounted_dev_list();
362 printf ("cur_day_start = %s", ctime (&cur_day_start
));
365 /* Check for -P, -H or -L options. */
366 for (i
=1; (end_of_leading_options
= i
) < argc
; ++i
)
368 if (0 == strcmp("-H", argv
[i
]))
370 /* Meaning: dereference symbolic links on command line, but nowhere else. */
371 set_follow_state(SYMLINK_DEREF_ARGSONLY
);
373 else if (0 == strcmp("-L", argv
[i
]))
375 /* Meaning: dereference all symbolic links. */
376 set_follow_state(SYMLINK_ALWAYS_DEREF
);
378 else if (0 == strcmp("-P", argv
[i
]))
380 /* Meaning: never dereference symbolic links (default). */
381 set_follow_state(SYMLINK_NEVER_DEREF
);
383 else if (0 == strcmp("--", argv
[i
]))
385 /* -- signifies the end of options. */
386 end_of_leading_options
= i
+1; /* Next time start with the next option */
391 /* Hmm, must be one of
395 end_of_leading_options
= i
; /* Next time start with this option */
400 /* We are now processing the part of the "find" command line
401 * after the -H/-L options (if any).
404 /* fprintf(stderr, "rest: optind=%ld\n", (long)optind); */
406 /* Find where in ARGV the predicates begin. */
407 for (i
= end_of_leading_options
; i
< argc
&& strchr ("-!(),", argv
[i
][0]) == NULL
; i
++)
409 /* fprintf(stderr, "Looks like %s is not a predicate\n", argv[i]); */
413 /* Enclose the expression in `( ... )' so a default -print will
414 apply to the whole expression. */
415 parse_open (argv
, &argc
);
416 /* Build the input order list. */
419 if (strchr ("-!(),", argv
[i
][0]) == NULL
)
420 usage (_("paths must precede expression"));
421 predicate_name
= argv
[i
];
422 parse_function
= find_parser (predicate_name
);
423 if (parse_function
== NULL
)
424 /* Command line option not recognized */
425 error (1, 0, _("invalid predicate `%s'"), predicate_name
);
427 if (!(*parse_function
) (argv
, &i
))
430 /* Command line option requires an argument */
431 error (1, 0, _("missing argument to `%s'"), predicate_name
);
433 error (1, 0, _("invalid argument `%s' to `%s'"),
434 argv
[i
], predicate_name
);
437 if (predicates
->pred_next
== NULL
)
439 /* No predicates that do something other than set a global variable
440 were given; remove the unneeded initial `(' and add `-print'. */
441 cur_pred
= predicates
;
442 predicates
= last_pred
= predicates
->pred_next
;
443 free ((char *) cur_pred
);
444 parse_print (argv
, &argc
);
446 else if (!default_prints (predicates
->pred_next
))
448 /* One or more predicates that produce output were given;
449 remove the unneeded initial `('. */
450 cur_pred
= predicates
;
451 predicates
= predicates
->pred_next
;
452 free ((char *) cur_pred
);
456 /* `( user-supplied-expression ) -print'. */
457 parse_close (argv
, &argc
);
458 parse_print (argv
, &argc
);
462 printf (_("Predicate List:\n"));
463 print_list (predicates
);
466 /* Done parsing the predicates. Build the evaluation tree. */
467 cur_pred
= predicates
;
468 eval_tree
= get_expr (&cur_pred
, NO_PREC
);
470 /* Check if we have any left-over predicates (this fixes
471 * Debian bug #185202).
473 if (cur_pred
!= NULL
)
475 error (1, 0, _("unexpected extra predicate"));
479 printf (_("Eval Tree:\n"));
480 print_tree (eval_tree
, 0);
483 /* Rearrange the eval tree in optimal-predicate order. */
484 opt_expr (&eval_tree
);
486 /* Determine the point, if any, at which to stat the file. */
487 mark_stat (eval_tree
);
490 printf (_("Optimized Eval Tree:\n"));
491 print_tree (eval_tree
, 0);
494 starting_desc
= open (".", O_RDONLY
);
495 if (0 <= starting_desc
&& fchdir (starting_desc
) != 0)
497 close (starting_desc
);
500 if (starting_desc
< 0)
502 starting_dir
= xgetcwd ();
504 error (1, errno
, _("cannot get current directory"));
506 if ((*xstat
) (".", &starting_stat_buf
) != 0)
507 error (1, errno
, _("cannot get current directory"));
509 /* If no paths are given, default to ".". */
510 for (i
= end_of_leading_options
; i
< argc
&& strchr ("-!(),", argv
[i
][0]) == NULL
; i
++)
512 process_top_path (argv
[i
]);
515 /* If there were no path arguments, default to ".". */
516 if (i
== end_of_leading_options
)
519 * We use a temporary variable here because some actions modify
520 * the path temporarily. Hence if we use a string constant,
521 * we get a coredump. The best example of this is if we say
522 * "find -printf %H" (note, not "find . -printf %H").
524 char defaultpath
[2] = ".";
525 process_top_path (defaultpath
);
534 specific_dirname(const char *dir
)
538 if (0 == strcmp(".", dir
))
540 /* OK, what's '.'? */
541 if (NULL
!= getcwd(dirname
, sizeof(dirname
)))
543 return strdup(dirname
);
552 return canonicalize_filename_mode(dir
, CAN_EXISTING
);
560 /* list_item_present: Search for NEEDLE in HAYSTACK.
562 * NEEDLE is a normal C string. HAYSTACK is a list of concatenated C strings,
563 * each with a terminating NUL. The last item in the list is identified by
564 * the fact that its terminating NUL is itself followed by a second NUL.
566 * This data structure does not lend itself to fast searching, but we only
567 * do this when wd_sanity_check() thinks that a filesystem might have been
568 * mounted or unmounted. That doesn't happen very often.
571 list_item_present(const char *needle
, const char *haystack
)
573 if (NULL
!= haystack
)
575 const char *s
= haystack
;
578 if (0 == strcmp(s
, needle
))
585 ++s
; /* skip the first NUL. */
592 static char *mount_points
= NULL
;
595 /* Initialise our idea of what the list of mount points is.
596 * this function is called exactly once.
599 init_mount_point_list(void)
601 assert(NULL
== mount_points
);
602 mount_points
= get_mounted_filesystems();
606 refresh_mount_point_list(void)
613 init_mount_point_list();
616 /* Determine if a directory has recently had a filesystem
617 * mounted on it or unmounted from it.
619 static enum MountPointStateChange
620 get_mount_point_state(const char *dir
)
622 int was_mounted
, is_mounted
;
624 was_mounted
= list_item_present(dir
, mount_points
);
625 refresh_mount_point_list();
626 is_mounted
= list_item_present(dir
, mount_points
);
628 if (was_mounted
== is_mounted
)
629 return MountPointStateUnchanged
;
631 return MountPointRecentlyMounted
;
633 return MountPointRecentlyUnmounted
;
639 static dev_t
*mounted_devices
= NULL
;
640 static size_t num_mounted_devices
= 0u;
644 init_mounted_dev_list()
646 assert(NULL
== mounted_devices
);
647 assert(0 == num_mounted_devices
);
648 mounted_devices
= get_mounted_devices(&num_mounted_devices
);
652 refresh_mounted_dev_list(void)
656 free(mounted_devices
);
659 num_mounted_devices
= 0u;
660 init_mounted_dev_list();
664 /* Search for device DEV in the array LIST, which is of size N. */
666 dev_present(dev_t dev
, const dev_t
*list
, size_t n
)
672 if ( (*list
++) == dev
)
679 enum MountPointStateChange
681 MountPointRecentlyMounted
,
682 MountPointRecentlyUnmounted
,
683 MountPointStateUnchanged
688 static enum MountPointStateChange
689 get_mount_state(dev_t newdev
)
691 int new_is_present
, new_was_present
;
693 new_was_present
= dev_present(newdev
, mounted_devices
, num_mounted_devices
);
694 refresh_mounted_dev_list();
695 new_is_present
= dev_present(newdev
, mounted_devices
, num_mounted_devices
);
697 if (new_was_present
== new_is_present
)
698 return MountPointStateUnchanged
;
699 else if (new_is_present
)
700 return MountPointRecentlyMounted
;
702 return MountPointRecentlyUnmounted
;
707 /* Examine the results of the stat() of a directory from before we
708 * entered or left it, with the results of stat()ing it afterward. If
709 * these are different, the filesystem tree has been modified while we
710 * were traversing it. That might be an attempt to use a race
711 * condition to persuade find to do something it didn't intend
712 * (e.g. an attempt by an ordinary user to exploit the fact that root
713 * sometimes runs find on the whole filesystem). However, this can
714 * also happen if automount is running (certainly on Solaris). With
715 * automount, moving into a directory can cause a filesystem to be
718 * To cope sensibly with this, we will raise an error if we see the
719 * device number change unless we are chdir()ing into a subdirectory,
720 * and the directory we moved into has been mounted or unmounted "recently".
721 * Here "recently" means since we started "find" or we last re-read
722 * the /etc/mnttab file.
724 * If the device number does not change but the inode does, that is a
727 * If the device number and inode are both the same, we are happy.
729 * If a filesystem is (un)mounted as we chdir() into the directory, that
730 * may mean that we're now examining a section of the filesystem that might
731 * have been excluded from consideration (via -prune or -quit for example).
732 * Hence we print a warning message to indicate that the output of find
733 * might be inconsistent due to the change in the filesystem.
736 wd_sanity_check(const char *thing_to_stat
,
737 const char *program_name
,
739 const struct stat
*oldinfo
,
740 struct stat
*newinfo
,
743 enum TraversalDirection direction
)
746 char *specific_what
= NULL
;
750 if ((*xstat
) (".", newinfo
) != 0)
751 error (1, errno
, "%s", thing_to_stat
);
753 if (oldinfo
->st_dev
!= newinfo
->st_dev
)
755 specific_what
= specific_dirname(what
);
757 /* This condition is rare, so once we are here it is
758 * reasonable to perform an expensive computation to
759 * determine if we should continue or fail.
761 if (1 || TraversingDown
== direction
)
763 /* We stat()ed a directory, chdir()ed into it (we know this
764 * since direction is TraversingDown), stat()ed it again,
765 * and noticed that the device numbers are different. Check
766 * if the filesystem was recently mounted.
768 * If it was, it looks like chdir()ing into the directory
769 * caused a filesystem to be mounted. Maybe automount is
770 * running. Anyway, that's probably OK - but it happens
771 * only when we are moving downward.
773 * We also allow for the possibility that a similar thing
774 * has happened with the unmounting of a filesystem. This
775 * is much rarer, as it relies on an automounter timeout
776 * occurring at exactly the wrong moment.
778 enum MountPointStateChange transition
= get_mount_state(newinfo
->st_dev
);
781 case MountPointRecentlyUnmounted
:
784 _("Warning: filesystem %s has recently been unmounted."),
788 case MountPointRecentlyMounted
:
791 _("Warning: filesystem %s has recently been mounted."),
795 case MountPointStateUnchanged
:
803 fstype
= filesystem_type(thing_to_stat
, ".", newinfo
);
805 _("%s%s changed during execution of %s (old device number %ld, new device number %ld, filesystem type is %s) [ref %ld]"),
809 (long) oldinfo
->st_dev
,
810 (long) newinfo
->st_dev
,
816 /* Since the device has changed under us, the inode number
817 * will almost certainly also be different. However, we have
818 * already decided that this is not a problem. Hence we return
819 * without checking the inode number.
826 /* Device number was the same, check if the inode has changed. */
827 if (oldinfo
->st_ino
!= newinfo
->st_ino
)
829 specific_what
= specific_dirname(what
);
830 fstype
= filesystem_type(thing_to_stat
, ".", newinfo
);
833 _("%s%s changed during execution of %s (old inode number %ld, new inode number %ld, filesystem type is %s) [ref %ld]"),
837 (long) oldinfo
->st_ino
,
838 (long) newinfo
->st_ino
,
848 SafeChdirFailSymlink
,
853 /* Safely perform a change in directory. */
855 safely_chdir(const char *dest
, enum TraversalDirection direction
)
857 struct stat statbuf_dest
, statbuf_arrived
;
858 int rv
=SafeChdirFailDefect
, dotfd
=-1;
862 dotfd
= open(".", O_RDONLY
);
865 /* Stat the directory we're going to. */
866 if (0 == (following_links() ? stat
: lstat
)(dest
, &statbuf_dest
))
869 if (!following_links() && S_ISLNK(statbuf_dest
.st_mode
))
871 rv
= SafeChdirFailSymlink
;
879 rv
= SafeChdirFailStat
;
880 name
= specific_dirname(dest
);
892 name
= specific_dirname(".");
893 error(0, errno
, "%s", name
);
908 /* Safely go back to the starting directory. */
912 struct stat stat_buf
;
914 if (starting_desc
< 0)
916 if (chdir (starting_dir
) != 0)
917 error (1, errno
, "%s", starting_dir
);
919 wd_sanity_check(starting_dir
,
920 program_name
, starting_dir
,
921 &starting_stat_buf
, &stat_buf
, 0, __LINE__
,
926 if (fchdir (starting_desc
) != 0)
927 error (1, errno
, "%s", starting_dir
);
931 /* Descend PATHNAME, which is a command-line argument. */
934 process_top_path (char *pathname
)
936 struct stat stat_buf
, cur_stat_buf
;
939 path_length
= strlen (pathname
);
941 /* We stat each pathname given on the command-line twice --
942 once here and once in process_path. It's not too bad, though,
943 since the kernel can read the stat information out of its inode
944 cache the second time. */
945 if ((*xstat
) (pathname
, &stat_buf
) == 0 && S_ISDIR (stat_buf
.st_mode
))
947 if (chdir (pathname
) < 0)
949 if (!ignore_readdir_race
|| (errno
!= ENOENT
) )
951 error (0, errno
, "%s", pathname
);
957 /* Check that we are where we should be. */
958 wd_sanity_check(pathname
, program_name
,
960 &stat_buf
, &cur_stat_buf
, 0, __LINE__
,
963 process_path (pathname
, ".", false, ".");
967 process_path (pathname
, pathname
, false, ".");
970 /* Info on each directory in the current tree branch, to avoid
971 getting stuck in symbolic link loops. */
977 static struct dir_id
*dir_ids
= NULL
;
978 /* Entries allocated in `dir_ids'. */
979 static int dir_alloc
= 0;
980 /* Index in `dir_ids' of directory currently being searched.
981 This is always the last valid entry. */
982 static int dir_curr
= -1;
983 /* (Arbitrary) number of entries to grow `dir_ids' by. */
984 #define DIR_ALLOC_STEP 32
986 /* Recursively descend path PATHNAME, applying the predicates.
987 LEAF is true if PATHNAME is known to be in a directory that has no
988 more unexamined subdirectories, and therefore it is not a directory.
989 Knowing this allows us to avoid calling stat as long as possible for
992 NAME is PATHNAME relative to the current directory. We access NAME
995 PARENT is the path of the parent of NAME, relative to find's
998 Return nonzero iff PATHNAME is a directory. */
1001 process_path (char *pathname
, char *name
, boolean leaf
, char *parent
)
1003 struct stat stat_buf
;
1004 static dev_t root_dev
; /* Device ID of current argument pathname. */
1007 /* Assume it is a non-directory initially. */
1008 stat_buf
.st_mode
= 0;
1010 rel_pathname
= name
;
1016 if ((*xstat
) (name
, &stat_buf
) != 0)
1018 if (!ignore_readdir_race
|| (errno
!= ENOENT
) )
1020 error (0, errno
, "%s", pathname
);
1028 if (!S_ISDIR (stat_buf
.st_mode
))
1030 if (curdepth
>= mindepth
)
1031 apply_predicate (pathname
, &stat_buf
, eval_tree
);
1035 /* From here on, we're working on a directory. */
1037 stop_at_current_level
= maxdepth
>= 0 && curdepth
>= maxdepth
;
1039 /* If we've already seen this directory on this branch,
1040 don't descend it again. */
1041 for (i
= 0; i
<= dir_curr
; i
++)
1042 if (stat_buf
.st_ino
== dir_ids
[i
].ino
&&
1043 stat_buf
.st_dev
== dir_ids
[i
].dev
)
1044 stop_at_current_level
= true;
1046 if (dir_alloc
<= ++dir_curr
)
1048 dir_alloc
+= DIR_ALLOC_STEP
;
1049 dir_ids
= (struct dir_id
*)
1050 xrealloc ((char *) dir_ids
, dir_alloc
* sizeof (struct dir_id
));
1052 dir_ids
[dir_curr
].ino
= stat_buf
.st_ino
;
1053 dir_ids
[dir_curr
].dev
= stat_buf
.st_dev
;
1055 if (stay_on_filesystem
)
1058 root_dev
= stat_buf
.st_dev
;
1059 else if (stat_buf
.st_dev
!= root_dev
)
1060 stop_at_current_level
= true;
1063 if (do_dir_first
&& curdepth
>= mindepth
)
1064 apply_predicate (pathname
, &stat_buf
, eval_tree
);
1067 fprintf(stderr
, "pathname = %s, stop_at_current_level = %d\n",
1068 pathname
, stop_at_current_level
);
1071 if (stop_at_current_level
== false)
1072 /* Scan directory on disk. */
1073 process_dir (pathname
, name
, strlen (pathname
), &stat_buf
, parent
);
1075 if (do_dir_first
== false && curdepth
>= mindepth
)
1077 rel_pathname
= name
;
1078 apply_predicate (pathname
, &stat_buf
, eval_tree
);
1086 /* Scan directory PATHNAME and recurse through process_path for each entry.
1088 PATHLEN is the length of PATHNAME.
1090 NAME is PATHNAME relative to the current directory.
1092 STATP is the results of *xstat on it.
1094 PARENT is the path of the parent of NAME, relative to find's
1095 starting directory. */
1098 process_dir (char *pathname
, char *name
, int pathlen
, struct stat
*statp
, char *parent
)
1100 char *name_space
; /* Names of files in PATHNAME. */
1101 int subdirs_left
; /* Number of unexamined subdirs in PATHNAME. */
1102 struct stat stat_buf
;
1104 subdirs_left
= statp
->st_nlink
- 2; /* Account for name and ".". */
1107 name_space
= savedir (name
);
1108 if (name_space
== NULL
)
1112 error (0, errno
, "%s", pathname
);
1116 error (1, 0, _("virtual memory exhausted"));
1120 register char *namep
; /* Current point in `name_space'. */
1121 char *cur_path
; /* Full path of each file to process. */
1122 char *cur_name
; /* Base name of each file to process. */
1123 unsigned cur_path_size
; /* Bytes allocated for `cur_path'. */
1124 register unsigned file_len
; /* Length of each path to process. */
1125 register unsigned pathname_len
; /* PATHLEN plus trailing '/'. */
1127 if (pathname
[pathlen
- 1] == '/')
1128 pathname_len
= pathlen
+ 1; /* For '\0'; already have '/'. */
1130 pathname_len
= pathlen
+ 2; /* For '/' and '\0'. */
1134 if (strcmp (name
, ".") && chdir (name
) < 0)
1136 error (0, errno
, "%s", pathname
);
1141 /* Check that we are where we should be. */
1144 struct stat tmp
= {0};
1145 tmp
.st_dev
= dir_ids
[dir_curr
].dev
;
1146 tmp
.st_ino
= dir_ids
[dir_curr
].ino
;
1147 wd_sanity_check(pathname
,
1150 &tmp
, &stat_buf
, 0, __LINE__
,
1154 for (namep
= name_space
; *namep
; namep
+= file_len
- pathname_len
+ 1)
1156 /* Append this directory entry's name to the path being searched. */
1157 file_len
= pathname_len
+ strlen (namep
);
1158 if (file_len
> cur_path_size
)
1160 while (file_len
> cur_path_size
)
1161 cur_path_size
+= 1024;
1164 cur_path
= xmalloc (cur_path_size
);
1165 strcpy (cur_path
, pathname
);
1166 cur_path
[pathname_len
- 2] = '/';
1168 cur_name
= cur_path
+ pathname_len
- 1;
1169 strcpy (cur_name
, namep
);
1173 /* Normal case optimization.
1174 On normal Unix filesystems, a directory that has no
1175 subdirectories has two links: its name, and ".". Any
1176 additional links are to the ".." entries of its
1177 subdirectories. Once we have processed as many
1178 subdirectories as there are additional links, we know
1179 that the rest of the entries are non-directories --
1180 in other words, leaf files. */
1181 subdirs_left
-= process_path (cur_path
, cur_name
,
1182 subdirs_left
== 0, pathname
);
1184 /* There might be weird (e.g., CD-ROM or MS-DOS) filesystems
1185 mounted, which don't have Unix-like directory link counts. */
1186 process_path (cur_path
, cur_name
, false, pathname
);
1190 if (strcmp (name
, "."))
1192 /* We could go back and do the next command-line arg
1193 instead, maybe using longjmp. */
1196 if (symlink_handling
== SYMLINK_ALWAYS_DEREF
)
1198 else if (symlink_handling
== SYMLINK_DEREF_ARGSONLY
&& (curdepth
== 0))
1211 if (chdir (dir
) != 0)
1212 error (1, errno
, "%s", parent
);
1214 /* Check that we are where we should be. */
1218 int problem_is_with_parent
;
1222 tmp
.st_dev
= dir_ids
[dir_curr
-1].dev
;
1223 tmp
.st_ino
= dir_ids
[dir_curr
-1].ino
;
1227 tmp
.st_dev
= starting_stat_buf
.st_dev
;
1228 tmp
.st_ino
= starting_stat_buf
.st_ino
;
1231 problem_is_with_parent
= deref
? 1 : 0;
1232 wd_sanity_check(pathname
,
1234 deref
? parent
: starting_dir
,
1236 problem_is_with_parent
, __LINE__
,
1248 /* Return true if there are no side effects in any of the predicates in
1249 predicate list PRED, false if there are any. */
1252 no_side_effects (struct predicate
*pred
)
1254 while (pred
!= NULL
)
1256 if (pred
->side_effects
)
1258 pred
= pred
->pred_next
;
1264 /* Return true if there are no predicates with no_default_print in
1265 predicate list PRED, false if there are any.
1266 Returns true if default print should be performed */
1269 default_prints (struct predicate
*pred
)
1271 while (pred
!= NULL
)
1273 if (pred
->no_default_print
)
1275 pred
= pred
->pred_next
;