summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2022-03-13 15:00:32 -0400
committerJakob Kaivo <jkk@ung.org>2022-03-13 15:00:32 -0400
commit65cf227c67e1b293d7beb0ef3ecef50ad5223be8 (patch)
tree31d6fad4efaac74536ea7074310836c9384c529d
parent19eb24378a5e7eec6e1022ef07f422033c6623db (diff)
implement most of -d date parsing
-rw-r--r--touch.c105
1 files changed, 70 insertions, 35 deletions
diff --git a/touch.c b/touch.c
index 05dd721..06d0e69 100644
--- a/touch.c
+++ b/touch.c
@@ -64,20 +64,19 @@ static int touch(const char *path, struct timespec times[2], int create)
return 0;
}
-static int twodigits(const char *s)
+static int twodigits(const char *s, int min, int max)
{
char buf[3] = { s[0], s[1], '\0' };
if (!(isdigit(buf[0]) && isdigit(buf[1]))) {
- return -1;
+ fprintf(stderr, "touch: invalid time\n");
+ exit(1);
}
- return atoi(buf);
-}
-
-static struct timespec convert_date(const char *date)
-{
- (void)date;
- struct timespec ts = { 0 };
- return ts;
+ int ret = atoi(buf);
+ if (ret < min || ret > max) {
+ fprintf(stderr, "touch: invalid time\n");
+ exit(1);
+ }
+ return ret;
}
static struct timespec convert_time(const char *date)
@@ -92,53 +91,41 @@ static struct timespec convert_time(const char *date)
char *dot = strchr(date, '.');
if (dot) {
if (strlen(dot + 1) != 2) {
- fprintf(stderr, "invalid time %s\n", date);
+ fprintf(stderr, "invalid time\n");
exit(1);
}
- /* TODO: 00 - 60 */
- tm->tm_sec = twodigits(dot + 1);
+ tm->tm_sec = twodigits(dot + 1, 0, 60);
} else {
tm->tm_sec = 0;
}
switch (strlen(date) - (dot ? 3 : 0)) {
- case 12:
- century = twodigits(date) - 19;
+ case 12: /* CC */
+ century = twodigits(date, 0, 100) - 19;
date += 2;
/* FALLTHRU */
- case 10:
- /* TODO: 00 - 99 */
+ case 10: /* YY */
if (century == -1) {
- tm->tm_year = twodigits(date);
+ tm->tm_year = twodigits(date, 0, 100);
if (00 <= tm->tm_year && tm->tm_year <= 68) {
tm->tm_year += 100;
}
} else {
- tm->tm_year = (century * 100) + twodigits(date);
+ tm->tm_year = (century * 100) + twodigits(date, 0, 100);
}
date += 2;
/* FALLTHRU */
- case 8:
- /* TODO: 01 - 12 */
- tm->tm_mon = twodigits(date) - 1;
+ case 8: /* MM */
+ tm->tm_mon = twodigits(date, 1, 12) - 1;
date += 2;
- /* FALLTHRU */
- case 6:
- /* TODO: 01 - 31 */
- tm->tm_mday = twodigits(date);
+ tm->tm_mday = twodigits(date, 1, 31);
date += 2;
- /* FALLTHRU */
- case 4:
- /* TODO: 00 - 23 */
- tm->tm_hour = twodigits(date);
+ tm->tm_hour = twodigits(date, 0, 23);
date += 2;
- /* FALLTHRU */
- case 2:
- /* TODO: 00 - 59 */
- tm->tm_min = twodigits(date);
+ tm->tm_min = twodigits(date, 0, 59);
break;
default:
- fprintf(stderr, "invalide time %s\n", date);
+ fprintf(stderr, "invalid time\n");
exit(1);
}
@@ -150,6 +137,54 @@ static struct timespec convert_time(const char *date)
return ts;
}
+static int getnext(const char *current, char **next, size_t ndigits, char *term, int min, int max)
+{
+ char buf[ndigits + 1];
+ for (size_t i = 0; i < ndigits; i++) {
+ if (!isdigit(current[i])) {
+ return -1;
+ }
+ buf[i] = current[i];
+ }
+ buf[ndigits] = '\0';
+
+ char *end = NULL;
+ long ret = strtol(buf, &end, 10);
+ if (!strchr(term, *end)) {
+ fprintf(stderr, "touch: invalid date\n");
+ exit(1);
+ }
+ if (ret < min || ret > max) {
+ fprintf(stderr, "touch: invalid date\n");
+ exit(1);
+ }
+
+ *next = (char*)current + ndigits + 1;
+ return ret;
+}
+
+static struct timespec convert_date(const char *date)
+{
+ struct timespec ts = { 0 };
+ struct tm tm = { 0 };
+ char *next = (char*)date;
+
+ tm.tm_year = getnext(next, &next, 4, "-", 0, 10000) - 1900;
+ tm.tm_mon = getnext(next, &next, 2, "-", 1, 12) - 1;
+ tm.tm_mday = getnext(next, &next, 2, "T ", 1, 31);
+ tm.tm_hour = getnext(next, &next, 2, ":", 0, 23);
+ tm.tm_min = getnext(next, &next, 2, ":", 0, 59);
+ tm.tm_sec = getnext(next, &next, 2, ".,", 0, 60);
+
+ /* TODO: frac */
+ /* TODO: tz */
+ /* TODO: time is too large */
+
+ ts.tv_sec = mktime(&tm);
+
+ return ts;
+}
+
int main(int argc, char *argv[])
{
setlocale(LC_ALL, "");