source: trunk/essentials/sys-apps/findutils/find/find.c

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

silly!

File size: 38.9 KB
Line 
1/* find -- search for files in a directory hierarchy
2 Copyright (C) 1990, 91, 92, 93, 94, 2000,
3 2003, 2004, 2005 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
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
18 USA.*/
19
20/* GNU find was written by Eric Decker <cire@cisco.com>,
21 with enhancements by David MacKenzie <djm@gnu.org>,
22 Jay Plett <jay@silence.princeton.nj.us>,
23 and Tim Wood <axolotl!tim@toad.com>.
24 The idea for -print0 and xargs -0 came from
25 Dan Bernstein <brnstnd@kramden.acf.nyu.edu>.
26 Improvements have been made by James Youngman <jay@gnu.org>.
27*/
28
29
30#include "defs.h"
31
32#define USE_SAFE_CHDIR 1
33#undef STAT_MOUNTPOINTS
34
35
36#include <errno.h>
37#include <assert.h>
38
39
40#ifdef HAVE_FCNTL_H
41#include <fcntl.h>
42#else
43#include <sys/file.h>
44#endif
45
46#include "../gnulib/lib/xalloc.h"
47#include "../gnulib/lib/human.h"
48#include "../gnulib/lib/canonicalize.h"
49#include "closeout.h"
50#include <modetype.h>
51#include "savedirinfo.h"
52#include "buildcmd.h"
53#include "dirname.h"
54#include "quote.h"
55#include "quotearg.h"
56
57#ifdef HAVE_LOCALE_H
58#include <locale.h>
59#endif
60
61#if ENABLE_NLS
62# include <libintl.h>
63# define _(Text) gettext (Text)
64#else
65# define _(Text) Text
66#define textdomain(Domain)
67#define bindtextdomain(Package, Directory)
68#endif
69#ifdef gettext_noop
70# define N_(String) gettext_noop (String)
71#else
72/* See locate.c for explanation as to why not use (String) */
73# define N_(String) String
74#endif
75
76#define apply_predicate(pathname, stat_buf_ptr, node) \
77 (*(node)->pred_func)((pathname), (stat_buf_ptr), (node))
78
79#ifdef STAT_MOUNTPOINTS
80static void init_mounted_dev_list(int mandatory);
81#endif
82
83static void process_top_path PARAMS((char *pathname, mode_t mode));
84static int process_path PARAMS((char *pathname, char *name, boolean leaf, char *parent, mode_t type));
85static void process_dir PARAMS((char *pathname, char *name, int pathlen, struct stat *statp, char *parent));
86
87
88
89/* Name this program was run with. */
90char *program_name;
91
92/* A file descriptor open to the initial working directory.
93 Doing it this way allows us to work when the i.w.d. has
94 unreadable parents. */
95int starting_desc;
96
97/* The stat buffer of the initial working directory. */
98static struct stat starting_stat_buf;
99
100enum ChdirSymlinkHandling
101 {
102 SymlinkHandleDefault, /* Normally the right choice */
103 SymlinkFollowOk /* see comment in process_top_path() */
104 };
105
106
107enum TraversalDirection
108 {
109 TraversingUp,
110 TraversingDown
111 };
112
113enum WdSanityCheckFatality
114 {
115 FATAL_IF_SANITY_CHECK_FAILS,
116 RETRY_IF_SANITY_CHECK_FAILS,
117 NON_FATAL_IF_SANITY_CHECK_FAILS
118 };
119
120
121
122int
123main (int argc, char **argv)
124{
125 int i;
126 int end_of_leading_options = 0; /* First arg after any -H/-L etc. */
127 struct predicate *eval_tree;
128
129 program_name = argv[0];
130 state.exit_status = 0;
131
132 /* Set the option defaults before we do the the locale
133 * initialisation as check_nofollow() needs to be executed in the
134 * POSIX locale.
135 */
136 set_option_defaults(&options);
137
138#ifdef HAVE_SETLOCALE
139 setlocale (LC_ALL, "");
140#endif
141 bindtextdomain (PACKAGE, LOCALEDIR);
142 textdomain (PACKAGE);
143 atexit (close_stdout);
144
145 /* Check for -P, -H or -L options. */
146 end_of_leading_options = process_leading_options(argc, argv);
147
148 if (options.debug_options & DebugStat)
149 options.xstat = debug_stat;
150
151#ifdef DEBUG
152/* fprintf (stderr, "cur_day_start = %s", ctime (&p->cur_day_start)); - what's "p"? */
153#endif /* DEBUG */
154
155 /* We are now processing the part of the "find" command line
156 * after the -H/-L options (if any).
157 */
158 eval_tree = build_expression_tree(argc, argv, end_of_leading_options);
159
160
161 /* safely_chdir() needs to check that it has ended up in the right place.
162 * To avoid bailing out when something gets automounted, it checks if
163 * the target directory appears to have had a directory mounted on it as
164 * we chdir()ed. The problem with this is that in order to notice that
165 * a filesystem was mounted, we would need to lstat() all the mount points.
166 * That strategy loses if our machine is a client of a dead NFS server.
167 *
168 * Hence if safely_chdir() and wd_sanity_check() can manage without needing
169 * to know the mounted device list, we do that.
170 */
171 if (!options.open_nofollow_available)
172 {
173#ifdef STAT_MOUNTPOINTS
174 init_mounted_dev_list(0);
175#endif
176 }
177
178
179 starting_desc = open (".", O_RDONLY);
180 if (0 <= starting_desc && fchdir (starting_desc) != 0)
181 {
182 close (starting_desc);
183 starting_desc = -1;
184 }
185 if (starting_desc < 0)
186 {
187 starting_dir = xgetcwd ();
188 if (! starting_dir)
189 error (1, errno, _("cannot get current directory"));
190 }
191 if ((*options.xstat) (".", &starting_stat_buf) != 0)
192 error (1, errno, _("cannot get current directory"));
193
194 /* If no paths are given, default to ".". */
195 for (i = end_of_leading_options; i < argc && !looks_like_expression(argv[i], true); i++)
196 {
197 process_top_path (argv[i], 0);
198 }
199
200 /* If there were no path arguments, default to ".". */
201 if (i == end_of_leading_options)
202 {
203 /*
204 * We use a temporary variable here because some actions modify
205 * the path temporarily. Hence if we use a string constant,
206 * we get a coredump. The best example of this is if we say
207 * "find -printf %H" (note, not "find . -printf %H").
208 */
209 char defaultpath[2] = ".";
210 process_top_path (defaultpath, 0);
211 }
212
213 /* If "-exec ... {} +" has been used, there may be some
214 * partially-full command lines which have been built,
215 * but which are not yet complete. Execute those now.
216 */
217 cleanup();
218 return state.exit_status;
219}
220
221
222boolean is_fts_enabled()
223{
224 /* this version of find (i.e. this main()) does not use fts. */
225 return false;
226}
227
228
229
230static char *
231specific_dirname(const char *dir)
232{
233 char dirbuf[1024];
234
235 if (0 == strcmp(".", dir))
236 {
237 /* OK, what's '.'? */
238 if (NULL != getcwd(dirbuf, sizeof(dirbuf)))
239 {
240 return strdup(dirbuf);
241 }
242 else
243 {
244 return strdup(dir);
245 }
246 }
247 else
248 {
249 char *result = canonicalize_filename_mode(dir, CAN_EXISTING);
250 if (NULL == result)
251 return strdup(dir);
252 else
253 return result;
254 }
255}
256
257
258
259
260/* Return non-zero if FS is the name of a filesystem that is likely to
261 * be automounted
262 */
263static int
264fs_likely_to_be_automounted(const char *fs)
265{
266 return ( (0==strcmp(fs, "nfs")) || (0==strcmp(fs, "autofs")) || (0==strcmp(fs, "subfs")));
267}
268
269
270
271#ifdef STAT_MOUNTPOINTS
272static dev_t *mounted_devices = NULL;
273static size_t num_mounted_devices = 0u;
274
275
276static void
277init_mounted_dev_list(int mandatory)
278{
279 assert(NULL == mounted_devices);
280 assert(0 == num_mounted_devices);
281 mounted_devices = get_mounted_devices(&num_mounted_devices);
282 if (mandatory && (NULL == mounted_devices))
283 {
284 error(1, 0, "Cannot read list of mounted devices.");
285 }
286}
287
288static void
289refresh_mounted_dev_list(void)
290{
291 if (mounted_devices)
292 {
293 free(mounted_devices);
294 mounted_devices = 0;
295 }
296 num_mounted_devices = 0u;
297 init_mounted_dev_list(1);
298}
299
300
301/* Search for device DEV in the array LIST, which is of size N. */
302static int
303dev_present(dev_t dev, const dev_t *list, size_t n)
304{
305 if (list)
306 {
307 while (n-- > 0u)
308 {
309 if ( (*list++) == dev )
310 return 1;
311 }
312 }
313 return 0;
314}
315
316enum MountPointStateChange
317 {
318 MountPointRecentlyMounted,
319 MountPointRecentlyUnmounted,
320 MountPointStateUnchanged
321 };
322
323
324
325static enum MountPointStateChange
326get_mount_state(dev_t newdev)
327{
328 int new_is_present, new_was_present;
329
330 new_was_present = dev_present(newdev, mounted_devices, num_mounted_devices);
331 refresh_mounted_dev_list();
332 new_is_present = dev_present(newdev, mounted_devices, num_mounted_devices);
333
334 if (new_was_present == new_is_present)
335 return MountPointStateUnchanged;
336 else if (new_is_present)
337 return MountPointRecentlyMounted;
338 else
339 return MountPointRecentlyUnmounted;
340}
341
342
343
344/* We stat()ed a directory, chdir()ed into it (we know this
345 * since direction is TraversingDown), stat()ed it again,
346 * and noticed that the device numbers are different. Check
347 * if the filesystem was recently mounted.
348 *
349 * If it was, it looks like chdir()ing into the directory
350 * caused a filesystem to be mounted. Maybe automount is
351 * running. Anyway, that's probably OK - but it happens
352 * only when we are moving downward.
353 *
354 * We also allow for the possibility that a similar thing
355 * has happened with the unmounting of a filesystem. This
356 * is much rarer, as it relies on an automounter timeout
357 * occurring at exactly the wrong moment.
358 */
359static enum WdSanityCheckFatality
360dirchange_is_fatal(const char *specific_what,
361 enum WdSanityCheckFatality isfatal,
362 int silent,
363 struct stat *newinfo)
364{
365 enum MountPointStateChange transition = get_mount_state(newinfo->st_dev);
366 switch (transition)
367 {
368 case MountPointRecentlyUnmounted:
369 isfatal = NON_FATAL_IF_SANITY_CHECK_FAILS;
370 if (!silent)
371 {
372 error (0, 0,
373 _("Warning: filesystem %s has recently been unmounted."),
374 specific_what);
375 }
376 break;
377
378 case MountPointRecentlyMounted:
379 isfatal = NON_FATAL_IF_SANITY_CHECK_FAILS;
380 if (!silent)
381 {
382 error (0, 0,
383 _("Warning: filesystem %s has recently been mounted."),
384 specific_what);
385 }
386 break;
387
388 case MountPointStateUnchanged:
389 /* leave isfatal as it is */
390 break;
391 }
392
393 return isfatal;
394}
395
396
397#endif
398
399
400
401/* Examine the results of the stat() of a directory from before we
402 * entered or left it, with the results of stat()ing it afterward. If
403 * these are different, the filesystem tree has been modified while we
404 * were traversing it. That might be an attempt to use a race
405 * condition to persuade find to do something it didn't intend
406 * (e.g. an attempt by an ordinary user to exploit the fact that root
407 * sometimes runs find on the whole filesystem). However, this can
408 * also happen if automount is running (certainly on Solaris). With
409 * automount, moving into a directory can cause a filesystem to be
410 * mounted there.
411 *
412 * To cope sensibly with this, we will raise an error if we see the
413 * device number change unless we are chdir()ing into a subdirectory,
414 * and the directory we moved into has been mounted or unmounted "recently".
415 * Here "recently" means since we started "find" or we last re-read
416 * the /etc/mnttab file.
417 *
418 * If the device number does not change but the inode does, that is a
419 * problem.
420 *
421 * If the device number and inode are both the same, we are happy.
422 *
423 * If a filesystem is (un)mounted as we chdir() into the directory, that
424 * may mean that we're now examining a section of the filesystem that might
425 * have been excluded from consideration (via -prune or -quit for example).
426 * Hence we print a warning message to indicate that the output of find
427 * might be inconsistent due to the change in the filesystem.
428 */
429static boolean
430wd_sanity_check(const char *thing_to_stat,
431 const char *progname,
432 const char *what,
433 dev_t old_dev,
434 ino_t old_ino,
435 struct stat *newinfo,
436 int parent,
437 int line_no,
438 enum TraversalDirection direction,
439 enum WdSanityCheckFatality isfatal,
440 boolean *changed) /* output parameter */
441{
442 const char *fstype;
443 char *specific_what = NULL;
444 int silent = 0;
445 const char *current_dir = ".";
446
447 *changed = false;
448
449 if ((*options.xstat) (current_dir, newinfo) != 0)
450 error (1, errno, "%s", thing_to_stat);
451
452 if (old_dev != newinfo->st_dev)
453 {
454 *changed = true;
455 specific_what = specific_dirname(what);
456 fstype = filesystem_type(newinfo, current_dir);
457 silent = fs_likely_to_be_automounted(fstype);
458
459 /* This condition is rare, so once we are here it is
460 * reasonable to perform an expensive computation to
461 * determine if we should continue or fail.
462 */
463 if (TraversingDown == direction)
464 {
465#ifdef STAT_MOUNTPOINTS
466 isfatal = dirchange_is_fatal(specific_what,isfatal,silent,newinfo);
467#else
468 isfatal = RETRY_IF_SANITY_CHECK_FAILS;
469#endif
470 }
471
472 switch (isfatal)
473 {
474 case FATAL_IF_SANITY_CHECK_FAILS:
475 {
476 fstype = filesystem_type(newinfo, current_dir);
477 error (1, 0,
478 _("%s%s changed during execution of %s (old device number %ld, new device number %ld, filesystem type is %s) [ref %ld]"),
479 specific_what,
480 parent ? "/.." : "",
481 progname,
482 (long) old_dev,
483 (long) newinfo->st_dev,
484 fstype,
485 line_no);
486 /*NOTREACHED*/
487 return false;
488 }
489
490 case NON_FATAL_IF_SANITY_CHECK_FAILS:
491 {
492 /* Since the device has changed under us, the inode number
493 * will almost certainly also be different. However, we have
494 * already decided that this is not a problem. Hence we return
495 * without checking the inode number.
496 */
497 free(specific_what);
498 return true;
499 }
500
501 case RETRY_IF_SANITY_CHECK_FAILS:
502 return false;
503 }
504 }
505
506 /* Device number was the same, check if the inode has changed. */
507 if (old_ino != newinfo->st_ino)
508 {
509 *changed = true;
510 specific_what = specific_dirname(what);
511 fstype = filesystem_type(newinfo, current_dir);
512
513 error ((isfatal == FATAL_IF_SANITY_CHECK_FAILS) ? 1 : 0,
514 0, /* no relevant errno value */
515 _("%s%s changed during execution of %s (old inode number %ld, new inode number %ld, filesystem type is %s) [ref %ld]"),
516 specific_what,
517 parent ? "/.." : "",
518 progname,
519 (long) old_ino,
520 (long) newinfo->st_ino,
521 fstype,
522 line_no);
523 free(specific_what);
524 return false;
525 }
526
527 return true;
528}
529
530
531enum SafeChdirStatus
532 {
533 SafeChdirOK,
534 SafeChdirFailSymlink,
535 SafeChdirFailNotDir,
536 SafeChdirFailStat,
537 SafeChdirFailWouldBeUnableToReturn,
538 SafeChdirFailChdirFailed,
539 SafeChdirFailNonexistent
540 };
541
542/* Safely perform a change in directory. We do this by calling
543 * lstat() on the subdirectory, using chdir() to move into it, and
544 * then lstat()ing ".". We compare the results of the two stat calls
545 * to see if they are consistent. If not, we sound the alarm.
546 *
547 * If following_links() is true, we do follow symbolic links.
548 */
549static enum SafeChdirStatus
550safely_chdir_lstat(const char *dest,
551 enum TraversalDirection direction,
552 struct stat *statbuf_dest,
553 enum ChdirSymlinkHandling symlink_follow_option,
554 boolean *did_stat)
555{
556 struct stat statbuf_arrived;
557 int rv, dotfd=-1;
558 int saved_errno; /* specific_dirname() changes errno. */
559 boolean rv_set = false;
560 boolean statflag = false;
561 int tries = 0;
562 enum WdSanityCheckFatality isfatal = RETRY_IF_SANITY_CHECK_FAILS;
563
564 saved_errno = errno = 0;
565
566 dotfd = open(".", O_RDONLY);
567
568 /* We jump back to here if wd_sanity_check()
569 * recoverably triggers an alert.
570 */
571 retry:
572 ++tries;
573
574 if (dotfd >= 0)
575 {
576 /* Stat the directory we're going to. */
577 if (0 == options.xstat(dest, statbuf_dest))
578 {
579 statflag = true;
580
581#ifdef S_ISLNK
582 /* symlink_follow_option might be set to SymlinkFollowOk, which
583 * would allow us to chdir() into a symbolic link. This is
584 * only useful for the case where the directory we're
585 * chdir()ing into is the basename of a command line
586 * argument, for example where "foo/bar/baz" is specified on
587 * the command line. When -P is in effect (the default),
588 * baz will not be followed if it is a symlink, but if bar
589 * is a symlink, it _should_ be followed. Hence we need the
590 * ability to override the policy set by following_links().
591 */
592 if (!following_links() && S_ISLNK(statbuf_dest->st_mode))
593 {
594 /* We're not supposed to be following links, but this is
595 * a link. Check symlink_follow_option to see if we should
596 * make a special exception.
597 */
598 if (symlink_follow_option == SymlinkFollowOk)
599 {
600 /* We need to re-stat() the file so that the
601 * sanity check can pass.
602 */
603 if (0 != stat(dest, statbuf_dest))
604 {
605 rv = SafeChdirFailNonexistent;
606 rv_set = true;
607 saved_errno = errno;
608 goto fail;
609 }
610 statflag = true;
611 }
612 else
613 {
614 /* Not following symlinks, so the attempt to
615 * chdir() into a symlink should be prevented.
616 */
617 rv = SafeChdirFailSymlink;
618 rv_set = true;
619 saved_errno = 0; /* silence the error message */
620 goto fail;
621 }
622 }
623#endif
624#ifdef S_ISDIR
625 /* Although the immediately following chdir() would detect
626 * the fact that this is not a directory for us, this would
627 * result in an extra system call that fails. Anybody
628 * examining the system-call trace should ideally not be
629 * concerned that something is actually failing.
630 */
631 if (!S_ISDIR(statbuf_dest->st_mode))
632 {
633 rv = SafeChdirFailNotDir;
634 rv_set = true;
635 saved_errno = 0; /* silence the error message */
636 goto fail;
637 }
638#endif
639
640 if (options.debug_options & DebugSearch)
641 fprintf(stderr, "safely_chdir(): chdir(\"%s\")\n", dest);
642
643 if (0 == chdir(dest))
644 {
645 /* check we ended up where we wanted to go */
646 boolean changed = false;
647 if (!wd_sanity_check(".", program_name, ".",
648 statbuf_dest->st_dev,
649 statbuf_dest->st_ino,
650 &statbuf_arrived,
651 0, __LINE__, direction,
652 isfatal,
653 &changed))
654 {
655 /* Only allow one failure. */
656 if (RETRY_IF_SANITY_CHECK_FAILS == isfatal)
657 {
658 if (0 == fchdir(dotfd))
659 {
660 isfatal = FATAL_IF_SANITY_CHECK_FAILS;
661 goto retry;
662 }
663 else
664 {
665 /* Failed to return to original directory,
666 * but we know that the current working
667 * directory is not the one that we intend
668 * to be in. Since fchdir() failed, we
669 * can't recover from this and so this error
670 * is fatal.
671 */
672 error(1, errno,
673 "failed to return to parent directory");
674 }
675 }
676 else
677 {
678 /* XXX: not sure what to use as an excuse here. */
679 rv = SafeChdirFailNonexistent;
680 rv_set = true;
681 saved_errno = 0;
682 goto fail;
683 }
684 }
685
686 close(dotfd);
687 return SafeChdirOK;
688 }
689 else
690 {
691 saved_errno = errno;
692 if (ENOENT == saved_errno)
693 {
694 rv = SafeChdirFailNonexistent;
695 rv_set = true;
696 if (options.ignore_readdir_race)
697 errno = 0; /* don't issue err msg */
698 }
699 else if (ENOTDIR == saved_errno)
700 {
701 /* This can happen if the we stat a directory,
702 * and then filesystem activity changes it into
703 * a non-directory.
704 */
705 saved_errno = 0; /* don't issue err msg */
706 rv = SafeChdirFailNotDir;
707 rv_set = true;
708 }
709 else
710 {
711 rv = SafeChdirFailChdirFailed;
712 rv_set = true;
713 }
714 goto fail;
715 }
716 }
717 else
718 {
719 saved_errno = errno;
720 rv = SafeChdirFailStat;
721 rv_set = true;
722
723 if ( (ENOENT == saved_errno) || (0 == state.curdepth))
724 saved_errno = 0; /* don't issue err msg */
725 goto fail;
726 }
727 }
728 else
729 {
730 /* We do not have read permissions on "." */
731 rv = SafeChdirFailWouldBeUnableToReturn;
732 rv_set = true;
733 goto fail;
734 }
735
736 /* This is the success path, so we clear errno. The caller probably
737 * won't be calling error() anyway.
738 */
739 saved_errno = 0;
740
741 /* We use the same exit path for success or failure.
742 * which has occurred is recorded in RV.
743 */
744 fail:
745 /* We do not call error() as this would result in a duplicate error
746 * message when the caller does the same thing.
747 */
748 if (saved_errno)
749 errno = saved_errno;
750
751 if (dotfd >= 0)
752 {
753 close(dotfd);
754 dotfd = -1;
755 }
756
757 *did_stat = statflag;
758 assert(rv_set);
759 return rv;
760}
761
762#if defined(O_NOFOLLOW)
763/* Safely change working directory to the specified subdirectory. If
764 * we are not allowed to follow symbolic links, we use open() with
765 * O_NOFOLLOW, followed by fchdir(). This ensures that we don't
766 * follow symbolic links (of course, we do follow them if the -L
767 * option is in effect).
768 */
769static enum SafeChdirStatus
770safely_chdir_nofollow(const char *dest,
771 enum TraversalDirection direction,
772 struct stat *statbuf_dest,
773 enum ChdirSymlinkHandling symlink_follow_option,
774 boolean *did_stat)
775{
776 int extraflags, fd;
777
778 (void) direction;
779 (void) statbuf_dest;
780
781 extraflags = 0;
782 *did_stat = false;
783
784 switch (symlink_follow_option)
785 {
786 case SymlinkFollowOk:
787 extraflags = 0;
788 break;
789
790 case SymlinkHandleDefault:
791 if (following_links())
792 extraflags = 0;
793 else
794 extraflags = O_NOFOLLOW;
795 break;
796 }
797
798 errno = 0;
799 fd = open(dest, O_RDONLY|extraflags);
800 if (fd < 0)
801 {
802 switch (errno)
803 {
804 case ELOOP:
805 return SafeChdirFailSymlink; /* This is why we use O_NOFOLLOW */
806 case ENOENT:
807 return SafeChdirFailNonexistent;
808 default:
809 return SafeChdirFailChdirFailed;
810 }
811 }
812
813 errno = 0;
814 if (0 == fchdir(fd))
815 {
816 close(fd);
817 return SafeChdirOK;
818 }
819 else
820 {
821 int saved_errno = errno;
822 close(fd);
823 errno = saved_errno;
824
825 switch (errno)
826 {
827 case ENOTDIR:
828 return SafeChdirFailNotDir;
829
830 case EACCES:
831 case EBADF: /* Shouldn't happen */
832 case EINTR:
833 case EIO:
834 default:
835 return SafeChdirFailChdirFailed;
836 }
837 }
838}
839#endif
840
841static enum SafeChdirStatus
842safely_chdir(const char *dest,
843 enum TraversalDirection direction,
844 struct stat *statbuf_dest,
845 enum ChdirSymlinkHandling symlink_follow_option,
846 boolean *did_stat)
847{
848 /* We're about to leave a directory. If there are any -execdir
849 * argument lists which have been built but have not yet been
850 * processed, do them now because they must be done in the same
851 * directory.
852 */
853 complete_pending_execdirs(get_eval_tree());
854
855#if defined(O_NOFOLLOW)
856 if (options.open_nofollow_available)
857 return safely_chdir_nofollow(dest, direction, statbuf_dest, symlink_follow_option, did_stat);
858#endif
859 return safely_chdir_lstat(dest, direction, statbuf_dest, symlink_follow_option, did_stat);
860}
861
862
863
864
865/* Safely go back to the starting directory. */
866static void
867chdir_back (void)
868{
869 struct stat stat_buf;
870 boolean dummy;
871
872 if (starting_desc < 0)
873 {
874 if (options.debug_options & DebugSearch)
875 fprintf(stderr, "chdir_back(): chdir(\"%s\")\n", starting_dir);
876
877#ifdef STAT_MOUNTPOINTS
878 /* We will need the mounted device list. Get it now if we don't
879 * already have it.
880 */
881 if (NULL == mounted_devices)
882 init_mounted_dev_list(1);
883#endif
884
885 if (chdir (starting_dir) != 0)
886 error (1, errno, "%s", starting_dir);
887
888 wd_sanity_check(starting_dir,
889 program_name,
890 starting_dir,
891 starting_stat_buf.st_dev,
892 starting_stat_buf.st_ino,
893 &stat_buf, 0, __LINE__,
894 TraversingUp,
895 FATAL_IF_SANITY_CHECK_FAILS,
896 &dummy);
897 }
898 else
899 {
900 if (options.debug_options & DebugSearch)
901 fprintf(stderr, "chdir_back(): chdir(<starting-point>)\n");
902
903 if (fchdir (starting_desc) != 0)
904 error (1, errno, "%s", starting_dir);
905 }
906}
907
908
909/* Move to the parent of a given directory and then call a function,
910 * restoring the cwd. Don't bother changing directory if the
911 * specified directory is a child of "." or is the root directory.
912 */
913static void
914at_top (char *pathname,
915 mode_t mode,
916 struct stat *pstat,
917 void (*action)(char *pathname,
918 char *basename,
919 int mode,
920 struct stat *pstat))
921{
922 int dirchange;
923 char *parent_dir = dir_name(pathname);
924 char *base = base_name(pathname);
925
926 state.curdepth = 0;
927 state.starting_path_length = strlen (pathname);
928
929 if (0 == strcmp(pathname, parent_dir)
930 || 0 == strcmp(parent_dir, "."))
931 {
932 dirchange = 0;
933 base = pathname;
934 }
935 else
936 {
937 enum TraversalDirection direction;
938 enum SafeChdirStatus chdir_status;
939 struct stat st;
940 boolean did_stat = false;
941
942 dirchange = 1;
943 if (0 == strcmp(base, ".."))
944 direction = TraversingUp;
945 else
946 direction = TraversingDown;
947
948 /* We pass SymlinkFollowOk to safely_chdir(), which allows it to
949 * chdir() into a symbolic link. This is only useful for the
950 * case where the directory we're chdir()ing into is the
951 * basename of a command line argument, for example where
952 * "foo/bar/baz" is specified on the command line. When -P is
953 * in effect (the default), baz will not be followed if it is a
954 * symlink, but if bar is a symlink, it _should_ be followed.
955 * Hence we need the ability to override the policy set by
956 * following_links().
957 */
958 chdir_status = safely_chdir(parent_dir, direction, &st, SymlinkFollowOk, &did_stat);
959 if (SafeChdirOK != chdir_status)
960 {
961 const char *what = (SafeChdirFailWouldBeUnableToReturn == chdir_status) ? "." : parent_dir;
962 if (errno)
963 error (0, errno, "%s", what);
964 else
965 error (0, 0, "Failed to safely change directory into `%s'",
966 parent_dir);
967
968 /* We can't process this command-line argument. */
969 state.exit_status = 1;
970 return;
971 }
972 }
973
974 free (parent_dir);
975 parent_dir = NULL;
976
977 action(pathname, base, mode, pstat);
978
979 if (dirchange)
980 {
981 chdir_back();
982 }
983}
984
985
986static void do_process_top_dir(char *pathname,
987 char *base,
988 int mode,
989 struct stat *pstat)
990{
991 (void) pstat;
992
993 process_path (pathname, base, false, ".", mode);
994 complete_pending_execdirs(get_eval_tree());
995}
996
997static void do_process_predicate(char *pathname,
998 char *base,
999 int mode,
1000 struct stat *pstat)
1001{
1002 (void) mode;
1003
1004 state.rel_pathname = base;
1005 apply_predicate (pathname, pstat, get_eval_tree());
1006}
1007
1008
1009
1010
1011
1012/* Descend PATHNAME, which is a command-line argument.
1013
1014 Actions like -execdir assume that we are in the
1015 parent directory of the file we're examining,
1016 and on entry to this function our working directory
1017 is whatever it was when find was invoked. Therefore
1018 If PATHNAME is "." we just leave things as they are.
1019 Otherwise, we figure out what the parent directory is,
1020 and move to that.
1021*/
1022static void
1023process_top_path (char *pathname, mode_t mode)
1024{
1025 at_top(pathname, mode, NULL, do_process_top_dir);
1026}
1027
1028
1029/* Info on each directory in the current tree branch, to avoid
1030 getting stuck in symbolic link loops. */
1031static struct dir_id *dir_ids = NULL;
1032/* Entries allocated in `dir_ids'. */
1033static int dir_alloc = 0;
1034/* Index in `dir_ids' of directory currently being searched.
1035 This is always the last valid entry. */
1036static int dir_curr = -1;
1037/* (Arbitrary) number of entries to grow `dir_ids' by. */
1038#define DIR_ALLOC_STEP 32
1039
1040
1041
1042
1043/* We've detected a filesystem loop. This is caused by one of
1044 * two things:
1045 *
1046 * 1. Option -L is in effect and we've hit a symbolic link that
1047 * points to an ancestor. This is harmless. We won't traverse the
1048 * symbolic link.
1049 *
1050 * 2. We have hit a real cycle in the directory hierarchy. In this
1051 * case, we issue a diagnostic message (POSIX requires this) and we
1052 * skip that directory entry.
1053 */
1054static void
1055issue_loop_warning(const char *name, const char *pathname, int level)
1056{
1057 struct stat stbuf_link;
1058 if (lstat(name, &stbuf_link) != 0)
1059 stbuf_link.st_mode = S_IFREG;
1060
1061 if (S_ISLNK(stbuf_link.st_mode))
1062 {
1063 error(0, 0,
1064 _("Symbolic link `%s' is part of a loop in the directory hierarchy; we have already visited the directory to which it points."),
1065 pathname);
1066 }
1067 else
1068 {
1069 int distance = 1 + (dir_curr-level);
1070 /* We have found an infinite loop. POSIX requires us to
1071 * issue a diagnostic. Usually we won't get to here
1072 * because when the leaf optimisation is on, it will cause
1073 * the subdirectory to be skipped. If /a/b/c/d is a hard
1074 * link to /a/b, then the link count of /a/b/c is 2,
1075 * because the ".." entry of /b/b/c/d points to /a, not
1076 * to /a/b/c.
1077 */
1078 error(0, 0,
1079 _("Filesystem loop detected; `%s' has the same device number and inode as a directory which is %d %s."),
1080 pathname,
1081 distance,
1082 (distance == 1 ?
1083 _("level higher in the filesystem hierarchy") :
1084 _("levels higher in the filesystem hierarchy")));
1085 }
1086}
1087
1088
1089
1090/* Recursively descend path PATHNAME, applying the predicates.
1091 LEAF is true if PATHNAME is known to be in a directory that has no
1092 more unexamined subdirectories, and therefore it is not a directory.
1093 Knowing this allows us to avoid calling stat as long as possible for
1094 leaf files.
1095
1096 NAME is PATHNAME relative to the current directory. We access NAME
1097 but print PATHNAME.
1098
1099 PARENT is the path of the parent of NAME, relative to find's
1100 starting directory.
1101
1102 Return nonzero iff PATHNAME is a directory. */
1103
1104static int
1105process_path (char *pathname, char *name, boolean leaf, char *parent,
1106 mode_t mode)
1107{
1108 struct stat stat_buf;
1109 static dev_t root_dev; /* Device ID of current argument pathname. */
1110 int i;
1111 struct predicate *eval_tree;
1112
1113 eval_tree = get_eval_tree();
1114 /* Assume it is a non-directory initially. */
1115 stat_buf.st_mode = 0;
1116 state.rel_pathname = name;
1117 state.type = 0;
1118 state.have_stat = false;
1119 state.have_type = false;
1120
1121 if (!digest_mode(mode, pathname, name, &stat_buf, leaf))
1122 return 0;
1123
1124 if (!S_ISDIR (state.type))
1125 {
1126 if (state.curdepth >= options.mindepth)
1127 apply_predicate (pathname, &stat_buf, eval_tree);
1128 return 0;
1129 }
1130
1131 /* From here on, we're working on a directory. */
1132
1133
1134 /* Now we really need to stat the directory, even if we know the
1135 * type, because we need information like struct stat.st_rdev.
1136 */
1137 if (get_statinfo(pathname, name, &stat_buf) != 0)
1138 return 0;
1139
1140 state.have_stat = true;
1141 mode = state.type = stat_buf.st_mode; /* use full info now that we have it. */
1142 state.stop_at_current_level =
1143 options.maxdepth >= 0
1144 && state.curdepth >= options.maxdepth;
1145
1146 /* If we've already seen this directory on this branch,
1147 don't descend it again. */
1148 for (i = 0; i <= dir_curr; i++)
1149 if (stat_buf.st_ino == dir_ids[i].ino &&
1150 stat_buf.st_dev == dir_ids[i].dev)
1151 {
1152 state.stop_at_current_level = true;
1153 issue_loop_warning(name, pathname, i);
1154 }
1155
1156 if (dir_alloc <= ++dir_curr)
1157 {
1158 dir_alloc += DIR_ALLOC_STEP;
1159 dir_ids = (struct dir_id *)
1160 xrealloc ((char *) dir_ids, dir_alloc * sizeof (struct dir_id));
1161 }
1162 dir_ids[dir_curr].ino = stat_buf.st_ino;
1163 dir_ids[dir_curr].dev = stat_buf.st_dev;
1164
1165 if (options.stay_on_filesystem)
1166 {
1167 if (state.curdepth == 0)
1168 root_dev = stat_buf.st_dev;
1169 else if (stat_buf.st_dev != root_dev)
1170 state.stop_at_current_level = true;
1171 }
1172
1173 if (options.do_dir_first && state.curdepth >= options.mindepth)
1174 apply_predicate (pathname, &stat_buf, eval_tree);
1175
1176 if (options.debug_options & DebugSearch)
1177 fprintf(stderr, "pathname = %s, stop_at_current_level = %d\n",
1178 pathname, state.stop_at_current_level);
1179
1180 if (state.stop_at_current_level == false)
1181 /* Scan directory on disk. */
1182 process_dir (pathname, name, strlen (pathname), &stat_buf, parent);
1183
1184 if (options.do_dir_first == false && state.curdepth >= options.mindepth)
1185 {
1186 /* The fields in 'state' are now out of date. Correct them.
1187 */
1188 if (!digest_mode(mode, pathname, name, &stat_buf, leaf))
1189 return 0;
1190
1191 if (0 == dir_curr)
1192 {
1193 at_top(pathname, mode, &stat_buf, do_process_predicate);
1194 }
1195 else
1196 {
1197 do_process_predicate(pathname, name, mode, &stat_buf);
1198 }
1199 }
1200
1201 dir_curr--;
1202
1203 return 1;
1204}
1205
1206
1207
1208/* Scan directory PATHNAME and recurse through process_path for each entry.
1209
1210 PATHLEN is the length of PATHNAME.
1211
1212 NAME is PATHNAME relative to the current directory.
1213
1214 STATP is the results of *options.xstat on it.
1215
1216 PARENT is the path of the parent of NAME, relative to find's
1217 starting directory. */
1218
1219static void
1220process_dir (char *pathname, char *name, int pathlen, struct stat *statp, char *parent)
1221{
1222 int subdirs_left; /* Number of unexamined subdirs in PATHNAME. */
1223 boolean subdirs_unreliable; /* if true, cannot use dir link count as subdir limif (if false, it may STILL be unreliable) */
1224 unsigned int idx; /* Which entry are we on? */
1225 struct stat stat_buf;
1226
1227 struct savedir_dirinfo *dirinfo;
1228
1229 if (statp->st_nlink < 2)
1230 {
1231 subdirs_unreliable = true;
1232 }
1233 else
1234 {
1235 subdirs_unreliable = false; /* not necessarily right */
1236 subdirs_left = statp->st_nlink - 2; /* Account for name and ".". */
1237 }
1238
1239 errno = 0;
1240 dirinfo = xsavedir(name, 0);
1241
1242
1243 if (dirinfo == NULL)
1244 {
1245 assert(errno != 0);
1246 error (0, errno, "%s", pathname);
1247 state.exit_status = 1;
1248 }
1249 else
1250 {
1251 register char *namep; /* Current point in `name_space'. */
1252 char *cur_path; /* Full path of each file to process. */
1253 char *cur_name; /* Base name of each file to process. */
1254 unsigned cur_path_size; /* Bytes allocated for `cur_path'. */
1255 register unsigned file_len; /* Length of each path to process. */
1256 register unsigned pathname_len; /* PATHLEN plus trailing '/'. */
1257 boolean did_stat = false;
1258
1259 if (pathname[pathlen - 1] == '/')
1260 pathname_len = pathlen + 1; /* For '\0'; already have '/'. */
1261 else
1262 pathname_len = pathlen + 2; /* For '/' and '\0'. */
1263 cur_path_size = 0;
1264 cur_path = NULL;
1265
1266 /* We're about to leave the directory. If there are any
1267 * -execdir argument lists which have been built but have not
1268 * yet been processed, do them now because they must be done in
1269 * the same directory.
1270 */
1271 complete_pending_execdirs(get_eval_tree());
1272
1273 if (strcmp (name, "."))
1274 {
1275 enum SafeChdirStatus status = safely_chdir (name, TraversingDown, &stat_buf, SymlinkHandleDefault, &did_stat);
1276 switch (status)
1277 {
1278 case SafeChdirOK:
1279 /* If there had been a change but wd_sanity_check()
1280 * accepted it, we need to accept that on the
1281 * way back up as well, so modify our record
1282 * of what we think we should see later.
1283 * If there was no change, the assignments are a no-op.
1284 *
1285 * However, before performing the assignment, we need to
1286 * check that we have the stat information. If O_NOFOLLOW
1287 * is available, safely_chdir() will not have needed to use
1288 * stat(), and so stat_buf will just contain random data.
1289 */
1290 if (!did_stat)
1291 {
1292 /* If there is a link we need to follow it. Hence
1293 * the direct call to stat() not through (options.xstat)
1294 */
1295 if (0 != stat(".", &stat_buf))
1296 break; /* skip the assignment. */
1297 }
1298 dir_ids[dir_curr].dev = stat_buf.st_dev;
1299 dir_ids[dir_curr].ino = stat_buf.st_ino;
1300
1301 break;
1302
1303 case SafeChdirFailWouldBeUnableToReturn:
1304 error (0, errno, ".");
1305 state.exit_status = 1;
1306 break;
1307
1308 case SafeChdirFailNonexistent:
1309 case SafeChdirFailStat:
1310 case SafeChdirFailNotDir:
1311 case SafeChdirFailChdirFailed:
1312 error (0, errno, "%s", pathname);
1313 state.exit_status = 1;
1314 return;
1315
1316 case SafeChdirFailSymlink:
1317 error (0, 0,
1318 _("warning: not following the symbolic link %s"),
1319 pathname);
1320 state.exit_status = 1;
1321 return;
1322 }
1323 }
1324
1325 for (idx=0; idx < dirinfo->size; ++idx)
1326 {
1327 /* savedirinfo() may return dirinfo=NULL if extended information
1328 * is not available.
1329 */
1330 mode_t mode = (dirinfo->entries[idx].flags & SavedirHaveFileType) ?
1331 dirinfo->entries[idx].type_info : 0;
1332 namep = dirinfo->entries[idx].name;
1333
1334 /* Append this directory entry's name to the path being searched. */
1335 file_len = pathname_len + strlen (namep);
1336 if (file_len > cur_path_size)
1337 {
1338 while (file_len > cur_path_size)
1339 cur_path_size += 1024;
1340 if (cur_path)
1341 free (cur_path);
1342 cur_path = xmalloc (cur_path_size);
1343 strcpy (cur_path, pathname);
1344 cur_path[pathname_len - 2] = '/';
1345 }
1346 cur_name = cur_path + pathname_len - 1;
1347 strcpy (cur_name, namep);
1348
1349 state.curdepth++;
1350 if (!options.no_leaf_check && !subdirs_unreliable)
1351 {
1352 if (mode && S_ISDIR(mode) && (subdirs_left == 0))
1353 {
1354 /* This is a subdirectory, but the number of directories we
1355 * have found now exceeds the number we would expect given
1356 * the hard link count on the parent. This is likely to be
1357 * a bug in the filesystem driver (e.g. Linux's
1358 * /proc filesystem) or may just be a fact that the OS
1359 * doesn't really handle hard links with Unix semantics.
1360 * In the latter case, -noleaf should be used routinely.
1361 */
1362 error(0, 0, _("WARNING: Hard link count is wrong for %s: this may be a bug in your filesystem driver. Automatically turning on find's -noleaf option. Earlier results may have failed to include directories that should have been searched."),
1363 pathname);
1364 state.exit_status = 1; /* We know the result is wrong, now */
1365 options.no_leaf_check = true; /* Don't make same
1366 mistake again */
1367 subdirs_left = 1; /* band-aid for this iteration. */
1368 }
1369
1370 /* Normal case optimization. On normal Unix
1371 filesystems, a directory that has no subdirectories
1372 has two links: its name, and ".". Any additional
1373 links are to the ".." entries of its subdirectories.
1374 Once we have processed as many subdirectories as
1375 there are additional links, we know that the rest of
1376 the entries are non-directories -- in other words,
1377 leaf files. */
1378 subdirs_left -= process_path (cur_path, cur_name,
1379 subdirs_left == 0, pathname,
1380 mode);
1381 }
1382 else
1383 {
1384 /* There might be weird (e.g., CD-ROM or MS-DOS) filesystems
1385 mounted, which don't have Unix-like directory link counts. */
1386 process_path (cur_path, cur_name, false, pathname, mode);
1387 }
1388
1389 state.curdepth--;
1390 }
1391
1392
1393 /* We're about to leave the directory. If there are any
1394 * -execdir argument lists which have been built but have not
1395 * yet been processed, do them now because they must be done in
1396 * the same directory.
1397 */
1398 complete_pending_execdirs(get_eval_tree());
1399
1400 if (strcmp (name, "."))
1401 {
1402 enum SafeChdirStatus status;
1403 struct dir_id did;
1404 boolean did_stat = false;
1405
1406 /* We could go back and do the next command-line arg
1407 instead, maybe using longjmp. */
1408 char const *dir;
1409 boolean deref = following_links() ? true : false;
1410
1411 if ( (state.curdepth>0) && !deref)
1412 dir = "..";
1413 else
1414 {
1415 chdir_back ();
1416 dir = parent;
1417 }
1418
1419 status = safely_chdir (dir, TraversingUp, &stat_buf, SymlinkHandleDefault, &did_stat);
1420 switch (status)
1421 {
1422 case SafeChdirOK:
1423 break;
1424
1425 case SafeChdirFailWouldBeUnableToReturn:
1426 error (1, errno, ".");
1427 return;
1428
1429 case SafeChdirFailNonexistent:
1430 case SafeChdirFailStat:
1431 case SafeChdirFailSymlink:
1432 case SafeChdirFailNotDir:
1433 case SafeChdirFailChdirFailed:
1434 error (1, errno, "%s", pathname);
1435 return;
1436 }
1437
1438 if (dir_curr > 0)
1439 {
1440 did.dev = dir_ids[dir_curr-1].dev;
1441 did.ino = dir_ids[dir_curr-1].ino;
1442 }
1443 else
1444 {
1445 did.dev = starting_stat_buf.st_dev;
1446 did.ino = starting_stat_buf.st_ino;
1447 }
1448 }
1449
1450 if (cur_path)
1451 free (cur_path);
1452 free_dirinfo(dirinfo);
1453 }
1454}
Note: See TracBrowser for help on using the repository browser.