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., 9 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>. */
43 # define _(Text) gettext (Text)
46 #define textdomain(Domain)
47 #define bindtextdomain(Package, Directory)
50 # define N_(String) gettext_noop (String)
52 # define N_(String) (String)
55 #define apply_predicate(pathname, stat_buf_ptr, node) \
56 (*(node)->pred_func)((pathname), (stat_buf_ptr), (node))
58 static void process_top_path
PARAMS((char *pathname
));
59 static int process_path
PARAMS((char *pathname
, char *name
, boolean leaf
, char *parent
));
60 static void process_dir
PARAMS((char *pathname
, char *name
, int pathlen
, struct stat
*statp
, char *parent
));
61 static boolean no_side_effects
PARAMS((struct predicate
*pred
));
62 static boolean default_prints
PARAMS((struct predicate
*pred
));
64 /* Name this program was run with. */
67 /* All predicates for each path to process. */
68 struct predicate
*predicates
;
70 /* The last predicate allocated. */
71 struct predicate
*last_pred
;
73 /* The root of the evaluation tree. */
74 static struct predicate
*eval_tree
;
76 /* If true, process directory before contents. True unless -depth given. */
79 /* If >=0, don't descend more than this many levels of subdirectories. */
82 /* If >=0, don't process files above this level. */
85 /* Current depth; 0 means current path is a command line arg. */
88 /* Output block size. */
89 int output_block_size
;
91 /* Time at start of execution. */
94 /* Seconds between 00:00 1/1/70 and either one day before now
95 (the default), or the start of today (if -daystart is given). */
98 /* If true, cur_day_start has been adjusted to the start of the day. */
101 /* If true, do not assume that files in directories with nlink == 2
102 are non-directories. */
103 boolean no_leaf_check
;
105 /* If true, don't cross filesystem boundaries. */
106 boolean stay_on_filesystem
;
108 /* If true, don't descend past current directory.
109 Can be set by -prune, -maxdepth, and -xdev/-mount. */
110 boolean stop_at_current_level
;
112 /* The full path of the initial working directory, or "." if
113 STARTING_DESC is nonnegative. */
114 char const *starting_dir
= ".";
116 /* A file descriptor open to the initial working directory.
117 Doing it this way allows us to work when the i.w.d. has
118 unreadable parents. */
121 /* The stat buffer of the initial working directory. */
122 struct stat starting_stat_buf
;
124 /* If true, we have called stat on the current path. */
127 /* The file being operated on, relative to the current directory.
128 Used for stat, readlink, remove, and opendir. */
131 /* Length of current path. */
134 /* true if following symlinks. Should be consistent with xstat. */
137 /* Pointer to the function used to stat files. */
140 /* Status value to return to system. */
143 /* If true, we ignore the problem where we find that a directory entry
144 * no longer exists by the time we get around to processing it.
146 boolean ignore_readdir_race
;
151 debug_stat (file
, bufp
)
155 fprintf (stderr
, "debug_stat (%s)\n", file
);
156 return lstat (file
, bufp
);
158 #endif /* DEBUG_STAT */
161 main (int argc
, char **argv
)
164 PFB parse_function
; /* Pointer to the function which parses. */
165 struct predicate
*cur_pred
;
166 char *predicate_name
; /* Name of predicate being parsed. */
168 program_name
= argv
[0];
170 #ifdef HAVE_SETLOCALE
171 setlocale (LC_ALL
, "");
173 bindtextdomain (PACKAGE
, LOCALEDIR
);
174 textdomain (PACKAGE
);
179 maxdepth
= mindepth
= -1;
180 start_time
= time (NULL
);
181 cur_day_start
= start_time
- DAYSECS
;
183 no_leaf_check
= false;
184 stay_on_filesystem
= false;
185 ignore_readdir_race
= false;
190 #else /* !DEBUG_STAT */
192 #endif /* !DEBUG_STAT */
195 human_block_size (getenv ("FIND_BLOCK_SIZE"), 0, &output_block_size
);
197 if (getenv("POSIXLY_CORRECT"))
198 output_block_size
= 512;
200 output_block_size
= 1024;
202 if (getenv("FIND_BLOCK_SIZE"))
204 error (1, errno
, _("The environment variable FIND_BLOCK_SIZE is not supported, the only thing that affects the block size is the POSIXLY_CORRECT environment variable"));
210 printf ("cur_day_start = %s", ctime (&cur_day_start
));
213 /* Find where in ARGV the predicates begin. */
214 for (i
= 1; i
< argc
&& strchr ("-!(),", argv
[i
][0]) == NULL
; i
++)
217 /* Enclose the expression in `( ... )' so a default -print will
218 apply to the whole expression. */
219 parse_open (argv
, &argc
);
220 /* Build the input order list. */
223 if (strchr ("-!(),", argv
[i
][0]) == NULL
)
224 usage (_("paths must precede expression"));
225 predicate_name
= argv
[i
];
226 parse_function
= find_parser (predicate_name
);
227 if (parse_function
== NULL
)
228 /* Command line option not recognized */
229 error (1, 0, _("invalid predicate `%s'"), predicate_name
);
231 if (!(*parse_function
) (argv
, &i
))
234 /* Command line option requires an argument */
235 error (1, 0, _("missing argument to `%s'"), predicate_name
);
237 error (1, 0, _("invalid argument `%s' to `%s'"),
238 argv
[i
], predicate_name
);
241 if (predicates
->pred_next
== NULL
)
243 /* No predicates that do something other than set a global variable
244 were given; remove the unneeded initial `(' and add `-print'. */
245 cur_pred
= predicates
;
246 predicates
= last_pred
= predicates
->pred_next
;
247 free ((char *) cur_pred
);
248 parse_print (argv
, &argc
);
250 else if (!default_prints (predicates
->pred_next
))
252 /* One or more predicates that produce output were given;
253 remove the unneeded initial `('. */
254 cur_pred
= predicates
;
255 predicates
= predicates
->pred_next
;
256 free ((char *) cur_pred
);
260 /* `( user-supplied-expression ) -print'. */
261 parse_close (argv
, &argc
);
262 parse_print (argv
, &argc
);
266 printf (_("Predicate List:\n"));
267 print_list (predicates
);
270 /* Done parsing the predicates. Build the evaluation tree. */
271 cur_pred
= predicates
;
272 eval_tree
= get_expr (&cur_pred
, NO_PREC
);
274 /* Check if we have any left-over predicates (this fixes
275 * Debian bug #185202).
277 if (cur_pred
!= NULL
)
279 error (1, 0, _("unexpected extra predicate"));
283 printf (_("Eval Tree:\n"));
284 print_tree (eval_tree
, 0);
287 /* Rearrange the eval tree in optimal-predicate order. */
288 opt_expr (&eval_tree
);
290 /* Determine the point, if any, at which to stat the file. */
291 mark_stat (eval_tree
);
294 printf (_("Optimized Eval Tree:\n"));
295 print_tree (eval_tree
, 0);
298 starting_desc
= open (".", O_RDONLY
);
299 if (0 <= starting_desc
&& fchdir (starting_desc
) != 0)
301 close (starting_desc
);
304 if (starting_desc
< 0)
306 starting_dir
= xgetcwd ();
308 error (1, errno
, _("cannot get current directory"));
310 if ((*xstat
) (".", &starting_stat_buf
) != 0)
311 error (1, errno
, _("cannot get current directory"));
313 /* If no paths are given, default to ".". */
314 for (i
= 1; i
< argc
&& strchr ("-!(),", argv
[i
][0]) == NULL
; i
++)
315 process_top_path (argv
[i
]);
317 process_top_path (".");
322 /* Safely go back to the starting directory. */
326 struct stat stat_buf
;
328 if (starting_desc
< 0)
330 if (chdir (starting_dir
) != 0)
331 error (1, errno
, "%s", starting_dir
);
332 if ((*xstat
) (".", &stat_buf
) != 0)
333 error (1, errno
, "%s", starting_dir
);
334 if (stat_buf
.st_dev
!= starting_stat_buf
.st_dev
||
335 stat_buf
.st_ino
!= starting_stat_buf
.st_ino
)
336 error (1, 0, _("%s changed during execution of %s"), starting_dir
, program_name
);
340 if (fchdir (starting_desc
) != 0)
341 error (1, errno
, "%s", starting_dir
);
345 /* Descend PATHNAME, which is a command-line argument. */
348 process_top_path (char *pathname
)
350 struct stat stat_buf
, cur_stat_buf
;
353 path_length
= strlen (pathname
);
355 /* We stat each pathname given on the command-line twice --
356 once here and once in process_path. It's not too bad, though,
357 since the kernel can read the stat information out of its inode
358 cache the second time. */
359 if ((*xstat
) (pathname
, &stat_buf
) == 0 && S_ISDIR (stat_buf
.st_mode
))
361 if (chdir (pathname
) < 0)
363 if (!ignore_readdir_race
|| (errno
!= ENOENT
) )
365 error (0, errno
, "%s", pathname
);
371 /* Check that we are where we should be. */
372 if ((*xstat
) (".", &cur_stat_buf
) != 0)
373 error (1, errno
, "%s", pathname
);
374 if (cur_stat_buf
.st_dev
!= stat_buf
.st_dev
||
375 cur_stat_buf
.st_ino
!= stat_buf
.st_ino
)
376 error (1, 0, _("%s changed during execution of %s"), pathname
, program_name
);
378 process_path (pathname
, ".", false, ".");
382 process_path (pathname
, pathname
, false, ".");
385 /* Info on each directory in the current tree branch, to avoid
386 getting stuck in symbolic link loops. */
392 static struct dir_id
*dir_ids
= NULL
;
393 /* Entries allocated in `dir_ids'. */
394 static int dir_alloc
= 0;
395 /* Index in `dir_ids' of directory currently being searched.
396 This is always the last valid entry. */
397 static int dir_curr
= -1;
398 /* (Arbitrary) number of entries to grow `dir_ids' by. */
399 #define DIR_ALLOC_STEP 32
401 /* Recursively descend path PATHNAME, applying the predicates.
402 LEAF is true if PATHNAME is known to be in a directory that has no
403 more unexamined subdirectories, and therefore it is not a directory.
404 Knowing this allows us to avoid calling stat as long as possible for
407 NAME is PATHNAME relative to the current directory. We access NAME
410 PARENT is the path of the parent of NAME, relative to find's
413 Return nonzero iff PATHNAME is a directory. */
416 process_path (char *pathname
, char *name
, boolean leaf
, char *parent
)
418 struct stat stat_buf
;
419 static dev_t root_dev
; /* Device ID of current argument pathname. */
424 /* Assume it is a non-directory initially. */
425 stat_buf
.st_mode
= 0;
433 if ((*xstat
) (name
, &stat_buf
) != 0)
435 if (!ignore_readdir_race
|| (errno
!= ENOENT
) )
437 error (0, errno
, "%s", pathname
);
445 if (!S_ISDIR (stat_buf
.st_mode
))
447 if (curdepth
>= mindepth
)
448 apply_predicate (pathname
, &stat_buf
, eval_tree
);
452 /* From here on, we're working on a directory. */
454 stop_at_current_level
= maxdepth
>= 0 && curdepth
>= maxdepth
;
456 /* If we've already seen this directory on this branch,
457 don't descend it again. */
458 for (i
= 0; i
<= dir_curr
; i
++)
459 if (stat_buf
.st_ino
== dir_ids
[i
].ino
&&
460 stat_buf
.st_dev
== dir_ids
[i
].dev
)
461 stop_at_current_level
= true;
463 if (dir_alloc
<= ++dir_curr
)
465 dir_alloc
+= DIR_ALLOC_STEP
;
466 dir_ids
= (struct dir_id
*)
467 xrealloc ((char *) dir_ids
, dir_alloc
* sizeof (struct dir_id
));
469 dir_ids
[dir_curr
].ino
= stat_buf
.st_ino
;
470 dir_ids
[dir_curr
].dev
= stat_buf
.st_dev
;
472 if (stay_on_filesystem
)
475 root_dev
= stat_buf
.st_dev
;
476 else if (stat_buf
.st_dev
!= root_dev
)
477 stop_at_current_level
= true;
480 if (do_dir_first
&& curdepth
>= mindepth
)
481 apply_predicate (pathname
, &stat_buf
, eval_tree
);
484 fprintf(stderr
, "pathname = %s, stop_at_current_level = %d\n",
485 pathname
, stop_at_current_level
);
488 if (stop_at_current_level
== false)
489 /* Scan directory on disk. */
490 process_dir (pathname
, name
, strlen (pathname
), &stat_buf
, parent
);
492 if (do_dir_first
== false && curdepth
>= mindepth
)
495 apply_predicate (pathname
, &stat_buf
, eval_tree
);
503 /* Scan directory PATHNAME and recurse through process_path for each entry.
505 PATHLEN is the length of PATHNAME.
507 NAME is PATHNAME relative to the current directory.
509 STATP is the results of *xstat on it.
511 PARENT is the path of the parent of NAME, relative to find's
512 starting directory. */
515 process_dir (char *pathname
, char *name
, int pathlen
, struct stat
*statp
, char *parent
)
517 char *name_space
; /* Names of files in PATHNAME. */
518 int subdirs_left
; /* Number of unexamined subdirs in PATHNAME. */
519 struct stat stat_buf
;
521 subdirs_left
= statp
->st_nlink
- 2; /* Account for name and ".". */
524 name_space
= savedir (name
);
525 if (name_space
== NULL
)
529 error (0, errno
, "%s", pathname
);
533 error (1, 0, _("virtual memory exhausted"));
537 register char *namep
; /* Current point in `name_space'. */
538 char *cur_path
; /* Full path of each file to process. */
539 char *cur_name
; /* Base name of each file to process. */
540 unsigned cur_path_size
; /* Bytes allocated for `cur_path'. */
541 register unsigned file_len
; /* Length of each path to process. */
542 register unsigned pathname_len
; /* PATHLEN plus trailing '/'. */
544 if (pathname
[pathlen
- 1] == '/')
545 pathname_len
= pathlen
+ 1; /* For '\0'; already have '/'. */
547 pathname_len
= pathlen
+ 2; /* For '/' and '\0'. */
551 if (strcmp (name
, ".") && chdir (name
) < 0)
553 error (0, errno
, "%s", pathname
);
558 /* Check that we are where we should be. */
559 if ((*xstat
) (".", &stat_buf
) != 0)
560 error (1, errno
, "%s", pathname
);
561 if (stat_buf
.st_dev
!= dir_ids
[dir_curr
].dev
||
562 stat_buf
.st_ino
!= dir_ids
[dir_curr
].ino
)
563 error (1, 0, _("%s changed during execution of %s"), starting_dir
, program_name
);
565 for (namep
= name_space
; *namep
; namep
+= file_len
- pathname_len
+ 1)
567 /* Append this directory entry's name to the path being searched. */
568 file_len
= pathname_len
+ strlen (namep
);
569 if (file_len
> cur_path_size
)
571 while (file_len
> cur_path_size
)
572 cur_path_size
+= 1024;
575 cur_path
= xmalloc (cur_path_size
);
576 strcpy (cur_path
, pathname
);
577 cur_path
[pathname_len
- 2] = '/';
579 cur_name
= cur_path
+ pathname_len
- 1;
580 strcpy (cur_name
, namep
);
584 /* Normal case optimization.
585 On normal Unix filesystems, a directory that has no
586 subdirectories has two links: its name, and ".". Any
587 additional links are to the ".." entries of its
588 subdirectories. Once we have processed as many
589 subdirectories as there are additional links, we know
590 that the rest of the entries are non-directories --
591 in other words, leaf files. */
592 subdirs_left
-= process_path (cur_path
, cur_name
,
593 subdirs_left
== 0, pathname
);
595 /* There might be weird (e.g., CD-ROM or MS-DOS) filesystems
596 mounted, which don't have Unix-like directory link counts. */
597 process_path (cur_path
, cur_name
, false, pathname
);
601 if (strcmp (name
, "."))
603 /* We could go back and do the next command-line arg
604 instead, maybe using longjmp. */
615 if (chdir (dir
) != 0)
616 error (1, errno
, "%s", parent
);
618 /* Check that we are where we should be. */
619 if ((*xstat
) (".", &stat_buf
) != 0)
620 error (1, errno
, "%s", pathname
);
621 if (stat_buf
.st_dev
!=
622 (dir_curr
> 0 ? dir_ids
[dir_curr
-1].dev
: starting_stat_buf
.st_dev
) ||
624 (dir_curr
> 0 ? dir_ids
[dir_curr
-1].ino
: starting_stat_buf
.st_ino
))
627 error (1, 0, _("%s changed during execution of %s"), parent
, program_name
);
629 error (1, 0, _("%s/.. changed during execution of %s"), starting_dir
, program_name
);
639 /* Return true if there are no side effects in any of the predicates in
640 predicate list PRED, false if there are any. */
643 no_side_effects (struct predicate
*pred
)
647 if (pred
->side_effects
)
649 pred
= pred
->pred_next
;
654 /* Return true if there are no predicates with no_default_print in
655 predicate list PRED, false if there are any.
656 Returns true if default print should be performed */
659 default_prints (struct predicate
*pred
)
663 if (pred
->no_default_print
)
665 pred
= pred
->pred_next
;