summaryrefslogtreecommitdiffstats
path: root/usr.bin/find
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2001-05-03 18:05:35 +0000
committerphk <phk@FreeBSD.org>2001-05-03 18:05:35 +0000
commite51263b8a6769bca310145953de7cb2a93696e64 (patch)
tree9eec6ef5730dc41824c3e49c7f3642ecef218180 /usr.bin/find
parentd7b11c99fc99c4b8a79d95f29ec61a701a8956f2 (diff)
downloadFreeBSD-src-e51263b8a6769bca310145953de7cb2a93696e64.zip
FreeBSD-src-e51263b8a6769bca310145953de7cb2a93696e64.tar.gz
They add the following commands:
-anewer -cnewer -mnewer -okdir -newer[acm][acmt] With it, you can form queries like find . -newerct '1 minute ago' -print As an extra bonus, the program is ANSI-fied - the original version relies on some obscure features of K&R C. (This PR was submitted in 1999, and the submittor has kept the patch updated ever since, hats off for him guys, and how about you close a PR ??) PR: 9374 Submitted by: Martin Birgmeier <Martin.Birgmeier@aon.at>
Diffstat (limited to 'usr.bin/find')
-rw-r--r--usr.bin/find/Makefile5
-rw-r--r--usr.bin/find/extern.h100
-rw-r--r--usr.bin/find/find.161
-rw-r--r--usr.bin/find/find.c17
-rw-r--r--usr.bin/find/find.h71
-rw-r--r--usr.bin/find/function.c1296
-rw-r--r--usr.bin/find/ls.c2
-rw-r--r--usr.bin/find/operator.c38
-rw-r--r--usr.bin/find/option.c130
9 files changed, 793 insertions, 927 deletions
diff --git a/usr.bin/find/Makefile b/usr.bin/find/Makefile
index 9691657..a815525 100644
--- a/usr.bin/find/Makefile
+++ b/usr.bin/find/Makefile
@@ -3,6 +3,9 @@
CFLAGS+= -Wall
PROG= find
-SRCS= find.c function.c ls.c main.c misc.c operator.c option.c
+SRCS= find.c function.c ls.c main.c misc.c operator.c option.c getdate.y
+CLEANFILES+= getdate.c y.tab.h
+CFLAGS+= -I${.CURDIR}/../../gnu/usr.bin/cvs/lib -DHAVE_CONFIG_H
+.PATH: ${.CURDIR}/../../contrib/cvs/lib
.include <bsd.prog.mk>
diff --git a/usr.bin/find/extern.h b/usr.bin/find/extern.h
index 442a950..f200786 100644
--- a/usr.bin/find/extern.h
+++ b/usr.bin/find/extern.h
@@ -47,50 +47,68 @@ PLAN *paren_squish __P((PLAN *));
struct stat;
void printlong __P((char *, char *, struct stat *));
int queryuser __P((char **));
+OPTION *option __P((char *));
-PLAN *c_amin __P((char *));
-PLAN *c_atime __P((char *));
-PLAN *c_cmin __P((char *));
-PLAN *c_ctime __P((char *));
-PLAN *c_delete __P((void));
-PLAN *c_depth __P((void));
-PLAN *c_empty __P((void));
-PLAN *c_exec __P((char ***, int));
-PLAN *c_flags __P((char *));
-PLAN *c_execdir __P((char ***));
-PLAN *c_follow __P((void));
+creat_f c_Xmin;
+creat_f c_Xtime;
+creat_f c_and;
+creat_f c_delete;
+creat_f c_depth;
+creat_f c_empty;
+creat_f c_exec;
+creat_f c_flags;
+creat_f c_follow;
#if !defined(__NetBSD__)
-PLAN *c_fstype __P((char *));
+creat_f c_fstype;
#endif
-PLAN *c_group __P((char *));
-PLAN *c_iname __P((char *));
-PLAN *c_inum __P((char *));
-PLAN *c_ipath __P((char *));
-PLAN *c_iregex __P((char *));
-PLAN *c_links __P((char *));
-PLAN *c_ls __P((void));
-PLAN *c_name __P((char *));
-PLAN *c_newer __P((char *));
-PLAN *c_nogroup __P((void));
-PLAN *c_nouser __P((void));
-PLAN *c_path __P((char *));
-PLAN *c_perm __P((char *));
-PLAN *c_print __P((void));
-PLAN *c_print0 __P((void));
-PLAN *c_prune __P((void));
-PLAN *c_regex __P((char *));
-PLAN *c_size __P((char *));
-PLAN *c_type __P((char *));
-PLAN *c_user __P((char *));
-PLAN *c_xdev __P((void));
-PLAN *c_openparen __P((void));
-PLAN *c_closeparen __P((void));
-PLAN *c_maxdepth __P((char *));
-PLAN *c_mindepth __P((char *));
-PLAN *c_mmin __P((char *));
-PLAN *c_mtime __P((char *));
-PLAN *c_not __P((void));
-PLAN *c_or __P((void));
+creat_f c_group;
+creat_f c_inum;
+creat_f c_links;
+creat_f c_ls;
+creat_f c_mXXdepth;
+creat_f c_name;
+creat_f c_newer;
+creat_f c_nogroup;
+creat_f c_nouser;
+creat_f c_perm;
+creat_f c_print;
+creat_f c_regex;
+creat_f c_simple;
+creat_f c_size;
+creat_f c_type;
+creat_f c_user;
+creat_f c_xdev;
+
+exec_f f_Xmin;
+exec_f f_Xtime;
+exec_f f_always_true;
+exec_f f_closeparen;
+exec_f f_delete;
+exec_f f_empty;
+exec_f f_exec;
+exec_f f_expr;
+exec_f f_flags;
+exec_f f_fstype;
+exec_f f_group;
+exec_f f_inum;
+exec_f f_links;
+exec_f f_ls;
+exec_f f_name;
+exec_f f_newer;
+exec_f f_nogroup;
+exec_f f_not;
+exec_f f_nouser;
+exec_f f_openparen;
+exec_f f_or;
+exec_f f_path;
+exec_f f_perm;
+exec_f f_print;
+exec_f f_print0;
+exec_f f_prune;
+exec_f f_regex;
+exec_f f_size;
+exec_f f_type;
+exec_f f_user;
extern int ftsoptions, isdeprecated, isdepth, isoutput, issort, isxargs;
extern int mindepth, maxdepth;
diff --git a/usr.bin/find/find.1 b/usr.bin/find/find.1
index 10bf481..0a8d10b 100644
--- a/usr.bin/find/find.1
+++ b/usr.bin/find/find.1
@@ -160,6 +160,9 @@ True if the difference between the file last access time and the time
was started, rounded up to the next full minute, is
.Ar n
minutes.
+.It Ic -anewer Ar file
+Same as
+.Ic -neweram .
.It Ic -atime Ar n
True if the difference between the file last access time and the time
.Nm
@@ -173,6 +176,9 @@ information and the time
was started, rounded up to the next full minute, is
.Ar n
minutes.
+.It Ic -cnewer Ar file
+Same as
+.Ic -newercm .
.It Ic -ctime Ar n
True if the difference between the time of last change of file status
information and the time
@@ -256,6 +262,9 @@ will be displayed instead of the size in bytes.
If the file is a symbolic link, the pathname of the linked\-to file will be
displayed preceded by ``\->''.
The format is identical to that produced by ``ls \-dgils''.
+.It Ic -mnewer Ar file
+Same as
+.Ic -newer .
.It Ic -maxdepth Ar n
True if the depth of the current file into the tree is less than or equal to
.Ar n .
@@ -287,6 +296,14 @@ If the response is other than ``y'' the command is not executed and the
value of the
.Ar \&ok
expression is false.
+.It Ic \&-okdir Ar utility Op argument ... ;
+The
+.Ic \&-okdir
+primary is identical to the
+.Ic -execdir
+primary with the same exception as described for the
+.Ic \&-ok
+primary.
.It Ic -name Ar pattern
True if the last component of the pathname being examined matches
.Ar pattern .
@@ -312,6 +329,46 @@ but the match is case insensitive.
.It Ic -newer Ar file
True if the current file has a more recent last modification time than
.Ar file .
+.It Ic -newerXY Ar file
+True if the current file has a more recent last access time (
+.Ic X
+=
+.Ic a
+), change time (
+.Ic X
+=
+.Ic c
+), or modification time (
+.Ic X
+=
+.Ic m
+) than the last access time (
+.Ic Y
+=
+.Ic a
+), change time (
+.Ic Y
+=
+.Ic c
+), or modification time (
+.Ic Y
+=
+.Ic m
+) of
+.Ar file .
+In addition, if
+.Ic Y
+=
+.Ic t ,
+then
+.Ar file
+is instead interpreted as a direct date specification of the form
+understood by
+.Xr cvs 1 .
+Note that
+.Ic -newermm
+is equivalent to
+.Ic -newer .
.It Ic -nouser
True if the file belongs to an unknown user.
.It Ic -nogroup
@@ -512,10 +569,14 @@ and owned by ``wnj''.
.It Li "find / \e( -newer ttt -or -user wnj \e) -print"
Print out a list of all the files that are either owned by ``wnj'' or
that are newer than ``ttt''.
+.It Li "find . -newerct '1 minute ago' -print"
+Print out a list of all the files whose inode change time is more
+recent than the current time minus one minute.
.El
.Sh SEE ALSO
.Xr chflags 1 ,
.Xr chmod 1 ,
+.Xr cvs 1 ,
.Xr locate 1 ,
.Xr whereis 1 ,
.Xr which 1 ,
diff --git a/usr.bin/find/find.c b/usr.bin/find/find.c
index ce2595e..b10715b 100644
--- a/usr.bin/find/find.c
+++ b/usr.bin/find/find.c
@@ -116,17 +116,24 @@ find_formplan(argv)
* necessary, and add a -print node on the end.
*/
if (!isoutput) {
+ OPTION *p;
+ char **argv = 0;
+
if (plan == NULL) {
- new = c_print();
+ p = option("-print");
+ new = (p->create)(p, &argv);
tail = plan = new;
} else {
- new = c_openparen();
+ p = option("(");
+ new = (p->create)(p, &argv);
new->next = plan;
plan = new;
- new = c_closeparen();
+ p = option(")");
+ new = (p->create)(p, &argv);
tail->next = new;
tail = new;
- new = c_print();
+ p = option("-print");
+ new = (p->create)(p, &argv);
tail->next = new;
tail = new;
}
@@ -220,7 +227,7 @@ find_execute(plan, paths)
* false or all have been executed. This is where we do all
* the work specified by the user on the command line.
*/
- for (p = plan; p && (p->eval)(p, entry); p = p->next);
+ for (p = plan; p && (p->execute)(p, entry); p = p->next);
if (maxdepth != -1 && entry->fts_level >= maxdepth) {
if (fts_set(tree, entry, FTS_SKIP))
diff --git a/usr.bin/find/find.h b/usr.bin/find/find.h
index f240fc1..ce09344 100644
--- a/usr.bin/find/find.h
+++ b/usr.bin/find/find.h
@@ -39,37 +39,46 @@
#include <regex.h>
-/* node type */
-enum ntype {
- N_AND = 1, /* must start > 0 */
- N_AMIN, N_ATIME, N_CLOSEPAREN, N_CMIN, N_CTIME, N_DEPTH,
- N_EMPTY, N_EXEC, N_EXECDIR, N_EXPR, N_FLAGS,
- N_FOLLOW, N_FSTYPE, N_GROUP, N_INUM, N_LINKS, N_LS, N_MMIN,
- N_MTIME, N_NAME, N_INAME, N_PATH, N_IPATH, N_REGEX, N_IREGEX,
- N_NEWER, N_NOGROUP, N_NOT, N_NOUSER, N_OK, N_OPENPAREN, N_OR,
- N_PERM, N_PRINT, N_PRUNE, N_SIZE, N_TYPE, N_USER, N_XDEV,
- N_PRINT0, N_DELETE, N_MAXDEPTH, N_MINDEPTH
-};
+/* forward declarations */
+struct _plandata;
+struct _option;
+
+/* execute function */
+typedef int exec_f __P((struct _plandata *, FTSENT *));
+/* create function */
+typedef struct _plandata *creat_f(struct _option *, char ***);
+
+/* function modifiers */
+#define F_NEEDOK 0x00000001 /* -ok vs. -exec */
+#define F_EXECDIR 0x00000002 /* -execdir vs. -exec */
+#define F_TIME_A 0x00000004 /* one of -atime, -anewer, -newera* */
+#define F_TIME_C 0x00000008 /* one of -ctime, -cnewer, -newerc* */
+#define F_TIME2_A 0x00000010 /* one of -newer?a */
+#define F_TIME2_C 0x00000020 /* one of -newer?c */
+#define F_TIME2_T 0x00000040 /* one of -newer?t */
+#define F_MAXDEPTH F_TIME_A /* maxdepth vs. mindepth */
+/* command line function modifiers */
+#define F_EQUAL 0x00000000 /* [acm]min [acm]time inum links size */
+#define F_LESSTHAN 0x00000100
+#define F_GREATER 0x00000200
+#define F_ELG_MASK 0x00000300
+#define F_ATLEAST 0x00000400 /* flags perm */
+#define F_ANY 0x00000800 /* perm */
+#define F_MTMASK 0x00003000
+#define F_MTFLAG 0x00000000 /* fstype */
+#define F_MTTYPE 0x00001000
+#define F_MTUNKNOWN 0x00002000
+#define F_IGNCASE 0x00010000 /* iname ipath iregex */
/* node definition */
typedef struct _plandata {
- struct _plandata *next; /* next node */
- int (*eval) /* node evaluation function */
- __P((struct _plandata *, FTSENT *));
-#define F_EQUAL 1 /* [acm]time inum links size */
-#define F_LESSTHAN 2
-#define F_GREATER 3
-#define F_NEEDOK 1 /* exec ok */
-#define F_MTFLAG 1 /* fstype */
-#define F_MTTYPE 2
-#define F_ATLEAST 1 /* perm */
-#define F_ANY 2 /* perm */
- int flags; /* private flags */
- enum ntype type; /* plan node type */
+ struct _plandata *next; /* next node */
+ exec_f *execute; /* node evaluation function */
+ int flags; /* private flags */
union {
- gid_t _g_data; /* gid */
- ino_t _i_data; /* inode */
- mode_t _m_data; /* mode mask */
+ gid_t _g_data; /* gid */
+ ino_t _i_data; /* inode */
+ mode_t _m_data; /* mode mask */
struct {
u_long _f_flags;
u_long _f_mask;
@@ -110,12 +119,8 @@ typedef struct _plandata {
typedef struct _option {
char *name; /* option name */
- enum ntype token; /* token type */
- PLAN *(*create)(); /* create function: DON'T PROTOTYPE! */
-#define O_NONE 0x01 /* no call required */
-#define O_ZERO 0x02 /* pass: nothing */
-#define O_ARGV 0x04 /* pass: argv, increment argv */
-#define O_ARGVP 0x08 /* pass: *argv, N_OK || N_EXEC || N_EXECDIR */
+ creat_f *create; /* create function */
+ exec_f *execute; /* execute function */
int flags;
} OPTION;
diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c
index d448946..a60c4c4 100644
--- a/usr.bin/find/function.c
+++ b/usr.bin/find/function.c
@@ -48,6 +48,7 @@ static const char rcsid[] =
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/mount.h>
+#include <sys/timeb.h>
#include <dirent.h>
#include <err.h>
@@ -64,8 +65,10 @@ static const char rcsid[] =
#include "find.h"
+time_t get_date __P((char *date, struct timeb *now));
+
#define COMPARE(a, b) { \
- switch (plan->flags) { \
+ switch (plan->flags & F_ELG_MASK) { \
case F_EQUAL: \
return (a == b); \
case F_LESSTHAN: \
@@ -77,9 +80,19 @@ static const char rcsid[] =
} \
}
-static int do_f_regex __P((PLAN *, FTSENT *, int));
-static PLAN *do_c_regex __P((char *, int));
-static PLAN *palloc __P((enum ntype, int (*) __P((PLAN *, FTSENT *))));
+static PLAN *
+palloc(option)
+ OPTION *option;
+{
+ PLAN *new;
+
+ if ((new = malloc(sizeof(PLAN))) == NULL)
+ err(1, NULL);
+ new->execute = option->execute;
+ new->flags = option->flags;
+ new->next = NULL;
+ return new;
+}
/*
* find_parsenum --
@@ -98,14 +111,14 @@ find_parsenum(plan, option, vp, endch)
switch (*str) {
case '+':
++str;
- plan->flags = F_GREATER;
+ plan->flags |= F_GREATER;
break;
case '-':
++str;
- plan->flags = F_LESSTHAN;
+ plan->flags |= F_LESSTHAN;
break;
default:
- plan->flags = F_EQUAL;
+ plan->flags |= F_EQUAL;
break;
}
@@ -121,143 +134,218 @@ find_parsenum(plan, option, vp, endch)
errx(1, "%s: %s: illegal trailing character", option, vp);
if (endch)
*endch = endchar[0];
- return (value);
+ return value;
}
/*
+ * nextarg --
+ * Check that another argument still exists, return a pointer to it,
+ * and increment the argument vector pointer.
+ */
+static char *
+nextarg(option, argvp)
+ OPTION *option;
+ char ***argvp;
+{
+ char *arg;
+
+ if ((arg = **argvp) == 0)
+ errx(1, "%s: requires additional arguments", option->name);
+ (*argvp)++;
+ return arg;
+} /* nextarg() */
+
+/*
* The value of n for the inode times (atime, ctime, and mtime) is a range,
* i.e. n matches from (n - 1) to n 24 hour periods. This interacts with
* -n, such that "-mtime -1" would be less than 0 days, which isn't what the
* user wanted. Correct so that -1 is "less than 1".
*/
-#define TIME_CORRECT(p, ttype) \
- if ((p)->type == ttype && (p)->flags == F_LESSTHAN) \
+#define TIME_CORRECT(p) \
+ if (((p)->flags & F_ELG_MASK) == F_LESSTHAN) \
++((p)->t_data);
/*
- * -amin n functions --
+ * -[acm]min n functions --
*
- * True if the difference between the file access time and the
- * current time is n min periods.
+ * True if the difference between the
+ * file access time (-amin)
+ * last change of file status information (-cmin)
+ * file modification time (-mmin)
+ * and the current time is n min periods.
*/
int
-f_amin(plan, entry)
+f_Xmin(plan, entry)
PLAN *plan;
FTSENT *entry;
{
extern time_t now;
- COMPARE((now - entry->fts_statp->st_atime +
- 60 - 1) / 60, plan->t_data);
+ if (plan->flags & F_TIME_C) {
+ COMPARE((now - entry->fts_statp->st_ctime +
+ 60 - 1) / 60, plan->t_data);
+ } else if (plan->flags & F_TIME_A) {
+ COMPARE((now - entry->fts_statp->st_atime +
+ 60 - 1) / 60, plan->t_data);
+ } else {
+ COMPARE((now - entry->fts_statp->st_mtime +
+ 60 - 1) / 60, plan->t_data);
+ }
}
PLAN *
-c_amin(arg)
- char *arg;
+c_Xmin(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
+ char *nmins;
PLAN *new;
+ nmins = nextarg(option, argvp);
ftsoptions &= ~FTS_NOSTAT;
- new = palloc(N_AMIN, f_amin);
- new->t_data = find_parsenum(new, "-amin", arg, NULL);
- TIME_CORRECT(new, N_AMIN);
- return (new);
+ new = palloc(option);
+ new->t_data = find_parsenum(new, option->name, nmins, NULL);
+ TIME_CORRECT(new);
+ return new;
}
-
/*
- * -atime n functions --
+ * -[acm]time n functions --
*
- * True if the difference between the file access time and the
- * current time is n 24 hour periods.
+ * True if the difference between the
+ * file access time (-atime)
+ * last change of file status information (-ctime)
+ * file modification time (-mtime)
+ * and the current time is n 24 hour periods.
*/
+
int
-f_atime(plan, entry)
+f_Xtime(plan, entry)
PLAN *plan;
FTSENT *entry;
{
extern time_t now;
- COMPARE((now - entry->fts_statp->st_atime +
- 86400 - 1) / 86400, plan->t_data);
+ if (plan->flags & F_TIME_C) {
+ COMPARE((now - entry->fts_statp->st_ctime +
+ 86400 - 1) / 86400, plan->t_data);
+ } else if (plan->flags & F_TIME_A) {
+ COMPARE((now - entry->fts_statp->st_atime +
+ 86400 - 1) / 86400, plan->t_data);
+ } else {
+ COMPARE((now - entry->fts_statp->st_mtime +
+ 86400 - 1) / 86400, plan->t_data);
+ }
}
PLAN *
-c_atime(arg)
- char *arg;
+c_Xtime(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
+ char *ndays;
PLAN *new;
+ ndays = nextarg(option, argvp);
ftsoptions &= ~FTS_NOSTAT;
- new = palloc(N_ATIME, f_atime);
- new->t_data = find_parsenum(new, "-atime", arg, NULL);
- TIME_CORRECT(new, N_ATIME);
- return (new);
+ new = palloc(option);
+ new->t_data = find_parsenum(new, option->name, ndays, NULL);
+ TIME_CORRECT(new);
+ return new;
}
-
/*
- * -cmin n functions --
+ * -maxdepth/-mindepth n functions --
+ *
+ * Does the same as -prune if the level of the current file is
+ * greater/less than the specified maximum/minimum depth.
*
- * True if the difference between the last change of file
- * status information and the current time is n min periods.
+ * Note that -maxdepth and -mindepth are handled specially in
+ * find_execute() so their f_* functions are set to f_always_true().
*/
-int
-f_cmin(plan, entry)
- PLAN *plan;
- FTSENT *entry;
-{
- extern time_t now;
-
- COMPARE((now - entry->fts_statp->st_ctime +
- 60 - 1) / 60, plan->t_data);
-}
-
PLAN *
-c_cmin(arg)
- char *arg;
+c_mXXdepth(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
+ char *dstr;
PLAN *new;
- ftsoptions &= ~FTS_NOSTAT;
+ dstr = nextarg(option, argvp);
+ if (dstr[0] == '-')
+ /* all other errors handled by find_parsenum() */
+ errx(1, "%s: %s: value must be positive", option->name, dstr);
- new = palloc(N_CMIN, f_cmin);
- new->t_data = find_parsenum(new, "-cmin", arg, NULL);
- TIME_CORRECT(new, N_CMIN);
- return (new);
+ new = palloc(option);
+ if (option->flags & F_MAXDEPTH)
+ maxdepth = find_parsenum(new, option->name, dstr, NULL);
+ else
+ mindepth = find_parsenum(new, option->name, dstr, NULL);
+ return new;
}
/*
- * -ctime n functions --
+ * -delete functions --
*
- * True if the difference between the last change of file
- * status information and the current time is n 24 hour periods.
+ * True always. Makes its best shot and continues on regardless.
*/
int
-f_ctime(plan, entry)
+f_delete(plan, entry)
PLAN *plan;
FTSENT *entry;
{
- extern time_t now;
+ /* ignore these from fts */
+ if (strcmp(entry->fts_accpath, ".") == 0 ||
+ strcmp(entry->fts_accpath, "..") == 0)
+ return 1;
+
+ /* sanity check */
+ if (isdepth == 0 || /* depth off */
+ (ftsoptions & FTS_NOSTAT) || /* not stat()ing */
+ !(ftsoptions & FTS_PHYSICAL) || /* physical off */
+ (ftsoptions & FTS_LOGICAL)) /* or finally, logical on */
+ errx(1, "-delete: insecure options got turned on");
+
+ /* Potentially unsafe - do not accept relative paths whatsoever */
+ if (strchr(entry->fts_accpath, '/') != NULL)
+ errx(1, "-delete: %s: relative path potentially not safe",
+ entry->fts_accpath);
- COMPARE((now - entry->fts_statp->st_ctime +
- 86400 - 1) / 86400, plan->t_data);
+ /* Turn off user immutable bits if running as root */
+ if ((entry->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
+ !(entry->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
+ geteuid() == 0)
+ chflags(entry->fts_accpath,
+ entry->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
+
+ /* rmdir directories, unlink everything else */
+ if (S_ISDIR(entry->fts_statp->st_mode)) {
+ if (rmdir(entry->fts_accpath) < 0 && errno != ENOTEMPTY)
+ warn("-delete: rmdir(%s)", entry->fts_path);
+ } else {
+ if (unlink(entry->fts_accpath) < 0)
+ warn("-delete: unlink(%s)", entry->fts_path);
+ }
+
+ /* "succeed" */
+ return 1;
}
PLAN *
-c_ctime(arg)
- char *arg;
+c_delete(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
- PLAN *new;
- ftsoptions &= ~FTS_NOSTAT;
+ ftsoptions &= ~FTS_NOSTAT; /* no optimise */
+ ftsoptions |= FTS_PHYSICAL; /* disable -follow */
+ ftsoptions &= ~FTS_LOGICAL; /* disable -follow */
+ isoutput = 1; /* possible output */
+ isdepth = 1; /* -depth implied */
- new = palloc(N_CTIME, f_ctime);
- new->t_data = find_parsenum(new, "-ctime", arg, NULL);
- TIME_CORRECT(new, N_CTIME);
- return (new);
+ return palloc(option);
}
@@ -273,119 +361,17 @@ f_always_true(plan, entry)
PLAN *plan;
FTSENT *entry;
{
- return (1);
+ return 1;
}
PLAN *
-c_depth()
-{
- isdepth = 1;
-
- return (palloc(N_DEPTH, f_always_true));
-}
-
-/*
- * [-exec | -ok] utility [arg ... ] ; functions --
- *
- * True if the executed utility returns a zero value as exit status.
- * The end of the primary expression is delimited by a semicolon. If
- * "{}" occurs anywhere, it gets replaced by the current pathname.
- * The current directory for the execution of utility is the same as
- * the current directory when the find utility was started.
- *
- * The primary -ok is different in that it requests affirmation of the
- * user before executing the utility.
- */
-int
-f_exec(plan, entry)
- register PLAN *plan;
- FTSENT *entry;
-{
- extern int dotfd;
- register int cnt;
- pid_t pid;
- int status;
-
- for (cnt = 0; plan->e_argv[cnt]; ++cnt)
- if (plan->e_len[cnt])
- brace_subst(plan->e_orig[cnt], &plan->e_argv[cnt],
- entry->fts_path, plan->e_len[cnt]);
-
- if (plan->flags == F_NEEDOK && !queryuser(plan->e_argv))
- return (0);
-
- /* make sure find output is interspersed correctly with subprocesses */
- fflush(stdout);
-
- switch (pid = fork()) {
- case -1:
- err(1, "fork");
- /* NOTREACHED */
- case 0:
- if (fchdir(dotfd)) {
- warn("chdir");
- _exit(1);
- }
- execvp(plan->e_argv[0], plan->e_argv);
- warn("%s", plan->e_argv[0]);
- _exit(1);
- }
- pid = waitpid(pid, &status, 0);
- return (pid != -1 && WIFEXITED(status) && !WEXITSTATUS(status));
-}
-
-/*
- * c_exec --
- * build three parallel arrays, one with pointers to the strings passed
- * on the command line, one with (possibly duplicated) pointers to the
- * argv array, and one with integer values that are lengths of the
- * strings, but also flags meaning that the string has to be massaged.
- */
-PLAN *
-c_exec(argvp, isok)
+c_depth(option, argvp)
+ OPTION *option;
char ***argvp;
- int isok;
{
- PLAN *new; /* node returned */
- register int cnt;
- register char **argv, **ap, *p;
-
- isoutput = 1;
-
- new = palloc(N_EXEC, f_exec);
- if (isok)
- new->flags = F_NEEDOK;
-
- for (ap = argv = *argvp;; ++ap) {
- if (!*ap)
- errx(1,
- "%s: no terminating \";\"", isok ? "-ok" : "-exec");
- if (**ap == ';')
- break;
- }
-
- cnt = ap - *argvp + 1;
- new->e_argv = (char **)emalloc((u_int)cnt * sizeof(char *));
- new->e_orig = (char **)emalloc((u_int)cnt * sizeof(char *));
- new->e_len = (int *)emalloc((u_int)cnt * sizeof(int));
-
- for (argv = *argvp, cnt = 0; argv < ap; ++argv, ++cnt) {
- new->e_orig[cnt] = *argv;
- for (p = *argv; *p; ++p)
- if (p[0] == '{' && p[1] == '}') {
- new->e_argv[cnt] = emalloc((u_int)MAXPATHLEN);
- new->e_len[cnt] = MAXPATHLEN;
- break;
- }
- if (!*p) {
- new->e_argv[cnt] = *argv;
- new->e_len[cnt] = 0;
- }
- }
- new->e_argv[cnt] = new->e_orig[cnt] = NULL;
+ isdepth = 1;
- *argvp = argv + 1;
- return (new);
+ return palloc(option);
}
/*
@@ -398,8 +384,9 @@ f_empty(plan, entry)
PLAN *plan;
FTSENT *entry;
{
- if (S_ISREG(entry->fts_statp->st_mode) && entry->fts_statp->st_size == 0)
- return (1);
+ if (S_ISREG(entry->fts_statp->st_mode) &&
+ entry->fts_statp->st_size == 0)
+ return 1;
if (S_ISDIR(entry->fts_statp->st_mode)) {
struct dirent *dp;
int empty;
@@ -417,50 +404,63 @@ f_empty(plan, entry)
break;
}
closedir(dir);
- return (empty);
+ return empty;
}
- return (0);
+ return 0;
}
PLAN *
-c_empty()
+c_empty(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
ftsoptions &= ~FTS_NOSTAT;
- return (palloc(N_EMPTY, f_empty));
+ return palloc(option);
}
/*
- * -execdir utility [arg ... ] ; functions --
+ * [-exec | -execdir | -ok] utility [arg ... ] ; functions --
*
* True if the executed utility returns a zero value as exit status.
* The end of the primary expression is delimited by a semicolon. If
- * "{}" occurs anywhere, it gets replaced by the unqualified pathname.
- * The current directory for the execution of utility is the same as
- * the directory where the file lives.
+ * "{}" occurs anywhere, it gets replaced by the current pathname,
+ * or, in the case of -execdir, the current basename (filename
+ * without leading directory prefix). For -exec and -ok,
+ * the current directory for the execution of utility is the same as
+ * the current directory when the find utility was started, whereas
+ * for -execdir, it is the directory the file resides in.
+ *
+ * The primary -ok differs from -exec in that it requests affirmation
+ * of the user before executing the utility.
*/
int
-f_execdir(plan, entry)
+f_exec(plan, entry)
register PLAN *plan;
FTSENT *entry;
{
+ extern int dotfd;
register int cnt;
pid_t pid;
int status;
char *file;
/* XXX - if file/dir ends in '/' this will not work -- can it? */
- if ((file = strrchr(entry->fts_path, '/')))
- file++;
+ if ((plan->flags & F_EXECDIR) && \
+ (file = strrchr(entry->fts_path, '/')))
+ file++;
else
- file = entry->fts_path;
+ file = entry->fts_path;
for (cnt = 0; plan->e_argv[cnt]; ++cnt)
if (plan->e_len[cnt])
brace_subst(plan->e_orig[cnt], &plan->e_argv[cnt],
file, plan->e_len[cnt]);
- /* don't mix output of command with find output */
+ if ((plan->flags & F_NEEDOK) && !queryuser(plan->e_argv))
+ return 0;
+
+ /* make sure find output is interspersed correctly with subprocesses */
fflush(stdout);
fflush(stderr);
@@ -469,6 +469,11 @@ f_execdir(plan, entry)
err(1, "fork");
/* NOTREACHED */
case 0:
+ /* change dir back from where we started */
+ if (!(plan->flags & F_EXECDIR) && fchdir(dotfd)) {
+ warn("chdir");
+ _exit(1);
+ }
execvp(plan->e_argv[0], plan->e_argv);
warn("%s", plan->e_argv[0]);
_exit(1);
@@ -476,31 +481,35 @@ f_execdir(plan, entry)
pid = waitpid(pid, &status, 0);
return (pid != -1 && WIFEXITED(status) && !WEXITSTATUS(status));
}
-
+
/*
- * c_execdir --
+ * c_exec, c_execdir, c_ok --
* build three parallel arrays, one with pointers to the strings passed
* on the command line, one with (possibly duplicated) pointers to the
* argv array, and one with integer values that are lengths of the
* strings, but also flags meaning that the string has to be massaged.
*/
PLAN *
-c_execdir(argvp)
+c_exec(option, argvp)
+ OPTION *option;
char ***argvp;
{
PLAN *new; /* node returned */
register int cnt;
register char **argv, **ap, *p;
+ /* XXX - was in c_execdir, but seems unnecessary!?
ftsoptions &= ~FTS_NOSTAT;
+ */
isoutput = 1;
-
- new = palloc(N_EXECDIR, f_execdir);
+
+ /* XXX - this is a change from the previous coding */
+ new = palloc(option);
for (ap = argv = *argvp;; ++ap) {
if (!*ap)
errx(1,
- "-execdir: no terminating \";\"");
+ "%s: no terminating \";\"", option->name);
if (**ap == ';')
break;
}
@@ -526,7 +535,54 @@ c_execdir(argvp)
new->e_argv[cnt] = new->e_orig[cnt] = NULL;
*argvp = argv + 1;
- return (new);
+ return new;
+}
+
+int
+f_flags(plan, entry)
+ PLAN *plan;
+ FTSENT *entry;
+{
+ u_long flags;
+
+ flags = entry->fts_statp->st_flags &
+ (UF_NODUMP | UF_IMMUTABLE | UF_APPEND | UF_OPAQUE |
+ SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND);
+ if (plan->flags & F_ATLEAST)
+ /* note that plan->fl_flags always is a subset of
+ plan->fl_mask */
+ return (flags & plan->fl_mask) == plan->fl_flags;
+ else if (plan->flags & F_ANY)
+ return flags & plan->fl_mask;
+ else
+ return flags == plan->fl_flags;
+ /* NOTREACHED */
+}
+
+PLAN *
+c_flags(option, argvp)
+ OPTION *option;
+ char ***argvp;
+{
+ char *flags_str;
+ PLAN *new;
+ u_long flags, notflags;
+
+ flags_str = nextarg(option, argvp);
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(option);
+
+ if (*flags_str == '-') {
+ new->flags |= F_ATLEAST;
+ flags_str++;
+ }
+ if (strtofflags(&flags_str, &flags, &notflags) == 1)
+ errx(1, "%s: %s: illegal flags string", option->name, flags_str);
+
+ new->fl_flags = flags;
+ new->fl_mask = flags | notflags;
+ return new;
}
/*
@@ -536,12 +592,14 @@ c_execdir(argvp)
* basis.
*/
PLAN *
-c_follow()
+c_follow(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
ftsoptions &= ~FTS_PHYSICAL;
ftsoptions |= FTS_LOGICAL;
- return (palloc(N_FOLLOW, f_always_true));
+ return palloc(option);
}
/*
@@ -560,6 +618,9 @@ f_fstype(plan, entry)
static int val_type, val_flags;
char *p, save[2];
+ if ((plan->flags & F_MTMASK) == F_MTUNKNOWN)
+ return 0;
+
/* Only check when we cross mount point. */
if (first || curdev != entry->fts_statp->st_dev) {
curdev = entry->fts_statp->st_dev;
@@ -578,7 +639,6 @@ f_fstype(plan, entry)
p[0] = '.';
save[1] = p[1];
p[1] = '\0';
-
} else
p = NULL;
@@ -599,71 +659,66 @@ f_fstype(plan, entry)
val_flags = sb.f_flags;
val_type = sb.f_type;
}
- switch (plan->flags) {
+ switch (plan->flags & F_MTMASK) {
case F_MTFLAG:
- return (val_flags & plan->mt_data) != 0;
+ return val_flags & plan->mt_data;
case F_MTTYPE:
- return (val_type == plan->mt_data);
+ return val_type == plan->mt_data;
default:
abort();
}
}
#if !defined(__NetBSD__)
-int
-f_always_false(plan, entry)
- PLAN *plan;
- FTSENT *entry;
-{
- return (0);
-}
-
PLAN *
-c_fstype(arg)
- char *arg;
+c_fstype(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
+ char *fsname;
register PLAN *new;
struct vfsconf vfc;
-
+
+ fsname = nextarg(option, argvp);
ftsoptions &= ~FTS_NOSTAT;
- new = palloc(N_FSTYPE, f_fstype);
+ new = palloc(option);
/*
* Check first for a filesystem name.
*/
- if (getvfsbyname(arg, &vfc) == 0) {
- new->flags = F_MTTYPE;
+ if (getvfsbyname(fsname, &vfc) == 0) {
+ new->flags |= F_MTTYPE;
new->mt_data = vfc.vfc_typenum;
- return (new);
+ return new;
}
- switch (*arg) {
+ switch (*fsname) {
case 'l':
- if (!strcmp(arg, "local")) {
- new->flags = F_MTFLAG;
+ if (!strcmp(fsname, "local")) {
+ new->flags |= F_MTFLAG;
new->mt_data = MNT_LOCAL;
- return (new);
+ return new;
}
break;
case 'r':
- if (!strcmp(arg, "rdonly")) {
- new->flags = F_MTFLAG;
+ if (!strcmp(fsname, "rdonly")) {
+ new->flags |= F_MTFLAG;
new->mt_data = MNT_RDONLY;
- return (new);
+ return new;
}
break;
}
+
/*
* We need to make filesystem checks for filesystems
* that exists but aren't in the kernel work.
*/
- fprintf(stderr, "Warning: Unknown filesystem type %s\n", arg);
- free(new);
-
- return (palloc(N_FSTYPE, f_always_false));
+ fprintf(stderr, "Warning: Unknown filesystem type %s\n", fsname);
+ new->flags |= F_MTUNKNOWN;
+ return new;
}
-#endif
+#endif /* __NetBSD__ */
/*
* -group gname functions --
@@ -677,30 +732,33 @@ f_group(plan, entry)
PLAN *plan;
FTSENT *entry;
{
- return (entry->fts_statp->st_gid == plan->g_data);
+ return entry->fts_statp->st_gid == plan->g_data;
}
PLAN *
-c_group(gname)
- char *gname;
+c_group(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
+ char *gname;
PLAN *new;
struct group *g;
gid_t gid;
+ gname = nextarg(option, argvp);
ftsoptions &= ~FTS_NOSTAT;
g = getgrnam(gname);
if (g == NULL) {
gid = atoi(gname);
if (gid == 0 && gname[0] != '0')
- errx(1, "-group: %s: no such group", gname);
+ errx(1, "%s: %s: no such group", option->name, gname);
} else
gid = g->gr_gid;
- new = palloc(N_GROUP, f_group);
+ new = palloc(option);
new->g_data = gid;
- return (new);
+ return new;
}
/*
@@ -717,16 +775,19 @@ f_inum(plan, entry)
}
PLAN *
-c_inum(arg)
- char *arg;
+c_inum(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
+ char *inum_str;
PLAN *new;
+ inum_str = nextarg(option, argvp);
ftsoptions &= ~FTS_NOSTAT;
- new = palloc(N_INUM, f_inum);
- new->i_data = find_parsenum(new, "-inum", arg, NULL);
- return (new);
+ new = palloc(option);
+ new->i_data = find_parsenum(new, option->name, inum_str, NULL);
+ return new;
}
/*
@@ -743,16 +804,19 @@ f_links(plan, entry)
}
PLAN *
-c_links(arg)
- char *arg;
+c_links(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
+ char *nlinks;
PLAN *new;
+ nlinks = nextarg(option, argvp);
ftsoptions &= ~FTS_NOSTAT;
- new = palloc(N_LINKS, f_links);
- new->l_data = (nlink_t)find_parsenum(new, "-links", arg, NULL);
- return (new);
+ new = palloc(option);
+ new->l_data = (nlink_t)find_parsenum(new, option->name, nlinks, NULL);
+ return new;
}
/*
@@ -766,143 +830,21 @@ f_ls(plan, entry)
FTSENT *entry;
{
printlong(entry->fts_path, entry->fts_accpath, entry->fts_statp);
- return (1);
+ return 1;
}
PLAN *
-c_ls()
+c_ls(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
ftsoptions &= ~FTS_NOSTAT;
isoutput = 1;
- return (palloc(N_LS, f_ls));
+ return palloc(option);
}
/*
- * -maxdepth n functions --
- *
- * Does the same as -prune if the level of the current file is greater
- * than the specified maximum depth.
- *
- * Note that -maxdepth and -mindepth are handled specially in
- * find_execute() so their f_* functions here do nothing.
- */
-int
-f_maxdepth(plan, entry)
- PLAN *plan;
- FTSENT *entry;
-{
- return (1);
-}
-
-PLAN *
-c_maxdepth(arg)
- char *arg;
-{
- PLAN *new;
-
- if (*arg == '-')
- /* all other errors handled by find_parsenum() */
- errx(1, "-maxdepth: %s: value must be positive", arg);
-
- new = palloc(N_MAXDEPTH, f_maxdepth);
- maxdepth = find_parsenum(new, "-maxdepth", arg, NULL);
- return (new);
-}
-
-/*
- * -mindepth n functions --
- *
- * True if the current file is at or deeper than the specified minimum
- * depth.
- */
-int
-f_mindepth(plan, entry)
- PLAN *plan;
- FTSENT *entry;
-{
- return (1);
-}
-
-PLAN *
-c_mindepth(arg)
- char *arg;
-{
- PLAN *new;
-
- if (*arg == '-')
- /* all other errors handled by find_parsenum() */
- errx(1, "-maxdepth: %s: value must be positive", arg);
-
- new = palloc(N_MINDEPTH, f_mindepth);
- mindepth = find_parsenum(new, "-mindepth", arg, NULL);
- return (new);
-}
-
-/*
- * -mtime n functions --
- *
- * True if the difference between the file modification time and the
- * current time is n 24 hour periods.
- */
-int
-f_mtime(plan, entry)
- PLAN *plan;
- FTSENT *entry;
-{
- extern time_t now;
-
- COMPARE((now - entry->fts_statp->st_mtime + 86400 - 1) /
- 86400, plan->t_data);
-}
-
-PLAN *
-c_mtime(arg)
- char *arg;
-{
- PLAN *new;
-
- ftsoptions &= ~FTS_NOSTAT;
-
- new = palloc(N_MTIME, f_mtime);
- new->t_data = find_parsenum(new, "-mtime", arg, NULL);
- TIME_CORRECT(new, N_MTIME);
- return (new);
-}
-
-/*
- * -mmin n functions --
- *
- * True if the difference between the file modification time and the
- * current time is n min periods.
- */
-int
-f_mmin(plan, entry)
- PLAN *plan;
- FTSENT *entry;
-{
- extern time_t now;
-
- COMPARE((now - entry->fts_statp->st_mtime + 60 - 1) /
- 60, plan->t_data);
-}
-
-PLAN *
-c_mmin(arg)
- char *arg;
-{
- PLAN *new;
-
- ftsoptions &= ~FTS_NOSTAT;
-
- new = palloc(N_MMIN, f_mmin);
- new->t_data = find_parsenum(new, "-mmin", arg, NULL);
- TIME_CORRECT(new, N_MMIN);
- return (new);
-}
-
-
-/*
* -name functions --
*
* True if the basename of the filename being examined
@@ -913,145 +855,22 @@ f_name(plan, entry)
PLAN *plan;
FTSENT *entry;
{
- return (!fnmatch(plan->c_data, entry->fts_name, 0));
+ return !fnmatch(plan->c_data, entry->fts_name,
+ plan->flags & F_IGNCASE ? FNM_CASEFOLD : 0);
}
PLAN *
-c_name(pattern)
- char *pattern;
-{
- PLAN *new;
-
- new = palloc(N_NAME, f_name);
- new->c_data = pattern;
- return (new);
-}
-
-
-/*
- * -iname functions --
- *
- * Like -iname, but the match is case insensitive.
- */
-int
-f_iname(plan, entry)
- PLAN *plan;
- FTSENT *entry;
+c_name(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
- return (!fnmatch(plan->c_data, entry->fts_name, FNM_CASEFOLD));
-}
-
-PLAN *
-c_iname(pattern)
char *pattern;
-{
PLAN *new;
- new = palloc(N_INAME, f_iname);
+ pattern = nextarg(option, argvp);
+ new = palloc(option);
new->c_data = pattern;
- return (new);
-}
-
-
-/*
- * -regex functions --
- *
- * True if the whole path of the file matches pattern using
- * regular expression.
- */
-int
-f_regex(plan, entry)
- PLAN *plan;
- FTSENT *entry;
-{
- return (do_f_regex(plan, entry, 0));
-}
-
-PLAN *
-c_regex(pattern)
- char *pattern;
-{
- return (do_c_regex(pattern, 0));
-}
-
-/*
- * -iregex functions --
- *
- * Like -regex, but the match is case insensitive.
- */
-int
-f_iregex(plan, entry)
- PLAN *plan;
- FTSENT *entry;
-{
- return (do_f_regex(plan, entry, REG_ICASE));
-}
-
-PLAN *
-c_iregex(pattern)
- char *pattern;
-{
- return (do_c_regex(pattern, REG_ICASE));
-}
-
-static int
-do_f_regex(plan, entry, icase)
- PLAN *plan;
- FTSENT *entry;
- int icase;
-{
- char *str;
- size_t len;
- regex_t *pre;
- regmatch_t pmatch;
- int errcode;
- char errbuf[LINE_MAX];
- int matched;
-
- pre = plan->re_data;
- str = entry->fts_path;
- len = strlen(str);
- matched = 0;
-
- pmatch.rm_so = 0;
- pmatch.rm_eo = len;
-
- errcode = regexec(pre, str, 1, &pmatch, REG_STARTEND);
-
- if (errcode != 0 && errcode != REG_NOMATCH) {
- regerror(errcode, pre, errbuf, sizeof errbuf);
- errx(1, "%s: %s",
- icase == 0 ? "-regex" : "-iregex", errbuf);
- }
-
- if (errcode == 0 && pmatch.rm_so == 0 && pmatch.rm_eo == len)
- matched = 1;
-
- return (matched);
-}
-
-PLAN *
-do_c_regex(pattern, icase)
- char *pattern;
- int icase;
-{
- PLAN *new;
- regex_t *pre;
- int errcode;
- char errbuf[LINE_MAX];
-
- if ((pre = malloc(sizeof(regex_t))) == NULL)
- err(1, NULL);
-
- if ((errcode = regcomp(pre, pattern, regexp_flags | icase)) != 0) {
- regerror(errcode, pre, errbuf, sizeof errbuf);
- errx(1, "%s: %s: %s",
- icase == 0 ? "-regex" : "-iregex", pattern, errbuf);
- }
-
- new = icase == 0 ? palloc(N_REGEX, f_regex) : palloc(N_IREGEX, f_iregex);
- new->re_data = pre;
- return (new);
+ return new;
}
/*
@@ -1066,23 +885,43 @@ f_newer(plan, entry)
PLAN *plan;
FTSENT *entry;
{
- return (entry->fts_statp->st_mtime > plan->t_data);
+ if (plan->flags & F_TIME_C)
+ return entry->fts_statp->st_ctime > plan->t_data;
+ else if (plan->flags & F_TIME_A)
+ return entry->fts_statp->st_atime > plan->t_data;
+ else
+ return entry->fts_statp->st_mtime > plan->t_data;
}
PLAN *
-c_newer(filename)
- char *filename;
+c_newer(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
+ char *fn_or_tspec;
PLAN *new;
struct stat sb;
+ fn_or_tspec = nextarg(option, argvp);
ftsoptions &= ~FTS_NOSTAT;
- if (stat(filename, &sb))
- err(1, "%s", filename);
- new = palloc(N_NEWER, f_newer);
- new->t_data = sb.st_mtime;
- return (new);
+ new = palloc(option);
+ /* compare against what */
+ if (option->flags & F_TIME2_T) {
+ new->t_data = get_date(fn_or_tspec, (struct timeb *) 0);
+ if (new->t_data == (time_t) -1)
+ errx(1, "Can't parse date/time: %s", fn_or_tspec);
+ } else {
+ if (stat(fn_or_tspec, &sb))
+ err(1, "%s", fn_or_tspec);
+ if (option->flags & F_TIME2_C)
+ new->t_data = sb.st_ctime;
+ else if (option->flags & F_TIME2_A)
+ new->t_data = sb.st_atime;
+ else
+ new->t_data = sb.st_mtime;
+ }
+ return new;
}
/*
@@ -1096,15 +935,17 @@ f_nogroup(plan, entry)
PLAN *plan;
FTSENT *entry;
{
- return (group_from_gid(entry->fts_statp->st_gid, 1) ? 0 : 1);
+ return group_from_gid(entry->fts_statp->st_gid, 1) == NULL;
}
PLAN *
-c_nogroup()
+c_nogroup(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
ftsoptions &= ~FTS_NOSTAT;
- return (palloc(N_NOGROUP, f_nogroup));
+ return palloc(option);
}
/*
@@ -1118,15 +959,17 @@ f_nouser(plan, entry)
PLAN *plan;
FTSENT *entry;
{
- return (user_from_uid(entry->fts_statp->st_uid, 1) ? 0 : 1);
+ return user_from_uid(entry->fts_statp->st_uid, 1) == NULL;
}
PLAN *
-c_nouser()
+c_nouser(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
ftsoptions &= ~FTS_NOSTAT;
- return (palloc(N_NOUSER, f_nouser));
+ return palloc(option);
}
/*
@@ -1140,43 +983,11 @@ f_path(plan, entry)
PLAN *plan;
FTSENT *entry;
{
- return (!fnmatch(plan->c_data, entry->fts_path, 0));
-}
-
-PLAN *
-c_path(pattern)
- char *pattern;
-{
- PLAN *new;
-
- new = palloc(N_PATH, f_path);
- new->c_data = pattern;
- return (new);
-}
-
-/*
- * -ipath functions --
- *
- * Like -path, but the match is case insensitive.
- */
-int
-f_ipath(plan, entry)
- PLAN *plan;
- FTSENT *entry;
-{
- return (!fnmatch(plan->c_data, entry->fts_path, FNM_CASEFOLD));
+ return !fnmatch(plan->c_data, entry->fts_path,
+ plan->flags & F_IGNCASE ? FNM_CASEFOLD : 0);
}
-PLAN *
-c_ipath(pattern)
- char *pattern;
-{
- PLAN *new;
-
- new = palloc(N_IPATH, f_ipath);
- new->c_data = pattern;
- return (new);
-}
+/* c_path is the same as c_name */
/*
* -perm functions --
@@ -1194,90 +1005,40 @@ f_perm(plan, entry)
mode = entry->fts_statp->st_mode &
(S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO);
- if (plan->flags == F_ATLEAST)
- return ((plan->m_data | mode) == mode);
- else if (plan->flags == F_ANY )
- return (plan->m_data & mode);
+ if (plan->flags & F_ATLEAST)
+ return (plan->m_data | mode) == mode;
else
- return (mode == plan->m_data);
+ return mode == plan->m_data;
/* NOTREACHED */
}
PLAN *
-c_perm(perm)
- char *perm;
+c_perm(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
+ char *perm;
PLAN *new;
mode_t *set;
+ perm = nextarg(option, argvp);
ftsoptions &= ~FTS_NOSTAT;
- new = palloc(N_PERM, f_perm);
+ new = palloc(option);
if (*perm == '-') {
- new->flags = F_ATLEAST;
+ new->flags |= F_ATLEAST;
++perm;
} else if (*perm == '+') {
- new->flags = F_ANY;
+ new->flags |= F_ANY;
++perm;
}
if ((set = setmode(perm)) == NULL)
- errx(1, "-perm: %s: illegal mode string", perm);
+ errx(1, "%s: %s: illegal mode string", option->name, perm);
new->m_data = getmode(set, 0);
free(set);
- return (new);
-}
-
-/*
- * -flags functions --
- *
- * The flags argument is used to represent file flags bits.
- */
-int
-f_flags(plan, entry)
- PLAN *plan;
- FTSENT *entry;
-{
- u_long flags;
-
- flags = entry->fts_statp->st_flags &
- (UF_NODUMP | UF_IMMUTABLE | UF_APPEND | UF_OPAQUE |
- SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND);
- if (plan->flags == F_ATLEAST)
- /* note that plan->fl_flags always is a subset of
- plan->fl_mask */
- return (flags & plan->fl_mask) == plan->fl_flags;
- else
- return flags == plan->fl_flags;
- /* NOTREACHED */
-}
-
-PLAN *
-c_flags(flags_str)
- char *flags_str;
-{
- PLAN *new;
- u_long flags, notflags;
-
- ftsoptions &= ~FTS_NOSTAT;
-
- new = palloc(N_FLAGS, f_flags);
-
- if (*flags_str == '-') {
- new->flags = F_ATLEAST;
- flags_str++;
- }
- if (strtofflags(&flags_str, &flags, &notflags) == 1)
- errx(1, "-flags: %s: illegal flags string", flags_str);
-
- new->fl_flags = flags;
- new->fl_mask = flags | notflags;
-#if 0
- printf("flags = %08x, mask = %08x (%08x, %08x)\n",
- new->fl_flags, new->fl_mask, flags, notflags);
-#endif
return new;
}
@@ -1293,15 +1054,17 @@ f_print(plan, entry)
FTSENT *entry;
{
(void)puts(entry->fts_path);
- return (1);
+ return 1;
}
PLAN *
-c_print()
+c_print(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
isoutput = 1;
- return (palloc(N_PRINT, f_print));
+ return palloc(option);
}
/*
@@ -1317,16 +1080,10 @@ f_print0(plan, entry)
{
fputs(entry->fts_path, stdout);
fputc('\0', stdout);
- return (1);
+ return 1;
}
-PLAN *
-c_print0()
-{
- isoutput = 1;
-
- return (palloc(N_PRINT0, f_print0));
-}
+/* c_print0 is the same as c_print */
/*
* -prune functions --
@@ -1342,13 +1099,90 @@ f_prune(plan, entry)
if (fts_set(tree, entry, FTS_SKIP))
err(1, "%s", entry->fts_path);
- return (1);
+ return 1;
}
+/* c_prune == c_simple */
+
+/*
+ * -regex functions --
+ *
+ * True if the whole path of the file matches pattern using
+ * regular expression.
+ */
+int
+f_regex(plan, entry)
+ PLAN *plan;
+ FTSENT *entry;
+{
+ char *str;
+ size_t len;
+ regex_t *pre;
+ regmatch_t pmatch;
+ int errcode;
+ char errbuf[LINE_MAX];
+ int matched;
+
+ pre = plan->re_data;
+ str = entry->fts_path;
+ len = strlen(str);
+ matched = 0;
+
+ pmatch.rm_so = 0;
+ pmatch.rm_eo = len;
+
+ errcode = regexec(pre, str, 1, &pmatch, REG_STARTEND);
+
+ if (errcode != 0 && errcode != REG_NOMATCH) {
+ regerror(errcode, pre, errbuf, sizeof errbuf);
+ errx(1, "%s: %s",
+ plan->flags & F_IGNCASE ? "-iregex" : "-regex", errbuf);
+ }
+
+ if (errcode == 0 && pmatch.rm_so == 0 && pmatch.rm_eo == len)
+ matched = 1;
+
+ return matched;
+}
+
+PLAN *
+c_regex(option, argvp)
+ OPTION *option;
+ char ***argvp;
+{
+ PLAN *new;
+ char *pattern;
+ regex_t *pre;
+ int errcode;
+ char errbuf[LINE_MAX];
+
+ if ((pre = malloc(sizeof(regex_t))) == NULL)
+ err(1, NULL);
+
+ pattern = nextarg(option, argvp);
+
+ if ((errcode = regcomp(pre, pattern,
+ regexp_flags | (option->flags & F_IGNCASE ? REG_ICASE : 0))) != 0) {
+ regerror(errcode, pre, errbuf, sizeof errbuf);
+ errx(1, "%s: %s: %s",
+ option->flags & F_IGNCASE ? "-iregex" : "-regex",
+ pattern, errbuf);
+ }
+
+ new = palloc(option);
+ new->re_data = pre;
+
+ return new;
+}
+
+/* c_simple covers c_prune, c_openparen, c_closeparen, c_not, c_or */
+
PLAN *
-c_prune()
+c_simple(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
- return (palloc(N_PRUNE, f_prune));
+ return palloc(option);
}
/*
@@ -1374,20 +1208,23 @@ f_size(plan, entry)
}
PLAN *
-c_size(arg)
- char *arg;
+c_size(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
+ char *size_str;
PLAN *new;
char endch;
+ size_str = nextarg(option, argvp);
ftsoptions &= ~FTS_NOSTAT;
- new = palloc(N_SIZE, f_size);
+ new = palloc(option);
endch = 'c';
- new->o_data = find_parsenum(new, "-size", arg, &endch);
+ new->o_data = find_parsenum(new, option->name, size_str, &endch);
if (endch == 'c')
divsize = 0;
- return (new);
+ return new;
}
/*
@@ -1402,16 +1239,19 @@ f_type(plan, entry)
PLAN *plan;
FTSENT *entry;
{
- return ((entry->fts_statp->st_mode & S_IFMT) == plan->m_data);
+ return (entry->fts_statp->st_mode & S_IFMT) == plan->m_data;
}
PLAN *
-c_type(typestring)
- char *typestring;
+c_type(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
+ char *typestring;
PLAN *new;
mode_t mask;
+ typestring = nextarg(option, argvp);
ftsoptions &= ~FTS_NOSTAT;
switch (typestring[0]) {
@@ -1443,72 +1283,12 @@ c_type(typestring)
break;
#endif /* FTS_WHITEOUT */
default:
- errx(1, "-type: %s: unknown type", typestring);
+ errx(1, "%s: %s: unknown type", option->name, typestring);
}
- new = palloc(N_TYPE, f_type);
+ new = palloc(option);
new->m_data = mask;
- return (new);
-}
-
-/*
- * -delete functions --
- *
- * True always. Makes it's best shot and continues on regardless.
- */
-int
-f_delete(plan, entry)
- PLAN *plan;
- FTSENT *entry;
-{
- /* ignore these from fts */
- if (strcmp(entry->fts_accpath, ".") == 0 ||
- strcmp(entry->fts_accpath, "..") == 0)
- return (1);
-
- /* sanity check */
- if (isdepth == 0 || /* depth off */
- (ftsoptions & FTS_NOSTAT) || /* not stat()ing */
- !(ftsoptions & FTS_PHYSICAL) || /* physical off */
- (ftsoptions & FTS_LOGICAL)) /* or finally, logical on */
- errx(1, "-delete: insecure options got turned on");
-
- /* Potentially unsafe - do not accept relative paths whatsoever */
- if (strchr(entry->fts_accpath, '/') != NULL)
- errx(1, "-delete: %s: relative path potentially not safe",
- entry->fts_accpath);
-
- /* Turn off user immutable bits if running as root */
- if ((entry->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
- !(entry->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
- geteuid() == 0)
- chflags(entry->fts_accpath,
- entry->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
-
- /* rmdir directories, unlink everything else */
- if (S_ISDIR(entry->fts_statp->st_mode)) {
- if (rmdir(entry->fts_accpath) < 0 && errno != ENOTEMPTY)
- warn("-delete: rmdir(%s)", entry->fts_path);
- } else {
- if (unlink(entry->fts_accpath) < 0)
- warn("-delete: unlink(%s)", entry->fts_path);
- }
-
- /* "succeed" */
- return (1);
-}
-
-PLAN *
-c_delete()
-{
-
- ftsoptions &= ~FTS_NOSTAT; /* no optimise */
- ftsoptions |= FTS_PHYSICAL; /* disable -follow */
- ftsoptions &= ~FTS_LOGICAL; /* disable -follow */
- isoutput = 1; /* possible output */
- isdepth = 1; /* -depth implied */
-
- return (palloc(N_DELETE, f_delete));
+ return new;
}
/*
@@ -1523,30 +1303,33 @@ f_user(plan, entry)
PLAN *plan;
FTSENT *entry;
{
- return (entry->fts_statp->st_uid == plan->u_data);
+ return entry->fts_statp->st_uid == plan->u_data;
}
PLAN *
-c_user(username)
- char *username;
+c_user(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
+ char *username;
PLAN *new;
struct passwd *p;
uid_t uid;
+ username = nextarg(option, argvp);
ftsoptions &= ~FTS_NOSTAT;
p = getpwnam(username);
if (p == NULL) {
uid = atoi(username);
if (uid == 0 && username[0] != '0')
- errx(1, "-user: %s: no such user", username);
+ errx(1, "%s: %s: no such user", option->name, username);
} else
uid = p->pw_uid;
- new = palloc(N_USER, f_user);
+ new = palloc(option);
new->u_data = uid;
- return (new);
+ return new;
}
/*
@@ -1556,11 +1339,13 @@ c_user(username)
* different device ID (st_dev, see stat() S5.6.2 [POSIX.1])
*/
PLAN *
-c_xdev()
+c_xdev(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
ftsoptions |= FTS_XDEV;
- return (palloc(N_XDEV, f_always_true));
+ return palloc(option);
}
/*
@@ -1574,29 +1359,48 @@ f_expr(plan, entry)
FTSENT *entry;
{
register PLAN *p;
- register int state;
+ register int state = 0;
- state = 0;
for (p = plan->p_data[0];
- p && (state = (p->eval)(p, entry)); p = p->next);
- return (state);
+ p && (state = (p->execute)(p, entry)); p = p->next);
+ return state;
}
/*
- * N_OPENPAREN and N_CLOSEPAREN nodes are temporary place markers. They are
+ * f_openparen and f_closeparen nodes are temporary place markers. They are
* eliminated during phase 2 of find_formplan() --- the '(' node is converted
- * to a N_EXPR node containing the expression and the ')' node is discarded.
+ * to a f_expr node containing the expression and the ')' node is discarded.
+ * The functions themselves are only used as constants.
*/
-PLAN *
-c_openparen()
+
+int
+f_openparen(plan, entry)
+ PLAN *plan;
+ FTSENT *entry;
+{
+ abort();
+}
+
+int
+f_closeparen(plan, entry)
+ PLAN *plan;
+ FTSENT *entry;
{
- return (palloc(N_OPENPAREN, (int (*)())-1));
+ abort();
}
+/* c_openparen == c_simple */
+/* c_closeparen == c_simple */
+
+/*
+ * AND operator. Since AND is implicit, no node is allocated.
+ */
PLAN *
-c_closeparen()
+c_and(option, argvp)
+ OPTION *option;
+ char ***argvp;
{
- return (palloc(N_CLOSEPAREN, (int (*)())-1));
+ return NULL;
}
/*
@@ -1610,19 +1414,14 @@ f_not(plan, entry)
FTSENT *entry;
{
register PLAN *p;
- register int state;
+ register int state = 0;
- state = 0;
for (p = plan->p_data[0];
- p && (state = (p->eval)(p, entry)); p = p->next);
- return (!state);
+ p && (state = (p->execute)(p, entry)); p = p->next);
+ return !state;
}
-PLAN *
-c_not()
-{
- return (palloc(N_NOT, f_not));
-}
+/* c_not == c_simple */
/*
* expression -o expression functions --
@@ -1636,38 +1435,17 @@ f_or(plan, entry)
FTSENT *entry;
{
register PLAN *p;
- register int state;
+ register int state = 0;
- state = 0;
for (p = plan->p_data[0];
- p && (state = (p->eval)(p, entry)); p = p->next);
+ p && (state = (p->execute)(p, entry)); p = p->next);
if (state)
- return (1);
+ return 1;
for (p = plan->p_data[1];
- p && (state = (p->eval)(p, entry)); p = p->next);
- return (state);
+ p && (state = (p->execute)(p, entry)); p = p->next);
+ return state;
}
-PLAN *
-c_or()
-{
- return (palloc(N_OR, f_or));
-}
-
-static PLAN *
-palloc(t, f)
- enum ntype t;
- int (*f) __P((PLAN *, FTSENT *));
-{
- PLAN *new;
-
- if ((new = malloc(sizeof(PLAN))) == NULL)
- err(1, NULL);
- new->type = t;
- new->eval = f;
- new->flags = 0;
- new->next = NULL;
- return (new);
-}
+/* c_or == c_simple */
diff --git a/usr.bin/find/ls.c b/usr.bin/find/ls.c
index cd138f5..d033973 100644
--- a/usr.bin/find/ls.c
+++ b/usr.bin/find/ls.c
@@ -65,7 +65,7 @@ printlong(name, accpath, sb)
{
char modep[15], *user_from_uid(), *group_from_gid();
- (void)printf("%6lu %4qd ", (u_long)sb->st_ino, sb->st_blocks);
+ (void)printf("%6lu %4qd ", (u_long) sb->st_ino, sb->st_blocks);
(void)strmode(sb->st_mode, modep);
(void)printf("%s %3u %-*s %-*s ", modep, sb->st_nlink, UT_NAMESIZE,
user_from_uid(sb->st_uid, 0), UT_NAMESIZE,
diff --git a/usr.bin/find/operator.c b/usr.bin/find/operator.c
index 0cb67cc..d7ac745 100644
--- a/usr.bin/find/operator.c
+++ b/usr.bin/find/operator.c
@@ -72,7 +72,7 @@ yanknode(planp)
* yankexpr --
* Removes one expression from the plan. This is used mainly by
* paren_squish. In comments below, an expression is either a
- * simple node or a N_EXPR node containing a list of simple nodes.
+ * simple node or a f_expr node containing a list of simple nodes.
*/
static PLAN *
yankexpr(planp)
@@ -82,7 +82,6 @@ yankexpr(planp)
PLAN *node; /* pointer to returned node or expression */
PLAN *tail; /* pointer to tail of subplan */
PLAN *subplan; /* pointer to head of ( ) expression */
- int f_expr();
/* first pull the top node from the plan */
if ((node = yanknode(planp)) == NULL)
@@ -94,23 +93,22 @@ yankexpr(planp)
* just return it and unwind our recursion; all other nodes are
* complete expressions, so just return them.
*/
- if (node->type == N_OPENPAREN)
+ if (node->execute == f_openparen)
for (tail = subplan = NULL;;) {
if ((next = yankexpr(planp)) == NULL)
err(1, "(: missing closing ')'");
/*
* If we find a closing ')' we store the collected
* subplan in our '(' node and convert the node to
- * a N_EXPR. The ')' we found is ignored. Otherwise,
+ * a f_expr. The ')' we found is ignored. Otherwise,
* we just continue to add whatever we get to our
* subplan.
*/
- if (next->type == N_CLOSEPAREN) {
+ if (next->execute == f_closeparen) {
if (subplan == NULL)
errx(1, "(): empty inner expression");
node->p_data[0] = subplan;
- node->type = N_EXPR;
- node->eval = f_expr;
+ node->execute = f_expr;
break;
} else {
if (subplan == NULL)
@@ -141,14 +139,14 @@ paren_squish(plan)
/*
* the basic idea is to have yankexpr do all our work and just
- * collect it's results together.
+ * collect its results together.
*/
while ((expr = yankexpr(&plan)) != NULL) {
/*
* if we find an unclaimed ')' it means there is a missing
* '(' someplace.
*/
- if (expr->type == N_CLOSEPAREN)
+ if (expr->execute == f_closeparen)
errx(1, "): no beginning '('");
/* add the expression to our result plan */
@@ -172,18 +170,18 @@ not_squish(plan)
PLAN *plan; /* plan to process */
{
register PLAN *next; /* next node being processed */
- register PLAN *node; /* temporary node used in N_NOT processing */
+ register PLAN *node; /* temporary node used in f_not processing */
register PLAN *tail; /* pointer to tail of result plan */
PLAN *result; /* pointer to head of result plan */
- tail = result = next = NULL;
+ tail = result = NULL;
- while ((next = yanknode(&plan)) != NULL) {
+ while (next = yanknode(&plan)) {
/*
* if we encounter a ( expression ) then look for nots in
* the expr subplan.
*/
- if (next->type == N_EXPR)
+ if (next->execute == f_expr)
next->p_data[0] = not_squish(next->p_data[0]);
/*
@@ -191,23 +189,23 @@ not_squish(plan)
* it in the not's subplan. As an optimization we compress
* several not's to zero or one not.
*/
- if (next->type == N_NOT) {
+ if (next->execute == f_not) {
int notlevel = 1;
node = yanknode(&plan);
- while (node != NULL && node->type == N_NOT) {
+ while (node != NULL && node->execute == f_not) {
++notlevel;
node = yanknode(&plan);
}
if (node == NULL)
errx(1, "!: no following expression");
- if (node->type == N_OR)
+ if (node->execute == f_or)
errx(1, "!: nothing between ! and -o");
/*
* If we encounter ! ( expr ) then look for nots in
* the expr subplan.
*/
- if (node->type == N_EXPR)
+ if (node->execute == f_expr)
node->p_data[0] = not_squish(node->p_data[0]);
if (notlevel % 2 != 1)
next = node;
@@ -246,11 +244,11 @@ or_squish(plan)
* if we encounter a ( expression ) then look for or's in
* the expr subplan.
*/
- if (next->type == N_EXPR)
+ if (next->execute == f_expr)
next->p_data[0] = or_squish(next->p_data[0]);
/* if we encounter a not then look for or's in the subplan */
- if (next->type == N_NOT)
+ if (next->execute == f_not)
next->p_data[0] = or_squish(next->p_data[0]);
/*
@@ -258,7 +256,7 @@ or_squish(plan)
* or's first subplan and then recursively collect the
* remaining stuff into the second subplan and return the or.
*/
- if (next->type == N_OR) {
+ if (next->execute == f_or) {
if (result == NULL)
errx(1, "-o: no expression before -o");
next->p_data[0] = result;
diff --git a/usr.bin/find/option.c b/usr.bin/find/option.c
index b5911f2..0a37320 100644
--- a/usr.bin/find/option.c
+++ b/usr.bin/find/option.c
@@ -54,62 +54,75 @@ static const char rcsid[] =
#include "find.h"
-static OPTION *option __P((char *));
-
/* NB: the following table must be sorted lexically. */
static OPTION const options[] = {
- { "!", N_NOT, c_not, O_ZERO },
- { "(", N_OPENPAREN, c_openparen, O_ZERO },
- { ")", N_CLOSEPAREN, c_closeparen, O_ZERO },
- { "-a", N_AND, NULL, O_NONE },
- { "-amin", N_AMIN, c_amin, O_ARGV },
- { "-and", N_AND, NULL, O_NONE },
- { "-atime", N_ATIME, c_atime, O_ARGV },
- { "-cmin", N_CMIN, c_cmin, O_ARGV },
- { "-ctime", N_CTIME, c_ctime, O_ARGV },
- { "-delete", N_DELETE, c_delete, O_ZERO },
- { "-depth", N_DEPTH, c_depth, O_ZERO },
- { "-empty", N_EMPTY, c_empty, O_ZERO },
- { "-exec", N_EXEC, c_exec, O_ARGVP },
- { "-execdir", N_EXECDIR, c_execdir, O_ARGVP },
- { "-flags", N_FLAGS, c_flags, O_ARGV },
- { "-follow", N_FOLLOW, c_follow, O_ZERO },
-
+ { "!", c_simple, f_not, 0 },
+ { "(", c_simple, f_openparen, 0 },
+ { ")", c_simple, f_closeparen, 0 },
+ { "-a", c_and, NULL, 0 },
+ { "-amin", c_Xmin, f_Xmin, F_TIME_A },
+ { "-and", c_and, NULL, 0 },
+ { "-anewer", c_newer, f_newer, F_TIME_A },
+ { "-atime", c_Xtime, f_Xtime, F_TIME_A },
+ { "-cmin", c_Xmin, f_Xmin, F_TIME_C },
+ { "-cnewer", c_newer, f_newer, F_TIME_C },
+ { "-ctime", c_Xtime, f_Xtime, F_TIME_C },
+ { "-delete", c_delete, f_delete, 0 },
+ { "-depth", c_depth, f_always_true, 0 },
+ { "-empty", c_empty, f_empty, 0 },
+ { "-exec", c_exec, f_exec, 0 },
+ { "-execdir", c_exec, f_exec, F_EXECDIR },
+ { "-flags", c_flags, f_flags, 0 },
+ { "-follow", c_follow, f_always_true, 0 },
/*
* NetBSD doesn't provide a getvfsbyname(), so this option
* is not available if using a NetBSD kernel.
*/
#if !defined(__NetBSD__)
- { "-fstype", N_FSTYPE, c_fstype, O_ARGV },
+ { "-fstype", c_fstype, f_fstype, 0 },
#endif
- { "-group", N_GROUP, c_group, O_ARGV },
- { "-iname", N_INAME, c_iname, O_ARGV },
- { "-inum", N_INUM, c_inum, O_ARGV },
- { "-ipath", N_IPATH, c_ipath, O_ARGV },
- { "-iregex", N_IREGEX, c_iregex, O_ARGV },
- { "-links", N_LINKS, c_links, O_ARGV },
- { "-ls", N_LS, c_ls, O_ZERO },
- { "-maxdepth", N_MAXDEPTH, c_maxdepth, O_ARGV },
- { "-mindepth", N_MINDEPTH, c_mindepth, O_ARGV },
- { "-mmin", N_MMIN, c_mmin, O_ARGV },
- { "-mtime", N_MTIME, c_mtime, O_ARGV },
- { "-name", N_NAME, c_name, O_ARGV },
- { "-newer", N_NEWER, c_newer, O_ARGV },
- { "-nogroup", N_NOGROUP, c_nogroup, O_ZERO },
- { "-nouser", N_NOUSER, c_nouser, O_ZERO },
- { "-o", N_OR, c_or, O_ZERO },
- { "-ok", N_OK, c_exec, O_ARGVP },
- { "-or", N_OR, c_or, O_ZERO },
- { "-path", N_PATH, c_path, O_ARGV },
- { "-perm", N_PERM, c_perm, O_ARGV },
- { "-print", N_PRINT, c_print, O_ZERO },
- { "-print0", N_PRINT0, c_print0, O_ZERO },
- { "-prune", N_PRUNE, c_prune, O_ZERO },
- { "-regex", N_REGEX, c_regex, O_ARGV },
- { "-size", N_SIZE, c_size, O_ARGV },
- { "-type", N_TYPE, c_type, O_ARGV },
- { "-user", N_USER, c_user, O_ARGV },
- { "-xdev", N_XDEV, c_xdev, O_ZERO },
+ { "-group", c_group, f_group, 0 },
+ { "-iname", c_name, f_name, F_IGNCASE },
+ { "-inum", c_inum, f_inum, 0 },
+ { "-ipath", c_name, f_path, F_IGNCASE },
+ { "-iregex", c_regex, f_regex, F_IGNCASE },
+ { "-links", c_links, f_links, 0 },
+ { "-ls", c_ls, f_ls, 0 },
+ { "-maxdepth", c_mXXdepth, f_always_true, F_MAXDEPTH },
+ { "-mindepth", c_mXXdepth, f_always_true, 0 },
+ { "-mmin", c_Xmin, f_Xmin, 0 },
+ { "-mnewer", c_newer, f_newer, 0 },
+ { "-mtime", c_Xtime, f_Xtime, 0 },
+ { "-name", c_name, f_name, 0 },
+ { "-newer", c_newer, f_newer, 0 },
+ { "-neweraa", c_newer, f_newer, F_TIME_A | F_TIME2_A },
+ { "-newerac", c_newer, f_newer, F_TIME_A | F_TIME2_C },
+ { "-neweram", c_newer, f_newer, F_TIME_A },
+ { "-newerat", c_newer, f_newer, F_TIME_A | F_TIME2_T },
+ { "-newerca", c_newer, f_newer, F_TIME_C | F_TIME2_A },
+ { "-newercc", c_newer, f_newer, F_TIME_C | F_TIME2_C },
+ { "-newercm", c_newer, f_newer, F_TIME_C },
+ { "-newerct", c_newer, f_newer, F_TIME_C | F_TIME2_T },
+ { "-newerma", c_newer, f_newer, F_TIME2_A },
+ { "-newermc", c_newer, f_newer, F_TIME2_C },
+ { "-newermm", c_newer, f_newer, 0 },
+ { "-newermt", c_newer, f_newer, F_TIME2_T },
+ { "-nogroup", c_nogroup, f_nogroup, 0 },
+ { "-nouser", c_nouser, f_nouser, 0 },
+ { "-o", c_simple, f_or, 0 },
+ { "-ok", c_exec, f_exec, F_NEEDOK },
+ { "-okdir", c_exec, f_exec, F_NEEDOK | F_EXECDIR },
+ { "-or", c_simple, f_or, 0 },
+ { "-path", c_name, f_path, 0 },
+ { "-perm", c_perm, f_perm, 0 },
+ { "-print", c_print, f_print, 0 },
+ { "-print0", c_print, f_print0, 0 },
+ { "-prune", c_simple, f_prune, 0 },
+ { "-regex", c_regex, f_regex, 0 },
+ { "-size", c_size, f_size, 0 },
+ { "-type", c_type, f_type, 0 },
+ { "-user", c_user, f_user, 0 },
+ { "-xdev", c_xdev, f_always_true, 0 },
};
/*
@@ -133,30 +146,13 @@ find_create(argvp)
if ((p = option(*argv)) == NULL)
errx(1, "%s: unknown option", *argv);
++argv;
- if (p->flags & (O_ARGV|O_ARGVP) && !*argv)
- errx(1, "%s: requires additional arguments", *--argv);
- switch(p->flags) {
- case O_NONE:
- new = NULL;
- break;
- case O_ZERO:
- new = (p->create)();
- break;
- case O_ARGV:
- new = (p->create)(*argv++);
- break;
- case O_ARGVP:
- new = (p->create)(&argv, p->token == N_OK);
- break;
- default:
- abort();
- }
+ new = (p->create)(p, &argv);
*argvp = argv;
return (new);
}
-static OPTION *
+OPTION *
option(name)
char *name;
{
OpenPOWER on IntegriCloud