tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Possible enhancement to find(1)



On Sat, 11 Jun 2016, Paul Goyette wrote:

On Sat, 11 Jun 2016, Robert Elz wrote:
...
If you were also to add

{ "-newerat", N_ASINCE, c_asince, 1 }, /* gnu find compat */
	{ "-newerct", N_CSINCE,	c_csince,	1 },
	{ "-newermt", N_SINCE,	c_since,	1 },    /* ung */

in the appropriate place, you'd have something that was command line
compatible with gnu findutils, so scripts written for that find, which
only use facilities actually implemented here, would work.

Would that really be such an evil thing?

For me, yes.  I will not implement the ugly gnu stuff, neither in its
entirety nor partially.

Well, I've been convinced by several off-list exchanges that it's really
not so bad to implement the gnu stuff after all.

We only have to implement gnu-equivalents for the functionality that we
already have - so we don't have to implement comparisons of differing
attributes (ie, a found file's atime vs the reference file's mtime).
The man-page for findutils clearly states that not all combinations need
to be provided.

I've restructured the existing code a bit, so that the parsing code
provides each option's argument parser with the actual option name;
this allows us to use the same argument parsing routines for the "alias"
options as for the "real" options.

New diffs are attached.  These include lists of the findutils -newerXY
options which remain unimplemented.

Comments are welcomed - even though I might at first reject them, I do
eventually consider them.   :)



+------------------+--------------------------+------------------------+
| Paul Goyette     | PGP Key fingerprint:     | E-mail addresses:      |
| (Retired)        | FA29 0E3B 35AF E8AE 6651 | paul at whooppee.com   |
| Kernel Developer | 0786 F758 55DE 53BA 7731 | pgoyette at netbsd.org |
+------------------+--------------------------+------------------------+
Index: extern.h
===================================================================
RCS file: /cvsroot/src/usr.bin/find/extern.h,v
retrieving revision 1.28
diff -u -p -r1.28 extern.h
--- extern.h	19 Jul 2007 07:49:30 -0000	1.28
+++ extern.h	12 Jun 2016 00:30:16 -0000
@@ -47,53 +47,56 @@ void	 printlong(char *, char *, struct s
 int	 queryuser(char **);
 void	 show_path(int);
 
-PLAN	*c_amin(char ***, int);
-PLAN	*c_anewer(char ***, int);
-PLAN	*c_atime(char ***, int);
-PLAN	*c_cmin(char ***, int);
-PLAN	*c_cnewer(char ***, int);
-PLAN	*c_ctime(char ***, int);
-PLAN	*c_delete(char ***, int);
-PLAN	*c_depth(char ***, int);
-PLAN	*c_empty(char ***, int);
-PLAN	*c_exec(char ***, int);
-PLAN	*c_execdir(char ***, int);
-PLAN	*c_exit(char ***, int);
-PLAN	*c_false(char ***, int);
-PLAN	*c_flags(char ***, int);
-PLAN	*c_follow(char ***, int);
-PLAN	*c_fprint(char ***, int);
-PLAN	*c_fstype(char ***, int);
-PLAN	*c_group(char ***, int);
-PLAN	*c_iname(char ***, int);
-PLAN	*c_inum(char ***, int);
-PLAN	*c_iregex(char ***, int);
-PLAN	*c_links(char ***, int);
-PLAN	*c_ls(char ***, int);
-PLAN	*c_maxdepth(char ***, int);
-PLAN	*c_mindepth(char ***, int);
-PLAN	*c_mmin(char ***, int);
-PLAN	*c_mtime(char ***, int);
-PLAN	*c_name(char ***, int);
-PLAN	*c_newer(char ***, int);
-PLAN	*c_nogroup(char ***, int);
-PLAN	*c_nouser(char ***, int);
-PLAN	*c_path(char ***, int);
-PLAN	*c_perm(char ***, int);
-PLAN	*c_print(char ***, int);
-PLAN	*c_print0(char ***, int);
-PLAN	*c_printx(char ***, int);
-PLAN	*c_prune(char ***, int);
-PLAN	*c_regex(char ***, int);
-PLAN	*c_size(char ***, int);
-PLAN	*c_type(char ***, int);
-PLAN	*c_user(char ***, int);
-PLAN	*c_xdev(char ***, int);
-PLAN	*c_openparen(char ***, int);
-PLAN	*c_closeparen(char ***, int);
-PLAN	*c_not(char ***, int);
-PLAN	*c_or(char ***, int);
-PLAN	*c_null(char ***, int);
+PLAN	*c_amin(char ***, int, char *);
+PLAN	*c_anewer(char ***, int, char *);
+PLAN	*c_asince(char ***, int, char *);
+PLAN	*c_atime(char ***, int, char *);
+PLAN	*c_cmin(char ***, int, char *);
+PLAN	*c_cnewer(char ***, int, char *);
+PLAN	*c_csince(char ***, int, char *);
+PLAN	*c_ctime(char ***, int, char *);
+PLAN	*c_delete(char ***, int, char *);
+PLAN	*c_depth(char ***, int, char *);
+PLAN	*c_empty(char ***, int, char *);
+PLAN	*c_exec(char ***, int, char *);
+PLAN	*c_execdir(char ***, int, char *);
+PLAN	*c_exit(char ***, int, char *);
+PLAN	*c_false(char ***, int, char *);
+PLAN	*c_flags(char ***, int, char *);
+PLAN	*c_follow(char ***, int, char *);
+PLAN	*c_fprint(char ***, int, char *);
+PLAN	*c_fstype(char ***, int, char *);
+PLAN	*c_group(char ***, int, char *);
+PLAN	*c_iname(char ***, int, char *);
+PLAN	*c_inum(char ***, int, char *);
+PLAN	*c_iregex(char ***, int, char *);
+PLAN	*c_links(char ***, int, char *);
+PLAN	*c_ls(char ***, int, char *);
+PLAN	*c_maxdepth(char ***, int, char *);
+PLAN	*c_mindepth(char ***, int, char *);
+PLAN	*c_mmin(char ***, int, char *);
+PLAN	*c_mtime(char ***, int, char *);
+PLAN	*c_name(char ***, int, char *);
+PLAN	*c_newer(char ***, int, char *);
+PLAN	*c_nogroup(char ***, int, char *);
+PLAN	*c_nouser(char ***, int, char *);
+PLAN	*c_path(char ***, int, char *);
+PLAN	*c_perm(char ***, int, char *);
+PLAN	*c_print(char ***, int, char *);
+PLAN	*c_print0(char ***, int, char *);
+PLAN	*c_printx(char ***, int, char *);
+PLAN	*c_prune(char ***, int, char *);
+PLAN	*c_regex(char ***, int, char *);
+PLAN	*c_since(char ***, int, char *);
+PLAN	*c_size(char ***, int, char *);
+PLAN	*c_type(char ***, int, char *);
+PLAN	*c_user(char ***, int, char *);
+PLAN	*c_xdev(char ***, int, char *);
+PLAN	*c_openparen(char ***, int, char *);
+PLAN	*c_closeparen(char ***, int, char *);
+PLAN	*c_not(char ***, int, char *);
+PLAN	*c_or(char ***, int, char *);
+PLAN	*c_null(char ***, int, char *);
 
 extern int ftsoptions, isdeprecated, isdepth, isoutput, issort, isxargs,
 	regcomp_flags;
Index: find.1
===================================================================
RCS file: /cvsroot/src/usr.bin/find/find.1,v
retrieving revision 1.81
diff -u -p -r1.81 find.1
--- find.1	17 May 2014 11:31:40 -0000	1.81
+++ find.1	12 Jun 2016 00:30:16 -0000
@@ -32,7 +32,7 @@
 .\"
 .\"	from: @(#)find.1	8.7 (Berkeley) 5/9/95
 .\"
-.Dd May 17, 2014
+.Dd June 10, 2016
 .Dt FIND 1
 .Os
 .Sh NAME
@@ -171,6 +171,12 @@ a preceding minus sign means
 and neither means
 .Dq exactly Ar n .
 .Pp
+For primaries which take a
+.Ar timestamp
+argument, the argument must be valid input to
+.Xr parsedate 3 .
+If the argument contains multiple words, enclose the argument in quotes.
+.Pp
 .Bl -tag -width Ds -compact
 .It Ic -amin Ar n
 True if the difference between the file last access time and the time
@@ -183,6 +189,10 @@ minutes.
 True if the current file has a more recent last access time than
 .Ar file .
 .Pp
+.It Ic -asince Ar "timestamp"
+True if the file last access time is greater than the specified
+.Ar timestamp .
+.Pp
 .It Ic -atime Ar n
 True if the difference between the file last access time and the time
 .Nm
@@ -202,6 +212,10 @@ minutes.
 True if the current file has a more recent last change time than
 .Ar file .
 .Pp
+.It Ic -csince Ar "timestamp"
+True if the file last status change time is greater than the specified
+.Ar timestamp .
+.Pp
 .It Ic -ctime Ar n
 True if the difference between the time of last change of file status
 information and the time
@@ -525,6 +539,21 @@ backslash
 True if the current file has a more recent last modification time than
 .Ar file .
 .Pp
+.It Ic -newerXY Ar reference
+For compatability with Gnu findutils.
+.Bl -column -offset indent ".Sy findutils" ".Sy equivalent"
+.It Sy findutils Ta Sy find
+.It Sy option Ta Sy equivalent
+.It -neweraa Ta -anewer
+.It -newerat Ta -asince
+.It -newercc Ta -cnewer
+.It -newerct Ta -csince
+.It -newermm Ta -newer
+.It -newermt Ta -since
+.El
+.Pp
+Other option variants from findutils are not implemented.
+.Pp
 .It Ic -nouser
 True if the file belongs to an unknown user.
 .Pp
@@ -637,6 +666,10 @@ basic regular expression
 This is a match on the whole path, not a search for the regular expression
 within the path.
 .Pp
+.It Ic -since Ar "timestamp"
+True if the file last modification time is more recent than
+.Ar timestamp .
+.Pp
 .It Ic -size Ar n Ns Op Cm c
 True if the file's size, rounded up, in 512-byte blocks is
 .Ar n .
@@ -809,8 +842,10 @@ standard.
 The options and the
 .Ic -amin ,
 .Ic -anewer ,
+.Ic -asince ,
 .Ic -cmin ,
 .Ic -cnewer ,
+.Ic -csince ,
 .Ic -delete ,
 .Ic -empty ,
 .Ic -execdir ,
@@ -828,8 +863,9 @@ The options and the
 .Ic -print0 ,
 .Ic -printx ,
 .Ic -regex ,
+.Ic -rm ,
 and
-.Ic -rm
+.Ic -since
 primaries are extensions to
 .St -p1003.2 .
 .Pp
Index: find.c
===================================================================
RCS file: /cvsroot/src/usr.bin/find/find.c,v
retrieving revision 1.29
diff -u -p -r1.29 find.c
--- find.c	20 Mar 2012 20:34:57 -0000	1.29
+++ find.c	12 Jun 2016 00:30:16 -0000
@@ -102,16 +102,16 @@ find_formplan(char **argv)
 	 */
 	if (!isoutput) {
 		if (plan == NULL) {
-			new = c_print(NULL, 0);
+			new = c_print(NULL, 0, NULL);
 			tail = plan = new;
 		} else {
-			new = c_openparen(NULL, 0);
+			new = c_openparen(NULL, 0, NULL);
 			new->next = plan;
 			plan = new;
-			new = c_closeparen(NULL, 0);
+			new = c_closeparen(NULL, 0, NULL);
 			tail->next = new;
 			tail = new;
-			new = c_print(NULL, 0);
+			new = c_print(NULL, 0, NULL);
 			tail->next = new;
 			tail = new;
 		}
Index: find.h
===================================================================
RCS file: /cvsroot/src/usr.bin/find/find.h,v
retrieving revision 1.25
diff -u -p -r1.25 find.h
--- find.h	4 May 2013 06:29:32 -0000	1.25
+++ find.h	12 Jun 2016 00:30:16 -0000
@@ -40,13 +40,13 @@
 /* node type */
 enum ntype {
 	N_AND = 1, 				/* must start > 0 */
-	N_AMIN, N_ANEWER, N_ATIME, N_CLOSEPAREN, N_CMIN, N_CNEWER, N_CTIME,
-	N_DEPTH, N_EMPTY, N_EXEC, N_EXECDIR, N_EXIT, N_EXPR, N_FALSE, N_FLAGS,
-	N_FOLLOW, N_FPRINT, N_FSTYPE, N_GROUP,
+	N_AMIN, N_ANEWER, N_ASINCE, N_ATIME, N_CLOSEPAREN, N_CMIN, N_CNEWER,
+	N_CSINCE, N_CTIME, N_DEPTH, N_EMPTY, N_EXEC, N_EXECDIR, N_EXIT,
+	N_EXPR, N_FALSE, N_FLAGS, N_FOLLOW, N_FPRINT, N_FSTYPE, N_GROUP,
 	N_INAME, N_INUM, N_IREGEX, N_LINKS, N_LS, N_MINDEPTH, N_MAXDEPTH,
 	N_MMIN, N_MTIME, N_NAME, N_NEWER, N_NOGROUP, N_NOT, N_NOUSER, N_OK,
 	N_OPENPAREN, N_OR, N_PATH, N_PERM, N_PRINT, N_PRINT0, N_PRINTX,
-	N_PRUNE, N_REGEX, N_SIZE, N_TYPE, N_USER, N_XDEV, N_DELETE
+	N_PRUNE, N_REGEX, N_SINCE, N_SIZE, N_TYPE, N_USER, N_XDEV, N_DELETE
 };
 
 /* node definition */
@@ -129,10 +129,10 @@ typedef struct _plandata {
 #define	fprint_file	p_un._fprint_file
 
 typedef struct _option {
-	const char *name;		/* option name */
-	enum ntype token;		/* token type */
-	PLAN *(*create)(char ***, int);	/* create function */
-	int arg;			/* function needs arg */
+	const char *name;			/* option name */
+	enum ntype token;			/* token type */
+	PLAN *(*create)(char ***, int, char *);	/* create function */
+	int arg;				/* function needs arg */
 } OPTION;
 
 #include "extern.h"
Index: function.c
===================================================================
RCS file: /cvsroot/src/usr.bin/find/function.c,v
retrieving revision 1.72
diff -u -p -r1.72 function.c
--- function.c	4 May 2013 06:29:32 -0000	1.72
+++ function.c	12 Jun 2016 00:30:16 -0000
@@ -83,9 +83,11 @@ static	void	run_f_exec(PLAN *);
 	int	f_always_true(PLAN *, FTSENT *);
 	int	f_amin(PLAN *, FTSENT *);
 	int	f_anewer(PLAN *, FTSENT *);
+	int	f_asince(PLAN *, FTSENT *);
 	int	f_atime(PLAN *, FTSENT *);
 	int	f_cmin(PLAN *, FTSENT *);
 	int	f_cnewer(PLAN *, FTSENT *);
+	int	f_csince(PLAN *, FTSENT *);
 	int	f_ctime(PLAN *, FTSENT *);
 	int	f_delete(PLAN *, FTSENT *);
 	int	f_empty(PLAN *, FTSENT *);
@@ -106,6 +108,25 @@ static	void	run_f_exec(PLAN *);
 	int	f_mtime(PLAN *, FTSENT *);
 	int	f_name(PLAN *, FTSENT *);
 	int	f_newer(PLAN *, FTSENT *);
+/*
+ * Unimplemented Gnu findutils options
+ *
+	int	f_newerBB(PLAN *, FTSENT *);
+	int	f_newerBa(PLAN *, FTSENT *);
+	int	f_newerBc(PLAN *, FTSENT *);
+	int	f_newerBm(PLAN *, FTSENT *);
+	int	f_newerBt(PLAN *, FTSENT *);
+	int	f_neweraB(PLAN *, FTSENT *);
+	int	f_newerac(PLAN *, FTSENT *);
+	int	f_neweram(PLAN *, FTSENT *);
+	int	f_newerca(PLAN *, FTSENT *);
+	int	f_newercm(PLAN *, FTSENT *);
+	int	f_newercB(PLAN *, FTSENT *);
+	int	f_newermB(PLAN *, FTSENT *);
+	int	f_newerma(PLAN *, FTSENT *);
+	int	f_newermc(PLAN *, FTSENT *);
+ *
+ */
 	int	f_nogroup(PLAN *, FTSENT *);
 	int	f_nouser(PLAN *, FTSENT *);
 	int	f_path(PLAN *, FTSENT *);
@@ -115,6 +136,7 @@ static	void	run_f_exec(PLAN *);
 	int	f_printx(PLAN *, FTSENT *);
 	int	f_prune(PLAN *, FTSENT *);
 	int	f_regex(PLAN *, FTSENT *);
+	int	f_since(PLAN *, FTSENT *);
 	int	f_size(PLAN *, FTSENT *);
 	int	f_type(PLAN *, FTSENT *);
 	int	f_user(PLAN *, FTSENT *);
@@ -170,6 +192,23 @@ find_parsenum(PLAN *plan, const char *op
 }
 
 /*
+ * find_parsedate --
+ *
+ * Validate the timestamp argument or report an error
+ */
+static time_t
+find_parsedate(PLAN *plan, const char *option, const char *vp)
+{
+	time_t timestamp;
+
+	errno = 0;
+	timestamp = parsedate(vp, NULL, NULL);
+	if (timestamp == -1 && errno != 0)
+		errx(1, "%s: %s: invalid timestamp value", option, vp);
+	return timestamp;
+}
+
+/*
  * 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
@@ -193,7 +232,7 @@ f_amin(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_amin(char ***argvp, int isok)
+c_amin(char ***argvp, int isok, char *opt)
 {
 	char *arg = **argvp;
 	PLAN *new;
@@ -202,7 +241,7 @@ c_amin(char ***argvp, int isok)
 	ftsoptions &= ~FTS_NOSTAT;
 
 	new = palloc(N_AMIN, f_amin);
-	new->t_data = find_parsenum(new, "-amin", arg, NULL);
+	new->t_data = find_parsenum(new, opt, arg, NULL);
 	TIME_CORRECT(new, N_AMIN);
 	return (new);
 }
@@ -222,7 +261,7 @@ f_anewer(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_anewer(char ***argvp, int isok)
+c_anewer(char ***argvp, int isok, char *opt)
 {
 	char *filename = **argvp;
 	PLAN *new;
@@ -232,13 +271,39 @@ c_anewer(char ***argvp, int isok)
 	ftsoptions &= ~FTS_NOSTAT;
 
 	if (stat(filename, &sb))
-		err(1, "%s", filename);
+		err(1, "%s: %s:", opt, filename);
 	new = palloc(N_ANEWER, f_anewer);
 	new->ts_data = sb.st_atim;
 	return (new);
 }
 
 /*
+ * -asince "timestamp" functions --
+ *
+ *	True if the file access time is greater than the timestamp value
+ */
+int
+f_asince(PLAN *plan, FTSENT *entry)
+{
+	COMPARE(entry->fts_statp->st_atime, plan->t_data);
+}
+
+PLAN *
+c_asince(char ***argvp, int isok, char *opt)
+{
+	char *arg = **argvp;
+	PLAN *new;
+
+	(*argvp)++;
+	ftsoptions &= ~FTS_NOSTAT;
+
+	new = palloc(N_ASINCE, f_asince);
+	new->t_data = find_parsedate(new, opt, arg);
+	new->flags = F_GREATER;
+	return (new);
+}
+
+/*
  * -atime n functions --
  *
  *	True if the difference between the file access time and the
@@ -252,7 +317,7 @@ f_atime(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_atime(char ***argvp, int isok)
+c_atime(char ***argvp, int isok, char *opt)
 {
 	char *arg = **argvp;
 	PLAN *new;
@@ -261,7 +326,7 @@ c_atime(char ***argvp, int isok)
 	ftsoptions &= ~FTS_NOSTAT;
 
 	new = palloc(N_ATIME, f_atime);
-	new->t_data = find_parsenum(new, "-atime", arg, NULL);
+	new->t_data = find_parsenum(new, opt, arg, NULL);
 	TIME_CORRECT(new, N_ATIME);
 	return (new);
 }
@@ -280,7 +345,7 @@ f_cmin(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_cmin(char ***argvp, int isok)
+c_cmin(char ***argvp, int isok, char *opt)
 {
 	char *arg = **argvp;
 	PLAN *new;
@@ -289,7 +354,7 @@ c_cmin(char ***argvp, int isok)
 	ftsoptions &= ~FTS_NOSTAT;
 
 	new = palloc(N_CMIN, f_cmin);
-	new->t_data = find_parsenum(new, "-cmin", arg, NULL);
+	new->t_data = find_parsenum(new, opt, arg, NULL);
 	TIME_CORRECT(new, N_CMIN);
 	return (new);
 }
@@ -309,7 +374,7 @@ f_cnewer(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_cnewer(char ***argvp, int isok)
+c_cnewer(char ***argvp, int isok, char *opt)
 {
 	char *filename = **argvp;
 	PLAN *new;
@@ -319,13 +384,39 @@ c_cnewer(char ***argvp, int isok)
 	ftsoptions &= ~FTS_NOSTAT;
 
 	if (stat(filename, &sb))
-		err(1, "%s", filename);
+		err(1, "%s: %s: ", opt, filename);
 	new = palloc(N_CNEWER, f_cnewer);
 	new->ts_data = sb.st_ctim;
 	return (new);
 }
 
 /*
+ * -csince "timestamp" functions --
+ *
+ *	True if the file status change time is greater than the timestamp value
+ */
+int
+f_csince(PLAN *plan, FTSENT *entry)
+{
+	COMPARE(entry->fts_statp->st_ctime, plan->t_data);
+}
+
+PLAN *
+c_csince(char ***argvp, int isok, char *opt)
+{
+	char *arg = **argvp;
+	PLAN *new;
+
+	(*argvp)++;
+	ftsoptions &= ~FTS_NOSTAT;
+
+	new = palloc(N_CSINCE, f_csince);
+	new->t_data = find_parsedate(new, opt, arg);
+	new->flags = F_GREATER;
+	return (new);
+}
+
+/*
  * -ctime n functions --
  *
  *	True if the difference between the last change of file
@@ -339,7 +430,7 @@ f_ctime(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_ctime(char ***argvp, int isok)
+c_ctime(char ***argvp, int isok, char *opt)
 {
 	char *arg = **argvp;
 	PLAN *new;
@@ -348,7 +439,7 @@ c_ctime(char ***argvp, int isok)
 	ftsoptions &= ~FTS_NOSTAT;
 
 	new = palloc(N_CTIME, f_ctime);
-	new->t_data = find_parsenum(new, "-ctime", arg, NULL);
+	new->t_data = find_parsenum(new, opt, arg, NULL);
 	TIME_CORRECT(new, N_CTIME);
 	return (new);
 }
@@ -399,7 +490,7 @@ f_delete(PLAN *plan __unused, FTSENT *en
 }
 
 PLAN *
-c_delete(char ***argvp __unused, int isok)
+c_delete(char ***argvp __unused, int isok, char *opt)
 {
 
 	ftsoptions &= ~FTS_NOSTAT;	/* no optimize */
@@ -426,7 +517,7 @@ f_always_true(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_depth(char ***argvp, int isok)
+c_depth(char ***argvp, int isok, char *opt)
 {
 	isdepth = 1;
 
@@ -467,7 +558,7 @@ f_empty(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_empty(char ***argvp, int isok)
+c_empty(char ***argvp, int isok, char *opt)
 {
 	ftsoptions &= ~FTS_NOSTAT;
 
@@ -624,7 +715,7 @@ run_f_exec(PLAN *plan)
  *	discussion), and then allocate ARG_MAX - 4K of space for args.
  */
 PLAN *
-c_exec(char ***argvp, int isok)
+c_exec(char ***argvp, int isok, char *opt)
 {
 	PLAN *new;			/* node returned */
 	size_t cnt;
@@ -644,8 +735,7 @@ c_exec(char ***argvp, int isok)
 	 */
 	for (ap = argv = *argvp, brace = 0;; ++ap) {
 		if (!*ap)
-			errx(1, "%s: no terminating \";\" or \"+\"",
-			    isok ? "-ok" : "-exec");
+			errx(1, "%s: no terminating \";\" or \"+\"", opt);
 		lastbrace = brace;
 		brace = 0;
 		if (strcmp(*ap, "{}") == 0)
@@ -663,7 +753,7 @@ c_exec(char ***argvp, int isok)
 	 * not make much sense anyway.
 	 */
 	if (new->flags & F_NEEDOK && new->flags & F_PLUSSET)
-		errx(1, "-ok: terminating \"+\" not permitted.");
+		errx(1, "%s: terminating \"+\" not permitted.", opt);
 
 	if (new->flags & F_PLUSSET) {
 		size_t c, bufsize;
@@ -780,7 +870,7 @@ f_execdir(PLAN *plan, FTSENT *entry)
  *	strings, but also flags meaning that the string has to be massaged.
  */
 PLAN *
-c_execdir(char ***argvp, int isok)
+c_execdir(char ***argvp, int isok, char *opt)
 {
 	PLAN *new;			/* node returned */
 	size_t cnt;
@@ -793,8 +883,7 @@ c_execdir(char ***argvp, int isok)
 
 	for (ap = argv = *argvp;; ++ap) {
 		if (!*ap)
-			errx(1,
-			    "-execdir: no terminating \";\"");
+			errx(1, "%s: no terminating \";\"", opt);
 		if (**ap == ';')
 			break;
 	}
@@ -824,7 +913,7 @@ c_execdir(char ***argvp, int isok)
 }
 
 PLAN *
-c_exit(char ***argvp, int isok)
+c_exit(char ***argvp, int isok, char *opt)
 {
 	char *arg = **argvp;
 	PLAN *new;
@@ -836,7 +925,7 @@ c_exit(char ***argvp, int isok)
 
 	if (arg) {
 		(*argvp)++;
-		new->exit_val = find_parsenum(new, "-exit", arg, NULL);
+		new->exit_val = find_parsenum(new, opt, arg, NULL);
 	} else
 		new->exit_val = 0;
 
@@ -855,7 +944,7 @@ f_false(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_false(char ***argvp, int isok)
+c_false(char ***argvp, int isok, char *opt)
 {
 	return (palloc(N_FALSE, f_false));
 }
@@ -878,7 +967,7 @@ f_flags(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_flags(char ***argvp, int isok)
+c_flags(char ***argvp, int isok, char *opt)
 {
 	char *flags = **argvp;
 	PLAN *new;
@@ -897,7 +986,7 @@ c_flags(char ***argvp, int isok)
 	flagset = 0;
 	if ((strcmp(flags, "none") != 0) &&
 	    (string_to_flags(&flags, &flagset, NULL) != 0))
-		errx(1, "-flags: %s: illegal flags string", flags);
+		errx(1, "%s: %s: illegal flags string", opt, flags);
 	new->f_data = flagset;
 	return (new);
 }
@@ -909,7 +998,7 @@ c_flags(char ***argvp, int isok)
  *	basis.
  */
 PLAN *
-c_follow(char ***argvp, int isok)
+c_follow(char ***argvp, int isok, char *opt)
 {
 	ftsoptions &= ~FTS_PHYSICAL;
 	ftsoptions |= FTS_LOGICAL;
@@ -935,7 +1024,7 @@ f_fprint(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_fprint(char ***argvp, int isok)
+c_fprint(char ***argvp, int isok, char *opt)
 {
 	PLAN *new;
 
@@ -944,7 +1033,7 @@ c_fprint(char ***argvp, int isok)
 	new = palloc(N_FPRINT, f_fprint);
 
 	if (NULL == (new->fprint_file = fopen(**argvp, "w")))
-		err(1, "-fprint: %s: cannot create file", **argvp);
+		err(1, "%s: %s: cannot create file", opt, **argvp);
 
 	(*argvp)++;
 	return (new);
@@ -1017,7 +1106,7 @@ f_fstype(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_fstype(char ***argvp, int isok)
+c_fstype(char ***argvp, int isok, char *opt)
 {
 	char *arg = **argvp;
 	PLAN *new;
@@ -1064,7 +1153,7 @@ f_group(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_group(char ***argvp, int isok)
+c_group(char ***argvp, int isok, char *opt)
 {
 	char *gname = **argvp;
 	PLAN *new;
@@ -1078,7 +1167,7 @@ c_group(char ***argvp, int isok)
 	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", opt, gname);
 	} else
 		gid = g->gr_gid;
 
@@ -1100,7 +1189,7 @@ f_inum(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_inum(char ***argvp, int isok)
+c_inum(char ***argvp, int isok, char *opt)
 {
 	char *arg = **argvp;
 	PLAN *new;
@@ -1109,7 +1198,7 @@ c_inum(char ***argvp, int isok)
 	ftsoptions &= ~FTS_NOSTAT;
 
 	new = palloc(N_INUM, f_inum);
-	new->i_data = find_parsenum(new, "-inum", arg, NULL);
+	new->i_data = find_parsenum(new, opt, arg, NULL);
 	return (new);
 }
 
@@ -1126,7 +1215,7 @@ f_links(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_links(char ***argvp, int isok)
+c_links(char ***argvp, int isok, char *opt)
 {
 	char *arg = **argvp;
 	PLAN *new;
@@ -1135,7 +1224,7 @@ c_links(char ***argvp, int isok)
 	ftsoptions &= ~FTS_NOSTAT;
 
 	new = palloc(N_LINKS, f_links);
-	new->l_data = (nlink_t)find_parsenum(new, "-links", arg, NULL);
+	new->l_data = (nlink_t)find_parsenum(new, opt, arg, NULL);
 	return (new);
 }
 
@@ -1153,7 +1242,7 @@ f_ls(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_ls(char ***argvp, int isok)
+c_ls(char ***argvp, int isok, char *opt)
 {
 
 	ftsoptions &= ~FTS_NOSTAT;
@@ -1179,7 +1268,7 @@ f_maxdepth(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_maxdepth(char ***argvp, int isok)
+c_maxdepth(char ***argvp, int isok, char *opt)
 {
 	char *arg = **argvp;
 	PLAN *new;
@@ -1203,7 +1292,7 @@ f_mindepth(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_mindepth(char ***argvp, int isok)
+c_mindepth(char ***argvp, int isok, char *opt)
 {
 	char *arg = **argvp;
 	PLAN *new;
@@ -1228,7 +1317,7 @@ f_mmin(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_mmin(char ***argvp, int isok)
+c_mmin(char ***argvp, int isok, char *opt)
 {
 	char *arg = **argvp;
 	PLAN *new;
@@ -1237,7 +1326,7 @@ c_mmin(char ***argvp, int isok)
 	ftsoptions &= ~FTS_NOSTAT;
 
 	new = palloc(N_MMIN, f_mmin);
-	new->t_data = find_parsenum(new, "-mmin", arg, NULL);
+	new->t_data = find_parsenum(new, opt, arg, NULL);
 	TIME_CORRECT(new, N_MMIN);
 	return (new);
 }
@@ -1256,7 +1345,7 @@ f_mtime(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_mtime(char ***argvp, int isok)
+c_mtime(char ***argvp, int isok, char *opt)
 {
 	char *arg = **argvp;
 	PLAN *new;
@@ -1265,7 +1354,7 @@ c_mtime(char ***argvp, int isok)
 	ftsoptions &= ~FTS_NOSTAT;
 
 	new = palloc(N_MTIME, f_mtime);
-	new->t_data = find_parsenum(new, "-mtime", arg, NULL);
+	new->t_data = find_parsenum(new, opt, arg, NULL);
 	TIME_CORRECT(new, N_MTIME);
 	return (new);
 }
@@ -1284,7 +1373,7 @@ f_name(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_name(char ***argvp, int isok)
+c_name(char ***argvp, int isok, char *opt)
 {
 	char *pattern = **argvp;
 	PLAN *new;
@@ -1308,7 +1397,7 @@ f_iname(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_iname(char ***argvp, int isok)
+c_iname(char ***argvp, int isok, char *opt)
 {
 	char *pattern = **argvp;
 	PLAN *new;
@@ -1334,7 +1423,7 @@ f_newer(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_newer(char ***argvp, int isok)
+c_newer(char ***argvp, int isok, char *opt)
 {
 	char *filename = **argvp;
 	PLAN *new;
@@ -1344,7 +1433,7 @@ c_newer(char ***argvp, int isok)
 	ftsoptions &= ~FTS_NOSTAT;
 
 	if (stat(filename, &sb))
-		err(1, "%s", filename);
+		err(1, "%s: %s", opt, filename);
 	new = palloc(N_NEWER, f_newer);
 	new->ts_data = sb.st_mtim;
 	return (new);
@@ -1364,7 +1453,7 @@ f_nogroup(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_nogroup(char ***argvp, int isok)
+c_nogroup(char ***argvp, int isok, char *opt)
 {
 	ftsoptions &= ~FTS_NOSTAT;
 
@@ -1385,7 +1474,7 @@ f_nouser(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_nouser(char ***argvp, int isok)
+c_nouser(char ***argvp, int isok, char *opt)
 {
 	ftsoptions &= ~FTS_NOSTAT;
 
@@ -1406,7 +1495,7 @@ f_path(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_path(char ***argvp, int isok)
+c_path(char ***argvp, int isok, char *opt)
 {
 	char *pattern = **argvp;
 	PLAN *new;
@@ -1439,7 +1528,7 @@ f_perm(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_perm(char ***argvp, int isok)
+c_perm(char ***argvp, int isok, char *opt)
 {
 	char *perm = **argvp;
 	PLAN *new;
@@ -1456,7 +1545,7 @@ c_perm(char ***argvp, int isok)
 	}
 
 	if ((set = setmode(perm)) == NULL)
-		err(1, "-perm: Cannot set file mode `%s'", perm);
+		err(1, "%s: Cannot set file mode `%s'", opt, perm);
 
 	new->m_data = getmode(set, 0);
 	free(set);
@@ -1505,7 +1594,7 @@ f_printx(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_print(char ***argvp, int isok)
+c_print(char ***argvp, int isok, char *opt)
 {
 
 	isoutput = 1;
@@ -1514,7 +1603,7 @@ c_print(char ***argvp, int isok)
 }
 
 PLAN *
-c_print0(char ***argvp, int isok)
+c_print0(char ***argvp, int isok, char *opt)
 {
 
 	isoutput = 1;
@@ -1523,7 +1612,7 @@ c_print0(char ***argvp, int isok)
 }
 
 PLAN *
-c_printx(char ***argvp, int isok)
+c_printx(char ***argvp, int isok, char *opt)
 {
 
 	isoutput = 1;
@@ -1545,7 +1634,7 @@ f_prune(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_prune(char ***argvp, int isok)
+c_prune(char ***argvp, int isok, char *opt)
 {
 
 	return (palloc(N_PRUNE, f_prune));
@@ -1599,20 +1688,46 @@ c_regex_common(char ***argvp, int isok, 
 }
 
 PLAN *
-c_regex(char ***argvp, int isok)
+c_regex(char ***argvp, int isok, char *opt)
 {
 
 	return (c_regex_common(argvp, isok, N_REGEX, false));
 }
 
 PLAN *
-c_iregex(char ***argvp, int isok)
+c_iregex(char ***argvp, int isok, char *opt)
 {
 
 	return (c_regex_common(argvp, isok, N_IREGEX, true));
 }
 
 /*
+ * -since "timestamp" functions --
+ *
+ *	True if the file modification time is greater than the timestamp value
+ */
+int
+f_since(PLAN *plan, FTSENT *entry)
+{
+	COMPARE(entry->fts_statp->st_mtime, plan->t_data);
+}
+
+PLAN *
+c_since(char ***argvp, int isok, char *opt)
+{
+	char *arg = **argvp;
+	PLAN *new;
+
+	(*argvp)++;
+	ftsoptions &= ~FTS_NOSTAT;
+
+	new = palloc(N_SINCE, f_since);
+	new->t_data = find_parsedate(new, opt, arg);
+	new->flags = F_GREATER;
+	return (new);
+}
+
+/*
  * -size n[c] functions --
  *
  *	True if the file size in bytes, divided by an implementation defined
@@ -1633,7 +1748,7 @@ f_size(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_size(char ***argvp, int isok)
+c_size(char ***argvp, int isok, char *opt)
 {
 	char *arg = **argvp;
 	PLAN *new;
@@ -1644,7 +1759,7 @@ c_size(char ***argvp, int isok)
 
 	new = palloc(N_SIZE, f_size);
 	endch = 'c';
-	new->o_data = find_parsenum(new, "-size", arg, &endch);
+	new->o_data = find_parsenum(new, opt, arg, &endch);
 	if (endch == 'c')
 		divsize = 0;
 	return (new);
@@ -1665,7 +1780,7 @@ f_type(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_type(char ***argvp, int isok)
+c_type(char ***argvp, int isok, char *opt)
 {
 	char *typestring = **argvp;
 	PLAN *new;
@@ -1706,7 +1821,7 @@ c_type(char ***argvp, int isok)
 		break;
 #endif /* S_IFWHT */
 	default:
-		errx(1, "-type: %s: unknown type", typestring);
+		errx(1, "%s: %s: unknown type", opt, typestring);
 	}
 
 	new = palloc(N_TYPE, f_type);
@@ -1729,7 +1844,7 @@ f_user(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_user(char ***argvp, int isok)
+c_user(char ***argvp, int isok, char *opt)
 {
 	char *username = **argvp;
 	PLAN *new;
@@ -1744,8 +1859,8 @@ c_user(char ***argvp, int isok)
 	if (p == NULL) {
 		if (atoi(username) == 0 && username[0] != '0' &&
 		    strcmp(username, "+0") && strcmp(username, "-0"))
-			errx(1, "-user: %s: no such user", username);
-		uid = find_parsenum(new, "-user", username, NULL);
+			errx(1, "%s: %s: no such user", opt, username);
+		uid = find_parsenum(new, opt, username, NULL);
 
 	} else {
 		new->flags = F_EQUAL;
@@ -1763,7 +1878,7 @@ c_user(char ***argvp, int isok)
  *	different device ID (st_dev, see stat() S5.6.2 [POSIX.1])
  */
 PLAN *
-c_xdev(char ***argvp, int isok)
+c_xdev(char ***argvp, int isok, char *opt)
 {
 	ftsoptions |= FTS_XDEV;
 
@@ -1793,14 +1908,14 @@ f_expr(PLAN *plan, FTSENT *entry)
  * to a N_EXPR node containing the expression and the ')' node is discarded.
  */
 PLAN *
-c_openparen(char ***argvp, int isok)
+c_openparen(char ***argvp, int isok, char *opt)
 {
 
 	return (palloc(N_OPENPAREN, (int (*)(PLAN *, FTSENT *))-1));
 }
 
 PLAN *
-c_closeparen(char ***argvp, int isok)
+c_closeparen(char ***argvp, int isok, char *opt)
 {
 
 	return (palloc(N_CLOSEPAREN, (int (*)(PLAN *, FTSENT *))-1));
@@ -1824,7 +1939,7 @@ f_not(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_not(char ***argvp, int isok)
+c_not(char ***argvp, int isok, char *opt)
 {
 
 	return (palloc(N_NOT, f_not));
@@ -1855,14 +1970,14 @@ f_or(PLAN *plan, FTSENT *entry)
 }
 
 PLAN *
-c_or(char ***argvp, int isok)
+c_or(char ***argvp, int isok, char *opt)
 {
 
 	return (palloc(N_OR, f_or));
 }
 
 PLAN *
-c_null(char ***argvp, int isok)
+c_null(char ***argvp, int isok, char *opt)
 {
 
 	return (NULL);
Index: option.c
===================================================================
RCS file: /cvsroot/src/usr.bin/find/option.c,v
retrieving revision 1.26
diff -u -p -r1.26 option.c
--- option.c	6 Feb 2007 15:33:22 -0000	1.26
+++ option.c	12 Jun 2016 00:30:16 -0000
@@ -64,9 +64,11 @@ static OPTION const options[] = {
 	{ "-amin",	N_AMIN,		c_amin,		1 },
 	{ "-and",	N_AND,		c_null,		0 },
 	{ "-anewer",	N_ANEWER,	c_anewer,	1 },
+	{ "-asince",	N_ASINCE,	c_asince,	1 },
 	{ "-atime",	N_ATIME,	c_atime,	1 },
 	{ "-cmin",	N_CMIN,		c_cmin,		1 },
 	{ "-cnewer",	N_CNEWER,	c_cnewer,	1 },
+	{ "-csince",	N_CSINCE,	c_csince,	1 },
 	{ "-ctime",	N_CTIME,	c_ctime,	1 },
 	{ "-delete",	N_DELETE,	c_delete,	0 },
 	{ "-depth",	N_DEPTH,	c_depth,	0 },
@@ -91,6 +93,38 @@ static OPTION const options[] = {
 	{ "-mtime",	N_MTIME,	c_mtime,	1 },
 	{ "-name",	N_NAME,		c_name,		1 },
 	{ "-newer",	N_NEWER,	c_newer,	1 },
+
+/* Aliases for compatability with Gnu findutils */
+	{ "-neweraa",	N_ANEWER,	c_anewer,	1 },
+	{ "-newerat",	N_ASINCE,	c_asince,	1 },
+	{ "-newercc",	N_CNEWER,	c_cnewer,	1 },
+	{ "-newerct",	N_CSINCE,	c_csince,	1 },
+	{ "-newermm",	N_NEWER,	c_newer,	1 },
+	{ "-newermt",	N_SINCE,	c_since,	1 },
+
+/*
+ * Unimplemented Gnu findutils options 
+ *
+ * If you implement any of these, be sure to re-sort the table
+ * in ascii(7) order!
+ *
+        { "-newerBB",	N_UNIMPL,	c_unimpl,	1 },
+        { "-newerBa",	N_UNIMPL,	c_unimpl,	1 },
+        { "-newerBc",	N_UNIMPL,	c_unimpl,	1 },
+        { "-newerBm",	N_UNIMPL,	c_unimpl,	1 },
+        { "-newerBt",	N_UNIMPL,	c_unimpl,	1 },
+        { "-neweraB",	N_UNIMPL,	c_unimpl,	1 },
+        { "-newerac",	N_UNIMPL,	c_unimpl,	1 },
+        { "-neweram",	N_UNIMPL,	c_unimpl,	1 },
+        { "-newerca",	N_UNIMPL,	c_unimpl,	1 },
+        { "-newercm",	N_UNIMPL,	c_unimpl,	1 },
+        { "-newercB",	N_UNIMPL,	c_unimpl,	1 },
+        { "-newermB",	N_UNIMPL,	c_unimpl,	1 },
+        { "-newerma",	N_UNIMPL,	c_unimpl,	1 },
+        { "-newermc",	N_UNIMPL,	c_unimpl,	1 },
+ *
+ */
+
 	{ "-nogroup",	N_NOGROUP,	c_nogroup,	0 },
 	{ "-nouser",	N_NOUSER,	c_nouser,	0 },
 	{ "-o",		N_OR,		c_or,		0 },
@@ -104,6 +138,7 @@ static OPTION const options[] = {
 	{ "-prune",	N_PRUNE,	c_prune,	0 },
 	{ "-regex",	N_REGEX,	c_regex,	1 },
 	{ "-rm",	N_DELETE,	c_delete,	0 },
+	{ "-since",	N_SINCE,	c_since,	1 },
 	{ "-size",	N_SIZE,		c_size,		1 },
 	{ "-type",	N_TYPE,		c_type,		1 },
 	{ "-user",	N_USER,		c_user,		1 },
@@ -124,16 +159,18 @@ find_create(char ***argvp)
 	OPTION *p;
 	PLAN *new;
 	char **argv;
+	char *opt;
 
 	argv = *argvp;
+	opt = *argv;
 
-	if ((p = option(*argv)) == NULL)
-		errx(1, "%s: unknown option", *argv);
+	if ((p = option(opt)) == NULL)
+		errx(1, "%s: unknown option", opt);
 	++argv;
 	if (p->arg && !*argv)
-		errx(1, "%s: requires additional arguments", *--argv);
+		errx(1, "%s: requires additional arguments", opt);
 
-	new = (p->create)(&argv, p->token == N_OK);
+	new = (p->create)(&argv, p->token == N_OK, opt);
 
 	*argvp = argv;
 	return (new);


Home | Main Index | Thread Index | Old Index