date: optional support for %N. Closes bug 1861.
No binary (build failed)
—
(log yok)
| @@ -115,6 +115,13 @@ config FEATURE_DATE_ISOFMT | |
| Enable option (-I) to output an ISO-8601 compliant | |
| date/time string. | |
| + | config FEATURE_DATE_NANO |
| + | bool "Support %[num]N nanosecond format specifier" |
| + | default y |
| + | depends on DATE |
| + | help |
| + | Support %[num]N format specifier. Adds ~250 bytes of code. |
| + | |
| config FEATURE_DATE_COMPAT | |
| bool "Support weird 'date MMDDhhmm[[YY]YY][.ss]' format" | |
| default y | |
| @@ -84,9 +84,9 @@ static const char date_longopts[] ALIGN1 = | |
| int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |
| int date_main(int argc UNUSED_PARAM, char **argv) | |
| { | |
| + | struct timespec ts; |
| struct tm tm_time; | |
| char buf_fmt_dt2str[64]; | |
| - | time_t tm; |
| unsigned opt; | |
| int ifmt = -1; | |
| char *date_str; | |
| @@ -161,11 +161,18 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |
| if (opt & OPT_REFERENCE) { | |
| struct stat statbuf; | |
| xstat(filename, &statbuf); | |
| - | tm = statbuf.st_mtime; |
| + | ts.tv_sec = statbuf.st_mtime; |
| + | #if ENABLE_FEATURE_DATE_NANO |
| + | ts.tv_nsec = statbuf.st_mtimensec; //or st_atim.tv_nsec? |
| + | #endif |
| } else { | |
| - | time(&tm); |
| + | #if ENABLE_FEATURE_DATE_NANO |
| + | clock_gettime(CLOCK_REALTIME, &ts); |
| + | #else |
| + | time(&ts.tv_nsec); |
| + | #endif |
| } | |
| - | localtime_r(&tm, &tm_time); |
| + | localtime_r(&ts.tv_sec, &tm_time); |
| /* If date string is given, update tm_time, and maybe set date */ | |
| if (date_str != NULL) { | |
| @@ -184,12 +191,12 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |
| /* Correct any day of week and day of year etc. fields */ | |
| tm_time.tm_isdst = -1; /* Be sure to recheck dst */ | |
| - | tm = validate_tm_time(date_str, &tm_time); |
| + | ts.tv_sec = validate_tm_time(date_str, &tm_time); |
| maybe_set_utc(opt); | |
| /* if setting time, set it */ | |
| - | if ((opt & OPT_SET) && stime(&tm) < 0) { |
| + | if ((opt & OPT_SET) && stime(&ts.tv_sec) < 0) { |
| bb_perror_msg("can't set date"); | |
| } | |
| } | |
| @@ -222,6 +229,46 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |
| fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y"; | |
| } | |
| } | |
| + | #if ENABLE_FEATURE_DATE_NANO |
| + | else { |
| + | /* User-specified fmt_dt2str */ |
| + | /* Search for and process "%N" */ |
| + | char *p = fmt_dt2str; |
| + | while ((p = strchr(p, '%')) != NULL) { |
| + | int n, m; |
| + | unsigned pres, scale; |
| + | |
| + | p++; |
| + | if (*p == '%') { |
| + | p++; |
| + | continue; |
| + | } |
| + | n = strspn(p, "0123456789"); |
| + | if (p[n] != 'N') { |
| + | p += n; |
| + | continue; |
| + | } |
| + | /* We have "%[nnn]N" */ |
| + | p[-1] = '\0'; |
| + | p[n] = '\0'; |
| + | scale = 1; |
| + | pres = 9; |
| + | if (n) { |
| + | pres = xatoi_u(p); |
| + | if (pres == 0) |
| + | pres = 9; |
| + | m = 9 - pres; |
| + | while (--m >= 0) |
| + | scale *= 10; |
| + | } |
| + | |
| + | m = p - fmt_dt2str; |
| + | p += n + 1; |
| + | fmt_dt2str = xasprintf("%s%0*u%s", fmt_dt2str, pres, (unsigned)ts.tv_nsec / scale, p); |
| + | p = fmt_dt2str + m; |
| + | } |
| + | } |
| + | #endif |
| #define date_buf bb_common_bufsiz1 | |
| if (*fmt_dt2str == '\0') { | |