blob: 43120250b3b7f9e9abf7ffdcdfd0edcef62d20a9 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Eric Andersen17d49ef1999-10-06 20:25:32 +00002/*
3 * Mini find implementation for busybox
4 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Eric Andersenc4996011999-10-20 22:08:37 +00006 *
Matt Kraai096370d2001-02-07 03:52:38 +00007 * Reworked by David Douthitt <n9ubh@callsign.net> and
8 * Matt Kraai <kraai@alumni.carnegiemellon.edu>.
Eric Andersen17d49ef1999-10-06 20:25:32 +00009 *
Rob Landleye9a7a622006-09-22 02:52:41 +000010 * Licensed under the GPL version 2, see the file LICENSE in this tarball.
Eric Andersen17d49ef1999-10-06 20:25:32 +000011 */
12
Denis Vlasenkodf0553b2006-10-29 00:21:47 +000013/* findutils-4.1.20:
14 *
15 * # find file.txt -exec 'echo {}' '{} {}' ';'
16 * find: echo file.txt: No such file or directory
17 * # find file.txt -exec 'echo' '{} {}' '; '
18 * find: missing argument to `-exec'
19 * # find file.txt -exec 'echo {}' '{} {}' ';' junk
20 * find: paths must precede expression
21 * # find file.txt -exec 'echo {}' '{} {}' ';' junk ';'
22 * find: paths must precede expression
23 * # find file.txt -exec 'echo' '{} {}' ';'
24 * file.txt file.txt
25 * (strace: execve("/bin/echo", ["echo", "file.txt file.txt"], [ 30 vars ]))
Denis Vlasenkodf0553b2006-10-29 00:21:47 +000026 * # find file.txt -exec 'echo' '{} {}' ';' -print -exec pwd ';'
27 * file.txt file.txt
28 * file.txt
29 * /tmp
Denis Vlasenkoe2fb7192006-10-29 19:03:56 +000030 * # find -name '*.c' -o -name '*.h'
31 * [shows files, *.c and *.h intermixed]
Denis Vlasenko5d499e12006-10-29 19:07:01 +000032 * # find file.txt -name '*f*' -o -name '*t*'
33 * file.txt
34 * # find file.txt -name '*z*' -o -name '*t*'
35 * file.txt
36 * # find file.txt -name '*f*' -o -name '*z*'
37 * file.txt
Denis Vlasenkoa3b4fed2006-10-31 03:20:13 +000038 *
39 * # find t z -name '*t*' -print -o -name '*z*'
40 * t
41 * # find t z t z -name '*t*' -o -name '*z*' -print
42 * z
43 * z
44 * # find t z t z '(' -name '*t*' -o -name '*z*' ')' -o -print
45 * (no output)
Denis Vlasenkodf0553b2006-10-29 00:21:47 +000046 */
47
Matt Kraai096370d2001-02-07 03:52:38 +000048#include <fnmatch.h>
Denis Vlasenkofc7f9222007-01-26 23:00:05 +000049#include "busybox.h"
Eric Andersen17d49ef1999-10-06 20:25:32 +000050
Denis Vlasenko5d499e12006-10-29 19:07:01 +000051USE_FEATURE_FIND_XDEV(static dev_t *xdev_dev;)
52USE_FEATURE_FIND_XDEV(static int xdev_count;)
Matt Kraai096370d2001-02-07 03:52:38 +000053
Denis Vlasenko5d499e12006-10-29 19:07:01 +000054typedef int (*action_fp)(const char *fileName, struct stat *statbuf, void *);
Matt Kraai096370d2001-02-07 03:52:38 +000055
Denis Vlasenko5d499e12006-10-29 19:07:01 +000056typedef struct {
57 action_fp f;
Denis Vlasenkocf787cf2007-02-04 17:11:25 +000058#if ENABLE_FEATURE_FIND_NOT
Bernhard Reutner-Fischer32773ac2007-03-29 13:54:17 +000059 bool invert;
Denis Vlasenkocf787cf2007-02-04 17:11:25 +000060#endif
Denis Vlasenko5d499e12006-10-29 19:07:01 +000061} action;
Denis Vlasenko92258542006-11-01 10:25:35 +000062#define ACTS(name, arg...) typedef struct { action a; arg; } action_##name;
63#define ACTF(name) static int func_##name(const char *fileName, struct stat *statbuf, action_##name* ap)
64 ACTS(print)
Denis Vlasenko434ad542007-01-27 13:45:17 +000065 ACTS(name, const char *pattern;)
Denis Vlasenko92258542006-11-01 10:25:35 +000066USE_FEATURE_FIND_PRINT0(ACTS(print0))
67USE_FEATURE_FIND_TYPE( ACTS(type, int type_mask;))
Denis Vlasenkofc7f9222007-01-26 23:00:05 +000068USE_FEATURE_FIND_PERM( ACTS(perm, char perm_char; mode_t perm_mask;))
69USE_FEATURE_FIND_MTIME( ACTS(mtime, char mtime_char; unsigned mtime_days;))
70USE_FEATURE_FIND_MMIN( ACTS(mmin, char mmin_char; unsigned mmin_mins;))
Denis Vlasenko92258542006-11-01 10:25:35 +000071USE_FEATURE_FIND_NEWER( ACTS(newer, time_t newer_mtime;))
72USE_FEATURE_FIND_INUM( ACTS(inum, ino_t inode_num;))
Bernhard Reutner-Fischer10b79962007-02-04 16:09:04 +000073USE_FEATURE_FIND_EXEC( ACTS(exec, char **exec_argv; unsigned int *subst_count; int exec_argc;))
Denis Vlasenko56fce002007-04-04 23:41:35 +000074USE_FEATURE_FIND_USER( ACTS(user, uid_t uid;))
75USE_FEATURE_FIND_GROUP( ACTS(group, gid_t gid;))
76USE_FEATURE_FIND_PAREN( ACTS(paren, action ***subexpr;))
77USE_FEATURE_FIND_SIZE( ACTS(size, off_t size;))
78USE_FEATURE_FIND_PRUNE( ACTS(prune))
Matt Kraai096370d2001-02-07 03:52:38 +000079
Denis Vlasenko5d499e12006-10-29 19:07:01 +000080static action ***actions;
Bernhard Reutner-Fischer32773ac2007-03-29 13:54:17 +000081static bool need_print = 1;
Denis Vlasenko56fce002007-04-04 23:41:35 +000082static int recurse_flags = action_recurse;
Rob Landley5d3a0e82005-10-04 03:34:39 +000083
Denis Vlasenko666da5e2006-12-26 18:17:42 +000084#if ENABLE_FEATURE_FIND_EXEC
Bernhard Reutner-Fischer10b79962007-02-04 16:09:04 +000085static unsigned int count_subst(const char *str)
Denis Vlasenkodf0553b2006-10-29 00:21:47 +000086{
Bernhard Reutner-Fischer10b79962007-02-04 16:09:04 +000087 unsigned int count = 0;
Denis Vlasenkodf0553b2006-10-29 00:21:47 +000088 while ((str = strstr(str, "{}"))) {
89 count++;
90 str++;
91 }
92 return count;
93}
94
95
Bernhard Reutner-Fischer10b79962007-02-04 16:09:04 +000096static char* subst(const char *src, unsigned int count, const char* filename)
Denis Vlasenkodf0553b2006-10-29 00:21:47 +000097{
98 char *buf, *dst, *end;
Bernhard Reutner-Fischer32773ac2007-03-29 13:54:17 +000099 size_t flen = strlen(filename);
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000100 /* we replace each '{}' with filename: growth by strlen-2 */
101 buf = dst = xmalloc(strlen(src) + count*(flen-2) + 1);
102 while ((end = strstr(src, "{}"))) {
103 memcpy(dst, src, end - src);
104 dst += end - src;
105 src = end + 2;
106 memcpy(dst, filename, flen);
107 dst += flen;
108 }
109 strcpy(dst, src);
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000110 return buf;
111}
Denis Vlasenko666da5e2006-12-26 18:17:42 +0000112#endif
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000113
114
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000115static int exec_actions(action ***appp, const char *fileName, struct stat *statbuf)
116{
117 int cur_group;
118 int cur_action;
119 int rc = TRUE;
120 action **app, *ap;
121
122 cur_group = -1;
123 while ((app = appp[++cur_group])) {
124 cur_action = -1;
Denis Vlasenkocf787cf2007-02-04 17:11:25 +0000125 while (1) {
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000126 ap = app[++cur_action];
Denis Vlasenkocf787cf2007-02-04 17:11:25 +0000127 if (!ap) {
128 /* all actions in group were successful */
129 return rc;
130 }
131 rc = ap->f(fileName, statbuf, ap);
132#if ENABLE_FEATURE_FIND_NOT
133 if (ap->invert) rc = !rc;
134#endif
135 if (!rc) {
136 /* current group failed, try next */
137 break;
138 }
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000139 }
140 }
141 return rc;
142}
143
144
Denis Vlasenko92258542006-11-01 10:25:35 +0000145ACTF(name)
Eric Andersen17d49ef1999-10-06 20:25:32 +0000146{
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000147 const char *tmp = strrchr(fileName, '/');
148 if (tmp == NULL)
149 tmp = fileName;
150 else
151 tmp++;
152 return fnmatch(ap->pattern, tmp, FNM_PERIOD) == 0;
153}
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000154#if ENABLE_FEATURE_FIND_TYPE
Denis Vlasenko92258542006-11-01 10:25:35 +0000155ACTF(type)
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000156{
Denis Vlasenko31c65f22006-10-31 23:39:37 +0000157 return ((statbuf->st_mode & S_IFMT) == ap->type_mask);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000158}
Rob Landleycee605c2005-10-06 16:39:17 +0000159#endif
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000160#if ENABLE_FEATURE_FIND_PERM
Denis Vlasenko92258542006-11-01 10:25:35 +0000161ACTF(perm)
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000162{
Denis Vlasenkofc7f9222007-01-26 23:00:05 +0000163 /* -perm +mode: at least one of perm_mask bits are set */
164 if (ap->perm_char == '+')
165 return (statbuf->st_mode & ap->perm_mask) != 0;
166 /* -perm -mode: all of perm_mask are set */
167 if (ap->perm_char == '-')
168 return (statbuf->st_mode & ap->perm_mask) == ap->perm_mask;
169 /* -perm mode: file mode must match perm_mask */
170 return (statbuf->st_mode & 07777) == ap->perm_mask;
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000171}
Rob Landleycee605c2005-10-06 16:39:17 +0000172#endif
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000173#if ENABLE_FEATURE_FIND_MTIME
Denis Vlasenko92258542006-11-01 10:25:35 +0000174ACTF(mtime)
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000175{
176 time_t file_age = time(NULL) - statbuf->st_mtime;
Denis Vlasenkofc7f9222007-01-26 23:00:05 +0000177 time_t mtime_secs = ap->mtime_days * 24*60*60;
178 if (ap->mtime_char == '+')
179 return file_age >= mtime_secs + 24*60*60;
180 if (ap->mtime_char == '-')
181 return file_age < mtime_secs;
182 /* just numeric mtime */
183 return file_age >= mtime_secs && file_age < (mtime_secs + 24*60*60);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000184}
Rob Landleycee605c2005-10-06 16:39:17 +0000185#endif
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000186#if ENABLE_FEATURE_FIND_MMIN
Denis Vlasenko92258542006-11-01 10:25:35 +0000187ACTF(mmin)
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000188{
189 time_t file_age = time(NULL) - statbuf->st_mtime;
190 time_t mmin_secs = ap->mmin_mins * 60;
Denis Vlasenkofc7f9222007-01-26 23:00:05 +0000191 if (ap->mmin_char == '+')
192 return file_age >= mmin_secs + 60;
193 if (ap->mmin_char == '-')
194 return file_age < mmin_secs;
195 /* just numeric mmin */
196 return file_age >= mmin_secs && file_age < (mmin_secs + 60);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000197}
Paul Fox72d1a232006-01-13 21:05:41 +0000198#endif
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000199#if ENABLE_FEATURE_FIND_NEWER
Denis Vlasenko92258542006-11-01 10:25:35 +0000200ACTF(newer)
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000201{
Denis Vlasenkofc7f9222007-01-26 23:00:05 +0000202 return (ap->newer_mtime < statbuf->st_mtime);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000203}
Rob Landleycee605c2005-10-06 16:39:17 +0000204#endif
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000205#if ENABLE_FEATURE_FIND_INUM
Denis Vlasenko92258542006-11-01 10:25:35 +0000206ACTF(inum)
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000207{
Denis Vlasenkofc7f9222007-01-26 23:00:05 +0000208 return (statbuf->st_ino == ap->inode_num);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000209}
Rob Landleycee605c2005-10-06 16:39:17 +0000210#endif
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000211#if ENABLE_FEATURE_FIND_EXEC
Denis Vlasenko92258542006-11-01 10:25:35 +0000212ACTF(exec)
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000213{
214 int i, rc;
215 char *argv[ap->exec_argc+1];
216 for (i = 0; i < ap->exec_argc; i++)
217 argv[i] = subst(ap->exec_argv[i], ap->subst_count[i], fileName);
218 argv[i] = NULL; /* terminate the list */
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000219 rc = wait4pid(spawn(argv));
Denis Vlasenko8f6c7922006-12-23 00:49:10 +0000220 if (rc)
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000221 bb_perror_msg("%s", argv[0]);
222 for (i = 0; i < ap->exec_argc; i++)
223 free(argv[i]);
224 return rc == 0; /* return 1 if success */
225}
Rob Landleycee605c2005-10-06 16:39:17 +0000226#endif
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000227
Denis Vlasenkoa1007072007-02-02 01:17:52 +0000228#if ENABLE_FEATURE_FIND_USER
229ACTF(user)
230{
231 return (statbuf->st_uid == ap->uid);
232}
233#endif
234
Denis Vlasenko56fce002007-04-04 23:41:35 +0000235#if ENABLE_FEATURE_FIND_GROUP
236ACTF(group)
237{
238 return (statbuf->st_gid == ap->gid);
239}
240#endif
241
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000242#if ENABLE_FEATURE_FIND_PRINT0
Denis Vlasenko92258542006-11-01 10:25:35 +0000243ACTF(print0)
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000244{
245 printf("%s%c", fileName, '\0');
Denis Vlasenko3a6755f2006-10-14 14:24:30 +0000246 return TRUE;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000247}
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000248#endif
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000249
Denis Vlasenko92258542006-11-01 10:25:35 +0000250ACTF(print)
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000251{
252 puts(fileName);
253 return TRUE;
254}
255
Denis Vlasenko56fce002007-04-04 23:41:35 +0000256#if ENABLE_FEATURE_FIND_PAREN
Denis Vlasenko92258542006-11-01 10:25:35 +0000257ACTF(paren)
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000258{
259 return exec_actions(ap->subexpr, fileName, statbuf);
260}
Denis Vlasenko56fce002007-04-04 23:41:35 +0000261#endif
Denis Vlasenko5fa71482006-12-12 22:31:15 +0000262
Bernhard Reutner-Fischer6d79dd62007-04-05 09:40:12 +0000263#if ENABLE_FEATURE_FIND_PRUNE
Denis Vlasenko5f18e7c2006-10-31 03:21:02 +0000264/*
265 * -prune: if -depth is not given, return true and do not descend
266 * current dir; if -depth is given, return false with no effect.
267 * Example:
268 * find dir -name 'asm-*' -prune -o -name '*.[chS]' -print
269 */
Denis Vlasenko92258542006-11-01 10:25:35 +0000270ACTF(prune)
Denis Vlasenko5f18e7c2006-10-31 03:21:02 +0000271{
272 return SKIP;
273}
Denis Vlasenko56fce002007-04-04 23:41:35 +0000274#endif
Denis Vlasenko5fa71482006-12-12 22:31:15 +0000275
Bernhard Reutner-Fischer6d79dd62007-04-05 09:40:12 +0000276#if ENABLE_FEATURE_FIND_SIZE
Denis Vlasenko5fa71482006-12-12 22:31:15 +0000277ACTF(size)
278{
279 return statbuf->st_size == ap->size;
280}
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000281#endif
282
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000283
284static int fileAction(const char *fileName, struct stat *statbuf, void* junk, int depth)
285{
Bernhard Reutner-Fischer32773ac2007-03-29 13:54:17 +0000286 int i;
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000287#ifdef CONFIG_FEATURE_FIND_XDEV
288 if (S_ISDIR(statbuf->st_mode) && xdev_count) {
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000289 for (i = 0; i < xdev_count; i++) {
290 if (xdev_dev[i] != statbuf->st_dev)
291 return SKIP;
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000292 }
293 }
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000294#endif
Bernhard Reutner-Fischer32773ac2007-03-29 13:54:17 +0000295 i = exec_actions(actions, fileName, statbuf);
Denis Vlasenko5f18e7c2006-10-31 03:21:02 +0000296 /* Had no explicit -print[0] or -exec? then print */
Bernhard Reutner-Fischer32773ac2007-03-29 13:54:17 +0000297 if (i && need_print)
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000298 puts(fileName);
Denis Vlasenko5f18e7c2006-10-31 03:21:02 +0000299 /* Cannot return 0: our caller, recursive_action(),
300 * will perror() and skip dirs (if called on dir) */
Bernhard Reutner-Fischer32773ac2007-03-29 13:54:17 +0000301 return i == 0 ? TRUE : i;
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000302}
303
Eric Andersen17d49ef1999-10-06 20:25:32 +0000304
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000305#if ENABLE_FEATURE_FIND_TYPE
Denis Vlasenko434ad542007-01-27 13:45:17 +0000306static int find_type(const char *type)
Matt Kraai096370d2001-02-07 03:52:38 +0000307{
308 int mask = 0;
309
Bernhard Reutner-Fischer307d27d2007-03-29 13:56:02 +0000310 if (*type == 'b')
Denis Vlasenko3a6755f2006-10-14 14:24:30 +0000311 mask = S_IFBLK;
Bernhard Reutner-Fischer307d27d2007-03-29 13:56:02 +0000312 else if (*type == 'c')
Denis Vlasenko3a6755f2006-10-14 14:24:30 +0000313 mask = S_IFCHR;
Bernhard Reutner-Fischer307d27d2007-03-29 13:56:02 +0000314 else if (*type == 'd')
Denis Vlasenko3a6755f2006-10-14 14:24:30 +0000315 mask = S_IFDIR;
Bernhard Reutner-Fischer307d27d2007-03-29 13:56:02 +0000316 else if (*type == 'p')
Denis Vlasenko3a6755f2006-10-14 14:24:30 +0000317 mask = S_IFIFO;
Bernhard Reutner-Fischer307d27d2007-03-29 13:56:02 +0000318 else if (*type == 'f')
Denis Vlasenko3a6755f2006-10-14 14:24:30 +0000319 mask = S_IFREG;
Bernhard Reutner-Fischer307d27d2007-03-29 13:56:02 +0000320 else if (*type == 'l')
Denis Vlasenko3a6755f2006-10-14 14:24:30 +0000321 mask = S_IFLNK;
Bernhard Reutner-Fischer307d27d2007-03-29 13:56:02 +0000322 else if (*type == 's')
Denis Vlasenko3a6755f2006-10-14 14:24:30 +0000323 mask = S_IFSOCK;
Matt Kraai096370d2001-02-07 03:52:38 +0000324
Bernhard Reutner-Fischer307d27d2007-03-29 13:56:02 +0000325 if (mask == 0 || *(type + 1) != '\0')
Bernhard Reutner-Fischer19008b82006-06-07 20:17:41 +0000326 bb_error_msg_and_die(bb_msg_invalid_arg, type, "-type");
Matt Kraai096370d2001-02-07 03:52:38 +0000327
328 return mask;
329}
330#endif
331
Denis Vlasenko4c978632007-02-03 03:31:13 +0000332#if ENABLE_FEATURE_FIND_PERM || ENABLE_FEATURE_FIND_MTIME \
333 || ENABLE_FEATURE_FIND_MMIN
Denis Vlasenkofc7f9222007-01-26 23:00:05 +0000334static const char* plus_minus_num(const char* str)
335{
336 if (*str == '-' || *str == '+')
337 str++;
338 return str;
339}
Denis Vlasenko4c978632007-02-03 03:31:13 +0000340#endif
Denis Vlasenkofc7f9222007-01-26 23:00:05 +0000341
Denis Vlasenko769d1e02007-01-22 23:04:27 +0000342static action*** parse_params(char **argv)
Eric Andersen17d49ef1999-10-06 20:25:32 +0000343{
Denis Vlasenko56fce002007-04-04 23:41:35 +0000344 enum {
345 PARM_a ,
346 PARM_o ,
347 USE_FEATURE_FIND_NOT( PARM_char_not ,)
348 PARM_print ,
349 USE_FEATURE_FIND_PRINT0(PARM_print0 ,)
350 PARM_name ,
351 USE_FEATURE_FIND_TYPE( PARM_type ,)
352 USE_FEATURE_FIND_PERM( PARM_perm ,)
353 USE_FEATURE_FIND_MTIME( PARM_mtime ,)
354 USE_FEATURE_FIND_MMIN( PARM_mmin ,)
355 USE_FEATURE_FIND_NEWER( PARM_newer ,)
356 USE_FEATURE_FIND_INUM( PARM_inum ,)
357 USE_FEATURE_FIND_EXEC( PARM_exec ,)
358 USE_FEATURE_FIND_USER( PARM_user ,)
359 USE_FEATURE_FIND_GROUP( PARM_group ,)
360 USE_FEATURE_FIND_DEPTH( PARM_depth ,)
361 USE_FEATURE_FIND_PAREN( PARM_char_brace,)
Bernhard Reutner-Fischer6d79dd62007-04-05 09:40:12 +0000362 USE_FEATURE_FIND_SIZE( PARM_size ,)
363 USE_FEATURE_FIND_PRUNE( PARM_prune ,)
Denis Vlasenko56fce002007-04-04 23:41:35 +0000364#if ENABLE_DESKTOP
365 PARM_and ,
366 PARM_or ,
367 USE_FEATURE_FIND_NOT( PARM_not ,)
368#endif
369 };
370
371 static const char *const params[] = {
372 "-a" ,
373 "-o" ,
374 USE_FEATURE_FIND_NOT( "!" ,)
375 "-print" ,
376 USE_FEATURE_FIND_PRINT0("-print0",)
377 "-name" ,
378 USE_FEATURE_FIND_TYPE( "-type" ,)
379 USE_FEATURE_FIND_PERM( "-perm" ,)
380 USE_FEATURE_FIND_MTIME( "-mtime" ,)
381 USE_FEATURE_FIND_MMIN( "-mmin" ,)
382 USE_FEATURE_FIND_NEWER( "-newer" ,)
383 USE_FEATURE_FIND_INUM( "-inum" ,)
384 USE_FEATURE_FIND_EXEC( "-exec" ,)
385 USE_FEATURE_FIND_USER( "-user" ,)
386 USE_FEATURE_FIND_GROUP( "-group" ,)
387 USE_FEATURE_FIND_DEPTH( "-depth" ,)
388 USE_FEATURE_FIND_PAREN( "(" ,)
Bernhard Reutner-Fischer6d79dd62007-04-05 09:40:12 +0000389 USE_FEATURE_FIND_SIZE( "-size" ,)
390 USE_FEATURE_FIND_PRUNE( "-prune" ,)
Denis Vlasenko56fce002007-04-04 23:41:35 +0000391#if ENABLE_DESKTOP
392 "-and" ,
393 "-or" ,
394 USE_FEATURE_FIND_NOT( "-not" ,)
395#endif
396 NULL
397 };
398
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000399 action*** appp;
Bernhard Reutner-Fischer10b79962007-02-04 16:09:04 +0000400 unsigned cur_group = 0;
401 unsigned cur_action = 0;
Bernhard Reutner-Fischer32773ac2007-03-29 13:54:17 +0000402 USE_FEATURE_FIND_NOT( bool invert_flag = 0; )
Denis Vlasenko56fce002007-04-04 23:41:35 +0000403
404 /* 'static' doesn't work here! (gcc 4.1.2) */
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000405 action* alloc_action(int sizeof_struct, action_fp f)
406 {
407 action *ap;
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000408 appp[cur_group] = xrealloc(appp[cur_group], (cur_action+2) * sizeof(*appp));
409 appp[cur_group][cur_action++] = ap = xmalloc(sizeof_struct);
410 appp[cur_group][cur_action] = NULL;
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000411 ap->f = f;
Denis Vlasenkocf787cf2007-02-04 17:11:25 +0000412 USE_FEATURE_FIND_NOT( ap->invert = invert_flag; )
Denis Vlasenkob2922642007-02-06 17:38:29 +0000413 USE_FEATURE_FIND_NOT( invert_flag = 0; )
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000414 return ap;
415 }
Denis Vlasenko56fce002007-04-04 23:41:35 +0000416
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000417#define ALLOC_ACTION(name) (action_##name*)alloc_action(sizeof(action_##name), (action_fp) func_##name)
Eric Andersen17d49ef1999-10-06 20:25:32 +0000418
Denis Vlasenkocf787cf2007-02-04 17:11:25 +0000419 appp = xzalloc(2 * sizeof(appp[0])); /* appp[0],[1] == NULL */
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000420
Bernhard Reutner-Fischer557b4582007-03-29 13:55:17 +0000421/* Actions have side effects and return a true or false value
422 * We implement: -print, -print0, -exec
423 *
424 * The rest are tests.
425 *
426 * Tests and actions are grouped by operators
427 * ( expr ) Force precedence
428 * ! expr True if expr is false
429 * -not expr Same as ! expr
430 * expr1 [-a[nd]] expr2 And; expr2 is not evaluated if expr1 is false
431 * expr1 -o[r] expr2 Or; expr2 is not evaluated if expr1 is true
432 * expr1 , expr2 List; both expr1 and expr2 are always evaluated
433 * We implement: (), -a, -o
434 */
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000435 while (*argv) {
Denis Vlasenko434ad542007-01-27 13:45:17 +0000436 const char *arg = argv[0];
437 const char *arg1 = argv[1];
Bernhard Reutner-Fischer557b4582007-03-29 13:55:17 +0000438 int parm = index_in_str_array(params, arg);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000439 /* --- Operators --- */
Denis Vlasenko56fce002007-04-04 23:41:35 +0000440 if (parm == PARM_a USE_DESKTOP(|| parm == PARM_and)) {
Denis Vlasenkocf787cf2007-02-04 17:11:25 +0000441 /* no further special handling required */
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000442 }
Denis Vlasenko56fce002007-04-04 23:41:35 +0000443 else if (parm == PARM_o USE_DESKTOP(|| parm == PARM_or)) {
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000444 /* start new OR group */
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000445 cur_group++;
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000446 appp = xrealloc(appp, (cur_group+2) * sizeof(*appp));
Denis Vlasenkocf787cf2007-02-04 17:11:25 +0000447 /*appp[cur_group] = NULL; - already NULL */
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000448 appp[cur_group+1] = NULL;
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000449 cur_action = 0;
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000450 }
Denis Vlasenkocf787cf2007-02-04 17:11:25 +0000451#if ENABLE_FEATURE_FIND_NOT
Denis Vlasenko56fce002007-04-04 23:41:35 +0000452 else if (parm == PARM_char_not USE_DESKTOP(|| parm == PARM_not)) {
Denis Vlasenkob2922642007-02-06 17:38:29 +0000453 /* also handles "find ! ! -name 'foo*'" */
454 invert_flag ^= 1;
Denis Vlasenkocf787cf2007-02-04 17:11:25 +0000455 }
456#endif
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000457
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000458 /* --- Tests and actions --- */
Denis Vlasenko56fce002007-04-04 23:41:35 +0000459 else if (parm == PARM_print) {
Denis Vlasenkoa3b4fed2006-10-31 03:20:13 +0000460 need_print = 0;
Denis Vlasenkocf787cf2007-02-04 17:11:25 +0000461 /* GNU find ignores '!' here: "find ! -print" */
462 USE_FEATURE_FIND_NOT( invert_flag = 0; )
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000463 (void) ALLOC_ACTION(print);
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000464 }
465#if ENABLE_FEATURE_FIND_PRINT0
Denis Vlasenko56fce002007-04-04 23:41:35 +0000466 else if (parm == PARM_print0) {
Denis Vlasenkoa3b4fed2006-10-31 03:20:13 +0000467 need_print = 0;
Denis Vlasenkocf787cf2007-02-04 17:11:25 +0000468 USE_FEATURE_FIND_NOT( invert_flag = 0; )
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000469 (void) ALLOC_ACTION(print0);
470 }
Paul Foxd7384292006-05-12 14:47:20 +0000471#endif
Denis Vlasenko56fce002007-04-04 23:41:35 +0000472 else if (parm == PARM_name) {
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000473 action_name *ap;
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000474 if (!*++argv)
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000475 bb_error_msg_and_die(bb_msg_requires_arg, arg);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000476 ap = ALLOC_ACTION(name);
477 ap->pattern = arg1;
478 }
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000479#if ENABLE_FEATURE_FIND_TYPE
Denis Vlasenko56fce002007-04-04 23:41:35 +0000480 else if (parm == PARM_type) {
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000481 action_type *ap;
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000482 if (!*++argv)
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000483 bb_error_msg_and_die(bb_msg_requires_arg, arg);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000484 ap = ALLOC_ACTION(type);
485 ap->type_mask = find_type(arg1);
486 }
Rob Landleycee605c2005-10-06 16:39:17 +0000487#endif
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000488#if ENABLE_FEATURE_FIND_PERM
489/* TODO:
490 * -perm mode File's permission bits are exactly mode (octal or symbolic).
491 * Symbolic modes use mode 0 as a point of departure.
492 * -perm -mode All of the permission bits mode are set for the file.
493 * -perm +mode Any of the permission bits mode are set for the file.
494 */
Denis Vlasenko56fce002007-04-04 23:41:35 +0000495 else if (parm == PARM_perm) {
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000496 action_perm *ap;
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000497 if (!*++argv)
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000498 bb_error_msg_and_die(bb_msg_requires_arg, arg);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000499 ap = ALLOC_ACTION(perm);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000500 ap->perm_char = arg1[0];
Denis Vlasenkofc7f9222007-01-26 23:00:05 +0000501 arg1 = plus_minus_num(arg1);
502 ap->perm_mask = 0;
503 if (!bb_parse_mode(arg1, &ap->perm_mask))
504 bb_error_msg_and_die("invalid mode: %s", arg1);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000505 }
Rob Landleycee605c2005-10-06 16:39:17 +0000506#endif
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000507#if ENABLE_FEATURE_FIND_MTIME
Denis Vlasenko56fce002007-04-04 23:41:35 +0000508 else if (parm == PARM_mtime) {
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000509 action_mtime *ap;
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000510 if (!*++argv)
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000511 bb_error_msg_and_die(bb_msg_requires_arg, arg);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000512 ap = ALLOC_ACTION(mtime);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000513 ap->mtime_char = arg1[0];
Denis Vlasenkofc7f9222007-01-26 23:00:05 +0000514 ap->mtime_days = xatoul(plus_minus_num(arg1));
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000515 }
Rob Landleycee605c2005-10-06 16:39:17 +0000516#endif
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000517#if ENABLE_FEATURE_FIND_MMIN
Denis Vlasenko56fce002007-04-04 23:41:35 +0000518 else if (parm == PARM_mmin) {
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000519 action_mmin *ap;
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000520 if (!*++argv)
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000521 bb_error_msg_and_die(bb_msg_requires_arg, arg);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000522 ap = ALLOC_ACTION(mmin);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000523 ap->mmin_char = arg1[0];
Denis Vlasenkofc7f9222007-01-26 23:00:05 +0000524 ap->mmin_mins = xatoul(plus_minus_num(arg1));
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000525 }
Rob Landleycee605c2005-10-06 16:39:17 +0000526#endif
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000527#if ENABLE_FEATURE_FIND_NEWER
Denis Vlasenko56fce002007-04-04 23:41:35 +0000528 else if (parm == PARM_newer) {
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000529 action_newer *ap;
Eric Andersen97d86f22003-01-23 05:27:42 +0000530 struct stat stat_newer;
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000531 if (!*++argv)
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000532 bb_error_msg_and_die(bb_msg_requires_arg, arg);
533 xstat(arg1, &stat_newer);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000534 ap = ALLOC_ACTION(newer);
535 ap->newer_mtime = stat_newer.st_mtime;
536 }
Rob Landleycee605c2005-10-06 16:39:17 +0000537#endif
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000538#if ENABLE_FEATURE_FIND_INUM
Denis Vlasenko56fce002007-04-04 23:41:35 +0000539 else if (parm == PARM_inum) {
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000540 action_inum *ap;
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000541 if (!*++argv)
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000542 bb_error_msg_and_die(bb_msg_requires_arg, arg);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000543 ap = ALLOC_ACTION(inum);
544 ap->inode_num = xatoul(arg1);
545 }
Rob Landleycee605c2005-10-06 16:39:17 +0000546#endif
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000547#if ENABLE_FEATURE_FIND_EXEC
Denis Vlasenko56fce002007-04-04 23:41:35 +0000548 else if (parm == PARM_exec) {
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000549 int i;
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000550 action_exec *ap;
Denis Vlasenkoa3b4fed2006-10-31 03:20:13 +0000551 need_print = 0;
Denis Vlasenkocf787cf2007-02-04 17:11:25 +0000552 USE_FEATURE_FIND_NOT( invert_flag = 0; )
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000553 ap = ALLOC_ACTION(exec);
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000554 ap->exec_argv = ++argv; /* first arg after -exec */
555 ap->exec_argc = 0;
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000556 while (1) {
Bernhard Reutner-Fischer32773ac2007-03-29 13:54:17 +0000557 if (!*argv) /* did not see ';' util end */
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000558 bb_error_msg_and_die(bb_msg_requires_arg, arg);
Denis Vlasenko9ac9e552006-12-23 15:58:11 +0000559 if (LONE_CHAR(argv[0], ';'))
Rob Landley5d3a0e82005-10-04 03:34:39 +0000560 break;
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000561 argv++;
562 ap->exec_argc++;
Rob Landley5d3a0e82005-10-04 03:34:39 +0000563 }
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000564 if (ap->exec_argc == 0)
Denis Vlasenkodf0553b2006-10-29 00:21:47 +0000565 bb_error_msg_and_die(bb_msg_requires_arg, arg);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000566 ap->subst_count = xmalloc(ap->exec_argc * sizeof(int));
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000567 i = ap->exec_argc;
568 while (i--)
569 ap->subst_count[i] = count_subst(ap->exec_argv[i]);
570 }
571#endif
Denis Vlasenko4c978632007-02-03 03:31:13 +0000572#if ENABLE_FEATURE_FIND_USER
Denis Vlasenko56fce002007-04-04 23:41:35 +0000573 else if (parm == PARM_user) {
Denis Vlasenkoa1007072007-02-02 01:17:52 +0000574 action_user *ap;
575 if (!*++argv)
576 bb_error_msg_and_die(bb_msg_requires_arg, arg);
577 ap = ALLOC_ACTION(user);
578 ap->uid = bb_strtou(arg1, NULL, 10);
579 if (errno)
580 ap->uid = xuname2uid(arg1);
581 }
582#endif
Denis Vlasenko56fce002007-04-04 23:41:35 +0000583#if ENABLE_FEATURE_FIND_GROUP
584 else if (parm == PARM_group) {
585 action_group *ap;
586 if (!*++argv)
587 bb_error_msg_and_die(bb_msg_requires_arg, arg);
588 ap = ALLOC_ACTION(group);
589 ap->gid = bb_strtou(arg1, NULL, 10);
590 if (errno)
591 ap->gid = xgroup2gid(arg1);
592 }
593#endif
594#if ENABLE_FEATURE_FIND_DEPTH
595 else if (parm == PARM_depth) {
596 recurse_flags |= action_depthFirst;
597 }
598#endif
599#if ENABLE_FEATURE_FIND_PAREN
600 else if (parm == PARM_char_brace) {
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000601 action_paren *ap;
602 char **endarg;
Bernhard Reutner-Fischer10b79962007-02-04 16:09:04 +0000603 unsigned nested = 1;
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000604
605 endarg = argv;
606 while (1) {
607 if (!*++endarg)
608 bb_error_msg_and_die("unpaired '('");
Denis Vlasenko9ac9e552006-12-23 15:58:11 +0000609 if (LONE_CHAR(*endarg, '('))
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000610 nested++;
Denis Vlasenko9ac9e552006-12-23 15:58:11 +0000611 else if (LONE_CHAR(*endarg, ')') && !--nested) {
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000612 *endarg = NULL;
613 break;
614 }
615 }
616 ap = ALLOC_ACTION(paren);
617 ap->subexpr = parse_params(argv + 1);
Denis Vlasenkoab2aea42007-01-29 22:51:58 +0000618 *endarg = (char*) ")"; /* restore NULLed parameter */
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000619 argv = endarg;
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000620 }
Denis Vlasenko56fce002007-04-04 23:41:35 +0000621#endif
622#if ENABLE_FEATURE_FIND_PRUNE
623 else if (parm == PARM_prune) {
Denis Vlasenkocf787cf2007-02-04 17:11:25 +0000624 USE_FEATURE_FIND_NOT( invert_flag = 0; )
Denis Vlasenko5f18e7c2006-10-31 03:21:02 +0000625 (void) ALLOC_ACTION(prune);
626 }
Denis Vlasenko56fce002007-04-04 23:41:35 +0000627#endif
628#if ENABLE_FEATURE_FIND_SIZE
629 else if (parm == PARM_size) {
Denis Vlasenko5fa71482006-12-12 22:31:15 +0000630 action_size *ap;
631 if (!*++argv)
632 bb_error_msg_and_die(bb_msg_requires_arg, arg);
633 ap = ALLOC_ACTION(size);
634 ap->size = XATOOFF(arg1);
635 }
Rob Landleycee605c2005-10-06 16:39:17 +0000636#endif
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000637 else
Manuel Novoa III cad53642003-03-19 09:13:01 +0000638 bb_show_usage();
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000639 argv++;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000640 }
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000641 return appp;
642#undef ALLOC_ACTION
643}
644
645
Denis Vlasenko06af2162007-02-03 17:28:39 +0000646int find_main(int argc, char **argv);
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000647int find_main(int argc, char **argv)
648{
Denis Vlasenko7d6c9292007-04-05 00:35:43 +0000649 static const char * const options[] = {
Bernhard Reutner-Fischera87ed2c2007-03-29 13:56:49 +0000650 "-follow",
651USE_FEATURE_FIND_XDEV( "-xdev", )
652 NULL
653 };
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000654
Denis Vlasenko7d6c9292007-04-05 00:35:43 +0000655 bool dereference = FALSE;
656 char *arg;
657 char **argp;
658 int i, firstopt, status = EXIT_SUCCESS;
659
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000660 for (firstopt = 1; firstopt < argc; firstopt++) {
661 if (argv[firstopt][0] == '-')
662 break;
Denis Vlasenkocf787cf2007-02-04 17:11:25 +0000663 if (ENABLE_FEATURE_FIND_NOT && LONE_CHAR(argv[firstopt], '!'))
664 break;
Denis Vlasenko56fce002007-04-04 23:41:35 +0000665#if ENABLE_FEATURE_FIND_PAREN
Denis Vlasenko9ac9e552006-12-23 15:58:11 +0000666 if (LONE_CHAR(argv[firstopt], '('))
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000667 break;
668#endif
669 }
670 if (firstopt == 1) {
Denis Vlasenkoab2aea42007-01-29 22:51:58 +0000671 argv[0] = (char*)".";
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000672 argv--;
673 firstopt++;
674 }
675
Bernhard Reutner-Fischer32773ac2007-03-29 13:54:17 +0000676/* All options always return true. They always take effect
677 * rather than being processed only when their place in the
678 * expression is reached.
679 * We implement: -follow, -xdev
680 */
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000681 /* Process options, and replace then with -a */
Denis Vlasenko92258542006-11-01 10:25:35 +0000682 /* (-a will be ignored by recursive parser later) */
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000683 argp = &argv[firstopt];
Denis Vlasenko92258542006-11-01 10:25:35 +0000684 while ((arg = argp[0])) {
Bernhard Reutner-Fischera87ed2c2007-03-29 13:56:49 +0000685 i = index_in_str_array(options, arg);
686 if (i == 0) { /* -follow */
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000687 dereference = TRUE;
Denis Vlasenkoab2aea42007-01-29 22:51:58 +0000688 argp[0] = (char*)"-a";
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000689 }
690#if ENABLE_FEATURE_FIND_XDEV
Bernhard Reutner-Fischera87ed2c2007-03-29 13:56:49 +0000691 else if (i == 1) { /* -xdev */
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000692 struct stat stbuf;
693 if (!xdev_count) {
694 xdev_count = firstopt - 1;
695 xdev_dev = xmalloc(xdev_count * sizeof(dev_t));
696 for (i = 1; i < firstopt; i++) {
697 /* not xstat(): shouldn't bomb out on
698 * "find not_exist exist -xdev" */
Denis Vlasenkoc9d34da2007-01-03 03:15:58 +0000699 if (stat(argv[i], &stbuf))
700 stbuf.st_dev = -1L;
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000701 xdev_dev[i-1] = stbuf.st_dev;
702 }
703 }
Denis Vlasenkoab2aea42007-01-29 22:51:58 +0000704 argp[0] = (char*)"-a";
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000705 }
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000706#endif
Denis Vlasenkoc9d34da2007-01-03 03:15:58 +0000707 argp++;
Denis Vlasenko666da5e2006-12-26 18:17:42 +0000708 }
Denis Vlasenko6191a7a2006-10-30 02:10:47 +0000709
710 actions = parse_params(&argv[firstopt]);
Denis Vlasenko5d499e12006-10-29 19:07:01 +0000711
Denis Vlasenkoe2fb7192006-10-29 19:03:56 +0000712 for (i = 1; i < firstopt; i++) {
713 if (!recursive_action(argv[i],
Denis Vlasenko56fce002007-04-04 23:41:35 +0000714 recurse_flags|(1<<dereference), /* flags */
Bernhard Reutner-Fischer3e816c12007-03-29 10:30:50 +0000715 fileAction, /* file action */
716 fileAction, /* dir action */
717 NULL, /* user data */
718 0)) /* depth */
Denis Vlasenkoe2fb7192006-10-29 19:03:56 +0000719 status = EXIT_FAILURE;
720 }
Matt Kraai096370d2001-02-07 03:52:38 +0000721 return status;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000722}