From 79dc2434cb8d39213b24b89f6c618174d8e9cbd4 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 24 Mar 2019 18:05:34 -0500 Subject: Factor out xparsedate() and xvali_date() into lib. --- toys/posix/date.c | 133 ++++-------------------------------------------------- 1 file changed, 10 insertions(+), 123 deletions(-) (limited to 'toys/posix') diff --git a/toys/posix/date.c b/toys/posix/date.c index 43b558a5..685ac8bf 100644 --- a/toys/posix/date.c +++ b/toys/posix/date.c @@ -59,135 +59,29 @@ GLOBALS( unsigned nano; ) -static void check_range(int a, int low, int high) -{ - if (ahigh) error_exit("%d>%d", a, high); -} - -static void check_tm(struct tm *tm) -{ - check_range(tm->tm_sec, 0, 60); - check_range(tm->tm_min, 0, 59); - check_range(tm->tm_hour, 0, 23); - check_range(tm->tm_mday, 1, 31); - check_range(tm->tm_mon, 0, 11); -} - -// Returns 0 success, nonzero for error. -static int parse_formats(char *str, time_t *t) -{ - struct tm tm; - time_t now; - int len = 0, i; - char *formats[] = { - // Formats with years must come first. - "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M", "%Y-%m-%d", - "%H:%M:%S", "%H:%M" - }; - - // Parse @UNIXTIME[.FRACTION] - if (*str == '@') { - long long ll; - - // Collect seconds and nanoseconds. - // &ll is not just t because we can't guarantee time_t is 64 bit (yet). - sscanf(str, "@%lld%n", &ll, &len); - if (str[len]=='.') { - str += len+1; - for (len = 0; len<9; len++) { - TT.nano *= 10; - if (isdigit(str[len])) TT.nano += str[len]-'0'; - } - } - if (str[len]) return 1; - *t = ll; - return 0; - } - - // Is it one of the fancy formats? - for (i = 0; i r2)) { - if (year < r1) year += 100; - } else if (year > r1) year -= 100; - tm.tm_year = year + century; - } - } - // Fractional part? - if (*str == '.') { - len = 0; - sscanf(str, ".%u%n", &tm.tm_sec, &len); - str += len; - } else tm.tm_sec = 0; - - // Does that look like a valid date? - check_tm(&tm); - if ((*t = mktime(&tm)) == -1) return 1; - - // Shouldn't be any trailing garbage. - return *str; -} - // Handles any leading `TZ="blah" ` in the input string. -static int parse_date(char *str, time_t *t) +static void parse_date(char *str, time_t *t) { - char *new_tz = NULL, *old_tz; - int result; + char *new_tz = NULL, *old_tz, *s = str; if (!strncmp(str, "TZ=\"", 4)) { // Extract the time zone and skip any whitespace. new_tz = str+4; - str = strchr(new_tz, '"'); - if (!str) return 1; - *str++ = '\0'; - while (isspace(*str)) ++str; + if (!(str = strchr(new_tz, '"'))) xvali_date(0, s); + *str++ = 0; + while (isspace(*str)) str++; // Switch $TZ. old_tz = getenv("TZ"); setenv("TZ", new_tz, 1); tzset(); } - result = parse_formats(str, t); + time(t); + xparsedate(str, t, &TT.nano); if (new_tz) { if (old_tz) setenv("TZ", old_tz, 1); else unsetenv("TZ"); } - return result; } // Print strftime plus %N escape(s). note: modifies fmt for %N @@ -236,10 +130,8 @@ void date_main(void) struct tm tm = {}; char *s = strptime(TT.d, TT.D+(*TT.D=='+'), &tm); - if (!s || *s) goto bad_showdate; - check_tm(&tm); - if ((t = mktime(&tm)) == -1) goto bad_showdate; - } else if (parse_date(TT.d, &t)) goto bad_showdate; + t = (s && *s) ? xvali_date(&tm, s) : xvali_date(0, TT.d); + } else parse_date(TT.d, &t); } else { struct timespec ts; struct stat st; @@ -264,7 +156,7 @@ void date_main(void) } else if (setdate) { struct timeval tv; - if (parse_date(setdate, &t)) goto bad_setdate; + parse_date(setdate, &t); tv.tv_sec = t; tv.tv_usec = TT.nano/1000; if (settimeofday(&tv, NULL) < 0) perror_msg("cannot set date"); @@ -279,9 +171,4 @@ void date_main(void) } return; - -bad_showdate: - setdate = TT.d; -bad_setdate: - error_exit("bad date '%s'", setdate); } -- cgit v1.2.3