From c7e300675629f357751157b815200fbbf489dd0c Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune Date: Wed, 21 May 2025 16:23:00 +0200 Subject: [PATCH 1/8] vtim: Harden VTIM_format() prototype This should allow compilers and static analyzers to complain about buffers too small, and this emphasizes the difference between the format and parse operations and how they treat their respective string arguments. --- include/vtim.h | 2 +- lib/libvarnish/vtim.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/vtim.h b/include/vtim.h index 9652238c0cf..75f7a9cbe6f 100644 --- a/include/vtim.h +++ b/include/vtim.h @@ -33,7 +33,7 @@ /* from libvarnish/vtim.c */ extern unsigned VTIM_postel; #define VTIM_FORMAT_SIZE 30 -void VTIM_format(vtim_real t, char *p); +void VTIM_format(vtim_real t, char p[VTIM_FORMAT_SIZE]); vtim_real VTIM_parse(const char *p); vtim_mono VTIM_mono(void); vtim_real VTIM_real(void); diff --git a/lib/libvarnish/vtim.c b/lib/libvarnish/vtim.c index af46aa66524..e023569e763 100644 --- a/lib/libvarnish/vtim.c +++ b/lib/libvarnish/vtim.c @@ -157,7 +157,7 @@ VTIM_real(void) } void -VTIM_format(vtim_real t, char *p) +VTIM_format(vtim_real t, char p[VTIM_FORMAT_SIZE]) { struct tm tm; time_t tt; From 622dd7307dfc386a19d8b650eae7d6d372fb7e6a Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune Date: Wed, 21 May 2025 16:49:31 +0200 Subject: [PATCH 2/8] vtim: Keep track of parsing in a struct --- lib/libvarnish/vtim.c | 88 +++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 33 deletions(-) diff --git a/lib/libvarnish/vtim.c b/lib/libvarnish/vtim.c index e023569e763..4d1f0c85e80 100644 --- a/lib/libvarnish/vtim.c +++ b/lib/libvarnish/vtim.c @@ -179,6 +179,27 @@ VTIM_format(vtim_real t, char p[VTIM_FORMAT_SIZE]) tm.tm_hour, tm.tm_min, tm.tm_sec)); } +struct vtim { + int year; + int month; + int mday; + int weekday; + int hour; + int min; + int sec; +}; + +#define VTIM_INIT(vtim) \ + do { \ + (vtim)->year = 0; \ + (vtim)->month = 0; \ + (vtim)->mday = 0; \ + (vtim)->weekday = -1; \ + (vtim)->hour = 0; \ + (vtim)->min = 0; \ + (vtim)->sec = 0; \ + } while (0) + #ifdef TEST_DRIVER #define FAIL() \ do { printf("\nFAIL <<%d>>\n", __LINE__); return (0); } while (0) @@ -191,7 +212,7 @@ VTIM_format(vtim_real t, char p[VTIM_FORMAT_SIZE]) do { \ if (*p < '0' || *p > '9') \ FAIL(); \ - fld += (*p - '0') * mult; \ + vtim->fld += (*p - '0') * mult; \ p++; \ } while(0) @@ -207,7 +228,7 @@ VTIM_format(vtim_real t, char p[VTIM_FORMAT_SIZE]) int i; \ for (i = 0; i < 7; i++) { \ if (!memcmp(p, weekday_name[i], 3)) { \ - weekday = i; \ + vtim->weekday = i; \ break; \ } \ } \ @@ -222,7 +243,7 @@ VTIM_format(vtim_real t, char p[VTIM_FORMAT_SIZE]) int i; \ for (i = 0; i < 12; i++) { \ if (!memcmp(p, month_name[i], 3)) { \ - month = i + 1; \ + vtim->month = i + 1; \ break; \ } \ } \ @@ -246,9 +267,8 @@ VTIM_format(vtim_real t, char p[VTIM_FORMAT_SIZE]) vtim_real VTIM_parse(const char *p) { + struct vtim vtim[1]; vtim_real t; - int month = 0, year = 0, weekday = -1, mday = 0; - int hour = 0, min = 0, sec = 0; int d, leap; if (p == NULL || *p == '\0') @@ -257,6 +277,8 @@ VTIM_parse(const char *p) while (*p == ' ') p++; + VTIM_INIT(vtim); + if (*p >= '0' && *p <= '9') { /* ISO8601 -- "1994-11-06T08:49:37" */ DIGIT(1000, year); @@ -273,7 +295,7 @@ VTIM_parse(const char *p) TIMESTAMP(); } else { WEEKDAY(); - assert(weekday >= 0 && weekday <= 6); + assert(vtim->weekday >= 0 && vtim->weekday <= 6); if (*p == ',') { /* RFC822 & RFC1123 - "Sun, 06 Nov 1994 08:49:37 GMT" */ p++; @@ -314,10 +336,10 @@ VTIM_parse(const char *p) DIGIT(100, year); DIGIT(10, year); DIGIT(1, year); - } else if (!memcmp(p, more_weekday[weekday], - strlen(more_weekday[weekday]))) { + } else if (!memcmp(p, more_weekday[vtim->weekday], + strlen(more_weekday[vtim->weekday]))) { /* RFC850 -- "Sunday, 06-Nov-94 08:49:37 GMT" */ - p += strlen(more_weekday[weekday]); + p += strlen(more_weekday[vtim->weekday]); MUSTBE(','); MUSTBE(' '); DIGIT(10, mday); @@ -327,9 +349,9 @@ VTIM_parse(const char *p) MUSTBE('-'); DIGIT(10, year); DIGIT(1, year); - year += 1900; - if (year < 1969) - year += 100; + vtim->year += 1900; + if (vtim->year < 1969) + vtim->year += 100; MUSTBE(' '); TIMESTAMP(); MUSTBE(' '); @@ -346,56 +368,56 @@ VTIM_parse(const char *p) if (*p != '\0') FAIL(); - if (sec < 0 || sec > 60) /* Leapseconds! */ + if (vtim->sec < 0 || vtim->sec > 60) /* Leapseconds! */ FAIL(); - if (min < 0 || min > 59) + if (vtim->min < 0 || vtim->min > 59) FAIL(); - if (hour < 0 || hour > 23) + if (vtim->hour < 0 || vtim->hour > 23) FAIL(); - if (month < 1 || month > 12) + if (vtim->month < 1 || vtim->month > 12) FAIL(); - if (mday < 1 || mday > days_in_month[month - 1]) + if (vtim->mday < 1 || vtim->mday > days_in_month[vtim->month - 1]) FAIL(); - if (year < 1899) + if (vtim->year < 1899) FAIL(); - leap = - ((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0); + leap = ((vtim->year) % 4) == 0 && + (((vtim->year) % 100) != 0 || ((vtim->year) % 400) == 0); - if (month == 2 && mday > 28 && !leap) + if (vtim->month == 2 && vtim->mday > 28 && !leap) FAIL(); - if (sec == 60) /* Ignore Leapseconds */ - sec--; + if (vtim->sec == 60) /* Ignore Leapseconds */ + vtim->sec--; - t = ((hour * 60.) + min) * 60. + sec; + t = ((vtim->hour * 60.) + vtim->min) * 60. + vtim->sec; - d = (mday - 1) + days_before_month[month - 1]; + d = (vtim->mday - 1) + days_before_month[vtim->month - 1]; - if (month > 2 && leap) + if (vtim->month > 2 && leap) d++; - d += (year % 100) * 365; /* There are 365 days in a year */ + d += (vtim->year % 100) * 365; /* There are 365 days in a year */ - if ((year % 100) > 0) /* And a leap day every four years */ - d += (((year % 100) - 1) / 4); + if ((vtim->year % 100) > 0) /* And a leap day every four years */ + d += (((vtim->year % 100) - 1) / 4); - d += ((year / 100) - 20) * /* Days relative to y2000 */ + d += ((vtim->year / 100) - 20) * /* Days relative to y2000 */ (100 * 365 + 24); /* 24 leapdays per year in a century */ - d += ((year - 1) / 400) - 4; /* And one more every 400 years */ + d += ((vtim->year - 1) / 400) - 4; /* One more every 400 years */ /* * Now check weekday, if we have one. * 6 is because 2000-01-01 was a saturday. * 10000 is to make sure the modulus argument is always positive */ - if (weekday != -1 && (d + 6 + 7 * 10000) % 7 != weekday) + if (vtim->weekday != -1 && (d + 6 + 7 * 10000) % 7 != vtim->weekday) FAIL(); t += d * 86400.; - t += 10957. * 86400.; /* 10957 days frm UNIX epoch to y2000 */ + t += 10957. * 86400.; /* 10957 days frm UNIX epoch to y2000 */ return (t); } From 5d6cdae176d1f5890b9c309047bf158a0020ed0d Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune Date: Wed, 21 May 2025 17:00:35 +0200 Subject: [PATCH 3/8] vtim: Extract HTTP time parsing in two functions The only effective change is the optional white space relying on the OWS syntax (SP / HTAB) from the HTTP grammar instead of SP only. --- lib/libvarnish/vtim.c | 54 +++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/lib/libvarnish/vtim.c b/lib/libvarnish/vtim.c index 4d1f0c85e80..2e4a121d276 100644 --- a/lib/libvarnish/vtim.c +++ b/lib/libvarnish/vtim.c @@ -71,6 +71,7 @@ #include "vdef.h" #include "vas.h" +#include "vct.h" #include "vtim.h" /* relax vtim parsing */ @@ -264,21 +265,16 @@ struct vtim { DIGIT(1, sec); \ } while(0) -vtim_real -VTIM_parse(const char *p) +static unsigned +vtim_parse_http(struct vtim *vtim, const char **pp) { - struct vtim vtim[1]; - vtim_real t; - int d, leap; + const char *p; - if (p == NULL || *p == '\0') + AN(pp); + p = *pp; + if (*p == '\0') FAIL(); - while (*p == ' ') - p++; - - VTIM_INIT(vtim); - if (*p >= '0' && *p <= '9') { /* ISO8601 -- "1994-11-06T08:49:37" */ DIGIT(1000, year); @@ -362,11 +358,15 @@ VTIM_parse(const char *p) FAIL(); } - while (*p == ' ') - p++; + *pp = p; + return (1); +} - if (*p != '\0') - FAIL(); +static vtim_real +vtim_calc(struct vtim *vtim) +{ + vtim_real t; + int d, leap; if (vtim->sec < 0 || vtim->sec > 60) /* Leapseconds! */ FAIL(); @@ -422,6 +422,30 @@ VTIM_parse(const char *p) return (t); } +vtim_real +VTIM_parse(const char *p) +{ + struct vtim vtim[1]; + + if (p == NULL) + FAIL(); + + while (vct_isows(*p)) + p++; + + VTIM_INIT(vtim); + if (!vtim_parse_http(vtim, &p)) + FAIL(); + + while (vct_isows(*p)) + p++; + + if (*p != '\0') + FAIL(); + + return (vtim_calc(vtim)); +} + void VTIM_sleep(vtim_dur t) { From 285ea5ed11fc6df788026e25f3943d7ecdb762d1 Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune Date: Wed, 21 May 2025 17:09:00 +0200 Subject: [PATCH 4/8] vtim: Keep track of the fraction of a second --- lib/libvarnish/vtim.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/libvarnish/vtim.c b/lib/libvarnish/vtim.c index 2e4a121d276..72c24ece523 100644 --- a/lib/libvarnish/vtim.c +++ b/lib/libvarnish/vtim.c @@ -188,6 +188,7 @@ struct vtim { int hour; int min; int sec; + double frac; }; #define VTIM_INIT(vtim) \ @@ -199,6 +200,7 @@ struct vtim { (vtim)->hour = 0; \ (vtim)->min = 0; \ (vtim)->sec = 0; \ + (vtim)->frac = 0; \ } while (0) #ifdef TEST_DRIVER @@ -419,6 +421,11 @@ vtim_calc(struct vtim *vtim) t += 10957. * 86400.; /* 10957 days frm UNIX epoch to y2000 */ + assert(vtim->frac >= 0); + assert(vtim->frac < 1); + + t += vtim->frac; + return (t); } From 051940134079a6a344a8654d7c2ffcb2c95a48e9 Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune Date: Wed, 21 May 2025 17:39:20 +0200 Subject: [PATCH 5/8] vtim: Parse "web" timestamps As per an old recommendation on date-time formatting for better interoperability. This format also has the convenient property of being chronologically sorted. --- bin/varnishd/mgt/mgt_main.c | 1 + include/vtim.h | 1 + lib/libvarnish/vtim.c | 131 +++++++++++++++++++++++++++++++++++- 3 files changed, 132 insertions(+), 1 deletion(-) diff --git a/bin/varnishd/mgt/mgt_main.c b/bin/varnishd/mgt/mgt_main.c index 933a9d93a63..1bdc53d5fb6 100644 --- a/bin/varnishd/mgt/mgt_main.c +++ b/bin/varnishd/mgt/mgt_main.c @@ -344,6 +344,7 @@ mgt_tests(void) assert(VTIM_parse("Sun, 06 Nov 1994 08:49:37 GMT") == 784111777); assert(VTIM_parse("Sunday, 06-Nov-94 08:49:37 GMT") == 784111777); assert(VTIM_parse("Sun Nov 6 08:49:37 1994") == 784111777); + assert(VTIM_parse_web("1994-11-06T08:49:37.00Z") == 784111777); /* Check that our VSHA256 works */ VSHA256_Test(); diff --git a/include/vtim.h b/include/vtim.h index 75f7a9cbe6f..8b637d32f5f 100644 --- a/include/vtim.h +++ b/include/vtim.h @@ -35,6 +35,7 @@ extern unsigned VTIM_postel; #define VTIM_FORMAT_SIZE 30 void VTIM_format(vtim_real t, char p[VTIM_FORMAT_SIZE]); vtim_real VTIM_parse(const char *p); +vtim_real VTIM_parse_web(const char *p); vtim_mono VTIM_mono(void); vtim_real VTIM_real(void); void VTIM_sleep(vtim_dur t); diff --git a/lib/libvarnish/vtim.c b/lib/libvarnish/vtim.c index 72c24ece523..c1d94d9fb3c 100644 --- a/lib/libvarnish/vtim.c +++ b/lib/libvarnish/vtim.c @@ -213,7 +213,7 @@ struct vtim { #define DIGIT(mult, fld) \ do { \ - if (*p < '0' || *p > '9') \ + if (!vct_isdigit(*p)) \ FAIL(); \ vtim->fld += (*p - '0') * mult; \ p++; \ @@ -267,6 +267,24 @@ struct vtim { DIGIT(1, sec); \ } while(0) +#define OPT_DIGIT(mult, fld) \ + if (!vct_isdigit(*p)) \ + break; \ + DIGIT(mult, fld) + +#define FRAC() \ + do { \ + DIGIT(0.1, frac); \ + OPT_DIGIT(0.01, frac); \ + OPT_DIGIT(0.001, frac); \ + OPT_DIGIT(0.0001, frac); \ + OPT_DIGIT(0.00001, frac); \ + OPT_DIGIT(0.000001, frac); \ + OPT_DIGIT(0.0000001, frac); \ + OPT_DIGIT(0.00000001, frac); \ + OPT_DIGIT(0.000000001, frac); \ + } while (0) + static unsigned vtim_parse_http(struct vtim *vtim, const char **pp) { @@ -453,6 +471,98 @@ VTIM_parse(const char *p) return (vtim_calc(vtim)); } +vtim_real +VTIM_parse_web(const char *p) +{ + struct vtim vtim[1]; + vtim_real t; + char sign; + + if (*p == '\0') + FAIL(); + + /* Parse date-time syntax from RFC3339's grammar: + * + * YYYY-MM-DDThh:mm:ss[.s]TZD + * + * The components are described in the W3C's Date and Time Formats + * note: + * + * YYYY = four-digit year + * MM = two-digit month (01=January, etc) + * DD = two-digit day of month (01 through 31) + * T = the character 'T' + * hh = two digits of hour (00 through 23, am/pm NOT allowed) + * mm = two digits of minute (00 through 59) + * ss = two digits of second (00 through 59) + * s = one or more digits for the decimal fraction of a second + * TZD = time zone designator (Z or +hh:mm or -hh:mm) + * Z = the character 'Z' + * + * https://www.w3.org/TR/1998/NOTE-datetime-19980827 + * + * In this note only the uppercase letters T and Z are valid, and + * RFC3339 allows such a restriction. + */ + + VTIM_INIT(vtim); + + DIGIT(1000, year); + DIGIT(100, year); + DIGIT(10, year); + DIGIT(1, year); + MUSTBE('-'); + DIGIT(10, month); + DIGIT(1, month); + MUSTBE('-'); + DIGIT(10, mday); + DIGIT(1, mday); + MUSTBE('T'); + TIMESTAMP(); + + if (vtim->sec == 60) + FAIL(); + + if (*p == '.') { + p++; + FRAC(); + } + + t = vtim_calc(vtim); + if (t == 0) + FAIL(); + + if (*p == 'Z') { + p++; + } else { + sign = *p; + if (sign != '-' && sign != '+') + FAIL(); + p++; + VTIM_INIT(vtim); + DIGIT(10, hour); + DIGIT(1, hour); + MUSTBE(':'); + DIGIT(10, min); + DIGIT(1, min); + if (vtim->hour > 23) + FAIL(); + if (vtim->min > 59) + FAIL(); + if (sign == '-') { + vtim->hour = -vtim->hour; + vtim->min = -vtim->min; + } + t += vtim->hour * 3600; + t += vtim->min * 60; + } + + if (*p != '\0') + FAIL(); + + return (t); +} + void VTIM_sleep(vtim_dur t) { @@ -529,6 +639,22 @@ tst(const char *s, time_t good) } } +static void +tst_web(const char *s, vtim_real good) +{ + vtim_real t; + char buf[BUFSIZ]; + + t = VTIM_parse_web(s); + VTIM_format(t, buf); + printf("%-30s -> %12.2f -> %s\n", s, t, buf); + if (t != good) { + printf("Parse error! Got: %f should have %f diff %f\n", + t, good, t - good); + exit(4); + } +} + /* XXX keep as double for the time being */ static int tst_delta_check(const char *name, double begin, double end, vtim_dur ref) @@ -689,6 +815,9 @@ main(int argc, char **argv) tst("1994-11-06T08:49:37", 784111777); + tst_web("1994-11-06T08:49:37.25Z", 784111777.25); + tst_web("1994-11-06T08:49:37.25+01:00", 784115377.25); + tst_delta(); return (0); From cbc194fd32745ff6fef82426d8c6e287262022bd Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune Date: Wed, 21 May 2025 18:30:09 +0200 Subject: [PATCH 6/8] vtim: Format "web" timestamps up to the microsecond --- include/vtim.h | 2 ++ lib/libvarnish/vtim.c | 49 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/include/vtim.h b/include/vtim.h index 8b637d32f5f..16b988b42a6 100644 --- a/include/vtim.h +++ b/include/vtim.h @@ -34,6 +34,8 @@ extern unsigned VTIM_postel; #define VTIM_FORMAT_SIZE 30 void VTIM_format(vtim_real t, char p[VTIM_FORMAT_SIZE]); +#define VTIM_FORMAT_WEB_SIZE (sizeof "2025-12-31T23:59:59.123456Z") +void VTIM_format_web(vtim_real t, char p[VTIM_FORMAT_WEB_SIZE]); vtim_real VTIM_parse(const char *p); vtim_real VTIM_parse_web(const char *p); vtim_mono VTIM_mono(void); diff --git a/lib/libvarnish/vtim.c b/lib/libvarnish/vtim.c index c1d94d9fb3c..b31cfd1ef67 100644 --- a/lib/libvarnish/vtim.c +++ b/lib/libvarnish/vtim.c @@ -72,6 +72,7 @@ #include "vas.h" #include "vct.h" +#include "vsb.h" #include "vtim.h" /* relax vtim parsing */ @@ -180,6 +181,47 @@ VTIM_format(vtim_real t, char p[VTIM_FORMAT_SIZE]) tm.tm_hour, tm.tm_min, tm.tm_sec)); } +void +VTIM_format_web(vtim_real t, char p[VTIM_FORMAT_WEB_SIZE]) +{ + char buf[sizeof "0.123456"], *z; + struct vsb vsb[1]; + struct tm tm; + time_t tt; + double frac, i; + + AN(p); + *p = '\0'; + + if (t < (vtim_real)INTMAX_MIN || t > (vtim_real)INTMAX_MAX) + return; + + tt = (time_t)(intmax_t)t; + if (gmtime_r(&tt, &tm) == NULL) + return; + + AN(VSB_init(vsb, p, VTIM_FORMAT_WEB_SIZE)); + VSB_printf(vsb, "%04d-%02d-%02dT%02d:%02d:%02d", + tm.tm_year + 1900, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + + frac = modf(t, &i); + if (frac >= 1e-6) { + bprintf(buf, "%0.6f", frac); + z = buf + sizeof buf - 2; + while (*z == '0') { + *z = '\0'; + z--; + } + if (*z != '.') + VSB_cat(vsb, buf + 1); + } + + VSB_putc(vsb, 'Z'); + AZ(VSB_finish(vsb)); + VSB_fini(vsb); +} + struct vtim { int year; int month; @@ -627,7 +669,7 @@ static void tst(const char *s, time_t good) { time_t t; - char buf[BUFSIZ]; + char buf[VTIM_FORMAT_SIZE]; t = VTIM_parse(s); VTIM_format(t, buf); @@ -643,10 +685,10 @@ static void tst_web(const char *s, vtim_real good) { vtim_real t; - char buf[BUFSIZ]; + char buf[VTIM_FORMAT_WEB_SIZE]; t = VTIM_parse_web(s); - VTIM_format(t, buf); + VTIM_format_web(t, buf); printf("%-30s -> %12.2f -> %s\n", s, t, buf); if (t != good) { printf("Parse error! Got: %f should have %f diff %f\n", @@ -817,6 +859,7 @@ main(int argc, char **argv) tst_web("1994-11-06T08:49:37.25Z", 784111777.25); tst_web("1994-11-06T08:49:37.25+01:00", 784115377.25); + tst_web("1994-11-06T08:49:37.123456+01:00", 784115377.123456); tst_delta(); From 2183e90b80e77b4380e39807dd136d924c4976f2 Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune Date: Wed, 25 Jun 2025 14:42:06 +0200 Subject: [PATCH 7/8] SQUASHME: relax vtim_test to millisecond precision Just to be safe, even though this is currently working fine with the handful of test cases. Spotted by @daghf. --- lib/libvarnish/vtim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libvarnish/vtim.c b/lib/libvarnish/vtim.c index b31cfd1ef67..8f9dc40e1b3 100644 --- a/lib/libvarnish/vtim.c +++ b/lib/libvarnish/vtim.c @@ -690,7 +690,7 @@ tst_web(const char *s, vtim_real good) t = VTIM_parse_web(s); VTIM_format_web(t, buf); printf("%-30s -> %12.2f -> %s\n", s, t, buf); - if (t != good) { + if (fabs(t - good) > 0.001) { printf("Parse error! Got: %f should have %f diff %f\n", t, good, t - good); exit(4); From c68bd83dfb7709d45a32caf1ddc1f1b26e682599 Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune Date: Wed, 25 Jun 2025 14:58:26 +0200 Subject: [PATCH 8/8] DRAFT: ban: Print web timestamps in ban.list --- bin/varnishd/cache/cache_ban.c | 10 ++++++++-- bin/varnishtest/tests/c00019.vtc | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bin/varnishd/cache/cache_ban.c b/bin/varnishd/cache/cache_ban.c index 77d7ed96f29..9760294d5d3 100644 --- a/bin/varnishd/cache/cache_ban.c +++ b/bin/varnishd/cache/cache_ban.c @@ -42,6 +42,7 @@ #include "vcli_serve.h" #include "vend.h" #include "vmb.h" +#include "vtim.h" /* cache_ban_build.c */ void BAN_Build_Init(void); @@ -848,13 +849,16 @@ ban_render(struct cli *cli, const uint8_t *bs, int quote) static void ban_list(struct cli *cli, struct ban *bl) { + char ts[VTIM_FORMAT_WEB_SIZE]; struct ban *b; int64_t o; VCLI_Out(cli, "Present bans:\n"); VTAILQ_FOREACH(b, &ban_head, list) { o = bl == b ? 1 : 0; - VCLI_Out(cli, "%10.6f %5ju %s", ban_time(b->spec), + VTIM_format_web(ban_time(b->spec), ts); + VCLI_Out(cli, "%-*s %5ju %s", + (int)VTIM_FORMAT_WEB_SIZE, ts, (intmax_t)(b->refcount - o), b->flags & BANS_FLAG_COMPLETED ? "C" : "-"); if (DO_DEBUG(DBG_LURKER)) { @@ -881,6 +885,7 @@ ban_list(struct cli *cli, struct ban *bl) static void ban_list_json(struct cli *cli, const char * const *av, struct ban *bl) { + char ts[VTIM_FORMAT_WEB_SIZE]; struct ban *b; int64_t o; int n = 0; @@ -894,7 +899,8 @@ ban_list_json(struct cli *cli, const char * const *av, struct ban *bl) n++; VCLI_Out(cli, "{\n"); VSB_indent(cli->sb, 2); - VCLI_Out(cli, "\"time\": %.6f,\n", ban_time(b->spec)); + VTIM_format_web(ban_time(b->spec), ts); + VCLI_Out(cli, "\"time\": \"%s\",\n", ts); VCLI_Out(cli, "\"refs\": %ju,\n", (intmax_t)(b->refcount - o)); VCLI_Out(cli, "\"completed\": %s,\n", b->flags & BANS_FLAG_COMPLETED ? "true" : "false"); diff --git a/bin/varnishtest/tests/c00019.vtc b/bin/varnishtest/tests/c00019.vtc index 9c8bd4e559f..dd40a35f4af 100644 --- a/bin/varnishtest/tests/c00019.vtc +++ b/bin/varnishtest/tests/c00019.vtc @@ -92,5 +92,5 @@ varnish v1 -clierr 106 "ban req.url ~ [[[" # Ban expression with quoting varnish v1 -cliok {ban req.url ~ "BAR"} shell {varnishadm -n ${tmpdir}/v1 ban 'obj.http.Host ~ \"Foo\"'} -varnish v1 -cliexpect {(?s)\d+\.\d+\s+\d+\s+-\s+\Qobj.http.Host ~ "Foo"\E} "ban.list" +varnish v1 -cliexpect {(?s)\S+\s+\d+\s+-\s+\Qobj.http.Host ~ "Foo"\E} "ban.list" varnish v1 -clijson "ban.list -j"