The branch main has been updated by des:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=d05e43bc0d5705919d057793aaa3e6d3df65f815

commit d05e43bc0d5705919d057793aaa3e6d3df65f815
Author:     Dag-Erling Smørgrav <[email protected]>
AuthorDate: 2022-10-19 17:02:45 +0000
Commit:     Dag-Erling Smørgrav <[email protected]>
CommitDate: 2022-10-19 17:02:45 +0000

    pax: update date parsing code (from OpenBSD)
    
    Sponsored by:   Klara, Inc.
    MFC after:      1 week
---
 bin/pax/pax.1      |  25 +++++++-----
 bin/pax/sel_subs.c | 116 +++++++++++++++++++++++++++++------------------------
 bin/pax/sel_subs.h |   2 +-
 3 files changed, 78 insertions(+), 65 deletions(-)

diff --git a/bin/pax/pax.1 b/bin/pax/pax.1
index abfbacee78b3..b503e1562f8a 100644
--- a/bin/pax/pax.1
+++ b/bin/pax/pax.1
@@ -33,7 +33,7 @@
 .\"    @(#)pax.1       8.4 (Berkeley) 4/18/94
 .\" $FreeBSD$
 .\"
-.Dd December 29, 2018
+.Dd October 19, 2022
 .Dt PAX 1
 .Os
 .Sh NAME
@@ -933,28 +933,31 @@ changed during a specified time range will be archived).
 A time range is made up of six different fields and each field must contain two
 digits.
 The format is:
-.Dl [yy[mm[dd[hh]]]]mm[.ss]
+.Pp
+.Dl [[[[[cc]yy]mm]dd]HH]MM[.SS]
+.Pp
 Where
-.Cm yy
+.Ar cc
+is the first two digits of the year (the century),
+.Ar yy
 is the last two digits of the year,
 the first
-.Cm mm
+.Ar mm
 is the month (from 01 to 12),
-.Cm dd
+.Ar dd
 is the day of the month (from 01 to 31),
-.Cm hh
+.Ar HH
 is the hour of the day (from 00 to 23),
-the second
-.Cm mm
+.Ar MM
 is the minute (from 00 to 59),
 and
-.Cm ss
+.Ar SS
 is the seconds (from 00 to 59).
 The minute field
-.Cm mm
+.Ar MM
 is required, while the other fields are optional and must be added in the
 following order:
-.Dl Cm hh , dd , mm , yy .
+.Ar HH , dd , mm , yy , cc .
 The
 .Cm ss
 field may be added independently of the other fields.
diff --git a/bin/pax/sel_subs.c b/bin/pax/sel_subs.c
index 12975f21946f..7ef5bec523a5 100644
--- a/bin/pax/sel_subs.c
+++ b/bin/pax/sel_subs.c
@@ -44,17 +44,20 @@ __FBSDID("$FreeBSD$");
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/stat.h>
-#include <pwd.h>
+
+#include <ctype.h>
 #include <grp.h>
+#include <pwd.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <strings.h>
-#include <stdlib.h>
+
 #include "pax.h"
 #include "sel_subs.h"
 #include "extern.h"
 
-static int str_sec(char *, time_t *);
+static int str_sec(const char *, time_t *);
 static int usr_match(ARCHD *);
 static int grp_match(ARCHD *);
 static int trng_match(ARCHD *);
@@ -309,7 +312,7 @@ grp_match(ARCHD *arcn)
  * trng_add()
  *     add a time range match to the time range list.
  *     This is a non-standard pax option. Lower and upper ranges are in the
- *     format: [yy[mm[dd[hh]]]]mm[.ss] and are comma separated.
+ *     format: [[[[[cc]yy]mm]dd]HH]MM[.SS] and are comma separated.
  *     Time ranges are based on current time, so 1234 would specify a time of
  *     12:34 today.
  * Return:
@@ -446,7 +449,7 @@ trng_add(char *str)
        return(0);
 
     out:
-       paxwarn(1, "Time range format is: [yy[mm[dd[hh]]]]mm[.ss][/[c][m]]");
+       paxwarn(1, "Time range format is: 
[[[[[cc]yy]mm]dd]HH]MM[.SS][/[c][m]]");
        return(-1);
 }
 
@@ -520,80 +523,87 @@ trng_match(ARCHD *arcn)
 
 /*
  * str_sec()
- *     Convert a time string in the format of [[[[yy[mm[dd[hh]mm[.ss] to gmt
- *     seconds. Tval already has current time loaded into it at entry.
+ *     Convert a time string in the format of [[[[[cc]yy]mm]dd]HH]MM[.SS] to
+ *     seconds UTC. Tval already has current time loaded into it at entry.
  * Return:
  *     0 if converted ok, -1 otherwise
  */
 
 static int
-str_sec(char *str, time_t *tval)
+str_sec(const char *p, time_t *tval)
 {
        struct tm *lt;
-       char *dot = NULL;
+       const char *dot, *t;
+       size_t len;
+       int bigyear;
+       int yearset;
+
+       yearset = 0;
+       len = strlen(p);
+
+       for (t = p, dot = NULL; *t; ++t) {
+               if (isdigit((unsigned char)*t))
+                       continue;
+               if (*t == '.' && dot == NULL) {
+                       dot = t;
+                       continue;
+               }
+               return(-1);
+       }
 
        lt = localtime(tval);
-       if ((dot = strchr(str, '.')) != NULL) {
-               /*
-                * seconds (.ss)
-                */
-               *dot++ = '\0';
-               if (strlen(dot) != 2)
+
+       if (dot != NULL) {                      /* .SS */
+               if (strlen(++dot) != 2)
                        return(-1);
-               if ((lt->tm_sec = ATOI2(dot)) > 61)
+               lt->tm_sec = ATOI2(dot);
+               if (lt->tm_sec > 61)
                        return(-1);
+               len -= 3;
        } else
                lt->tm_sec = 0;
 
-       switch (strlen(str)) {
-       case 10:
-               /*
-                * year (yy)
-                * watch out for year 2000
-                */
-               if ((lt->tm_year = ATOI2(str)) < 69)
-                       lt->tm_year += 100;
-               str += 2;
+       switch (len) {
+       case 12:                                /* cc */
+               bigyear = ATOI2(p);
+               lt->tm_year = (bigyear * 100) - 1900;
+               yearset = 1;
                /* FALLTHROUGH */
-       case 8:
-               /*
-                * month (mm)
-                * watch out months are from 0 - 11 internally
-                */
-               if ((lt->tm_mon = ATOI2(str)) > 12)
+       case 10:                                /* yy */
+               if (yearset) {
+                       lt->tm_year += ATOI2(p);
+               } else {
+                       lt->tm_year = ATOI2(p);
+                       if (lt->tm_year < 69)           /* hack for 2000 ;-} */
+                               lt->tm_year += (2000 - 1900);
+               }
+               /* FALLTHROUGH */
+       case 8:                                 /* mm */
+               lt->tm_mon = ATOI2(p);
+               if ((lt->tm_mon > 12) || !lt->tm_mon)
                        return(-1);
-               --lt->tm_mon;
-               str += 2;
+               --lt->tm_mon;                   /* time struct is 0 - 11 */
                /* FALLTHROUGH */
-       case 6:
-               /*
-                * day (dd)
-                */
-               if ((lt->tm_mday = ATOI2(str)) > 31)
+       case 6:                                 /* dd */
+               lt->tm_mday = ATOI2(p);
+               if ((lt->tm_mday > 31) || !lt->tm_mday)
                        return(-1);
-               str += 2;
                /* FALLTHROUGH */
-       case 4:
-               /*
-                * hour (hh)
-                */
-               if ((lt->tm_hour = ATOI2(str)) > 23)
+       case 4:                                 /* HH */
+               lt->tm_hour = ATOI2(p);
+               if (lt->tm_hour > 23)
                        return(-1);
-               str += 2;
                /* FALLTHROUGH */
-       case 2:
-               /*
-                * minute (mm)
-                */
-               if ((lt->tm_min = ATOI2(str)) > 59)
+       case 2:                                 /* MM */
+               lt->tm_min = ATOI2(p);
+               if (lt->tm_min > 59)
                        return(-1);
                break;
        default:
                return(-1);
        }
-       /*
-        * convert broken-down time to GMT clock time seconds
-        */
+
+       /* convert broken-down time to UTC clock time seconds */
        if ((*tval = mktime(lt)) == -1)
                return(-1);
        return(0);
diff --git a/bin/pax/sel_subs.h b/bin/pax/sel_subs.h
index 7e1ddeedcb87..a628e6981b1a 100644
--- a/bin/pax/sel_subs.h
+++ b/bin/pax/sel_subs.h
@@ -57,7 +57,7 @@ typedef struct grpt {
  * data structure for storing user supplied time ranges (-T option)
  */
 
-#define ATOI2(s)       ((((s)[0] - '0') * 10) + ((s)[1] - '0'))
+#define ATOI2(ar)      ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
 
 typedef struct time_rng {
        time_t          low_time;       /* lower inclusive time limit */

Reply via email to