diff options
-rwxr-xr-x | tests/touch.test | 5 | ||||
-rw-r--r-- | toys/posix/touch.c | 77 |
2 files changed, 39 insertions, 43 deletions
diff --git a/tests/touch.test b/tests/touch.test index d193d7cc..d5bef815 100755 --- a/tests/touch.test +++ b/tests/touch.test @@ -35,6 +35,11 @@ testing "-r" \ "touch -r walrus walrus2 && date -r walrus2 +%s.%N" \ "1234567890.123456789\n" "" "" +# Yes, the year could roll over while you're running this test. I do not care. +testing "-t MMDDhhmm" \ + "touch -t 01231234 input && date +%Y-%m-%d:%H-%M-%S -r input" \ + "$(date +%Y)-01-23:12-34-00\n" "" "" + #testing "-a" #testing "-m" #testing "-am" diff --git a/toys/posix/touch.c b/toys/posix/touch.c index cd7dd53d..79928cee 100644 --- a/toys/posix/touch.c +++ b/toys/posix/touch.c @@ -3,8 +3,6 @@ * Copyright 2012 Choubey Ji <warior.linux@gmail.com> * * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/touch.html - * - * TODO: have another go at merging the -t and -d stanzas USE_TOUCH(NEWTOY(touch, "acd:mr:t:h[!dtr]", TOYFLAG_BIN)) @@ -43,56 +41,49 @@ void touch_main(void) // use current time if no -t or -d ts[0].tv_nsec = UTIME_NOW; if (toys.optflags & (FLAG_t|FLAG_d)) { - char *s, *date; + char *s, *date, **format; struct tm tm; int len = 0; - localtime_r(&(ts->tv_sec), &tm); - - // Set time from -d? + // Initialize default values for time fields + ts->tv_sec = time(0); + ts->tv_nsec = 0; + // List of search types if (toys.optflags & FLAG_d) { + format = (char *[]){"%Y-%m-%dT%T", "%Y-%m-%d %T", 0}; date = TT.date; - i = strlen(date); - if (i) { - // Trailing Z means UTC timezone, don't expect libc to know this. - if (toupper(date[i-1])=='Z') { - date[i-1] = 0; - setenv("TZ", "UTC0", 1); - localtime_r(&(ts->tv_sec), &tm); - } - s = strptime(date, "%Y-%m-%dT%T", &tm); - ts->tv_nsec = 0; - if (s && *s=='.' && isdigit(s[1])) - sscanf(s, ".%lu%n", &ts->tv_nsec, &len); - else len = 0; - } else s = 0; - - // Set time from -t? - } else { - strcpy(toybuf, "%Y%m%d%H%M"); + format = (char *[]){"%Y%m%d%H%M", "%m%d%H%M", "%y%m%d%H%M", 0}; date = TT.time; - i = ((s = strchr(date, '.'))) ? s-date : strlen(date); - if (i < 8 || i%2) error_exit("bad '%s'", date); - for (i=0;i<3;i++) { - s = strptime(date, toybuf+(i&2), &tm); - if (s) break; - toybuf[1]='y'; - } - tm.tm_sec = 0; - ts->tv_nsec = 0; - if (s && *s=='.' && sscanf(s, ".%2u%n", &(tm.tm_sec), &len) == 1) { - if (sscanf(s += len, "%lu%n", &ts->tv_nsec, &len) == 1) { - s--; - len++; - } else len = 0; - } else len = 0; } - if (len) { - s += len; - if (ts->tv_nsec > 999999999) s = 0; - else while (len++ < 10) ts->tv_nsec *= 10; + + // Trailing Z means UTC timezone, don't expect libc to know this. + i = strlen(s = date); + if (i && toupper(date[i-1])=='Z') { + date[i-1] = 0; + setenv("TZ", "UTC0", 1); + } + + while (*format) { + localtime_r(&(ts->tv_sec), &tm); + // Adjusting for daylight savings time gives the wrong answer. + tm.tm_isdst = 0; + tm.tm_sec = 0; + s = strptime(date, *format++, &tm); + + // parse nanoseconds + if (s && *s=='.' && isdigit(s[1])) { + s++; + if (toys.optflags&FLAG_t) + if (1 == sscanf(s, "%2u%n", &(tm.tm_sec), &len)) s += len; + if (1 == sscanf(s, "%lu%n", &ts->tv_nsec, &len)) { + s += len; + if (ts->tv_nsec > 999999999) s = 0; + else while (len++ < 9) ts->tv_nsec *= 10; + } + } + if (s && !*s) break; } errno = 0; |