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);

Reply via email to