aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xtests/touch.test5
-rw-r--r--toys/posix/touch.c77
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;