git: d05e43bc0d57 - main - pax: update date parsing code (from OpenBSD)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 19 Oct 2022 17:04:17 UTC
The branch main has been updated by des:
URL: https://cgit.FreeBSD.org/src/commit/?id=d05e43bc0d5705919d057793aaa3e6d3df65f815
commit d05e43bc0d5705919d057793aaa3e6d3df65f815
Author: Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2022-10-19 17:02:45 +0000
Commit: Dag-Erling Smørgrav <des@FreeBSD.org>
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 */