Download raw body.
rpki-client: normalize 'buildtime' in the output
Hello,
In some of my analytics pipelines it became a nuisance how outputs from
the same validation run could have slightly different timestamps,
because of slight delays in I/O.
With the below diff the outputs generated from the same validated data
will have the same timestamp, and the modification time on disk will
also reflect this timestamp.
OK?
Kind regards,
Job
Index: ccr.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/ccr.c,v
diff -u -p -r1.26 ccr.c
--- ccr.c 18 Oct 2025 08:12:32 -0000 1.26
+++ ccr.c 30 Oct 2025 19:36:21 -0000
@@ -603,7 +603,6 @@ static CanonicalCacheRepresentation *
generate_ccr(struct validation_data *vd)
{
CanonicalCacheRepresentation *ccr = NULL;
- time_t now = get_current_time();
if ((ccr = CanonicalCacheRepresentation_new()) == NULL)
errx(1, "CanonicalCacheRepresentation_new");
@@ -612,7 +611,7 @@ generate_ccr(struct validation_data *vd)
if ((ccr->hashAlg = OBJ_nid2obj(NID_sha256)) == NULL)
errx(1, "OBJ_nid2obj");
- if (ASN1_GENERALIZEDTIME_set(ccr->producedAt, now) == NULL)
+ if (ASN1_GENERALIZEDTIME_set(ccr->producedAt, vd->buildtime) == NULL)
errx(1, "ASN1_GENERALIZEDTIME_set");
if ((ccr->mfts = generate_manifeststate(vd)) == NULL)
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
diff -u -p -r1.265 extern.h
--- extern.h 16 Oct 2025 06:46:31 -0000 1.265
+++ extern.h 30 Oct 2025 19:36:21 -0000
@@ -512,6 +512,7 @@ struct ccr {
};
struct validation_data {
+ time_t buildtime;
struct vrp_tree vrps;
struct brk_tree brks;
struct vap_tree vaps;
Index: main.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
diff -u -p -r1.300 main.c
--- main.c 17 Oct 2025 08:09:21 -0000 1.300
+++ main.c 30 Oct 2025 19:36:21 -0000
@@ -1553,6 +1553,8 @@ main(int argc, char *argv[])
timespecadd(&stats.system_time, &ts, &stats.system_time);
}
+ vd.buildtime = get_current_time();
+
/* change working directory to the output directory */
if (fchdir(outdirfd) == -1)
err(1, "fchdir output dir");
Index: output-bird.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/output-bird.c,v
diff -u -p -r1.25 output-bird.c
--- output-bird.c 23 Aug 2025 09:13:14 -0000 1.25
+++ output-bird.c 30 Oct 2025 19:36:21 -0000
@@ -25,7 +25,6 @@ output_bird(FILE *out, struct validation
{
struct vrp *v;
struct vap *vap;
- time_t now = get_current_time();
size_t i;
if (fprintf(out, "# For BIRD %s\n#\n", excludeaspa ? "2" : "2.16+") < 0)
@@ -35,7 +34,8 @@ output_bird(FILE *out, struct validation
return -1;
if (fprintf(out, "\ndefine force_roa_table_update = %lld;\n\n"
- "roa4 table ROAS4;\nroa6 table ROAS6;\n", (long long)now) < 0)
+ "roa4 table ROAS4;\nroa6 table ROAS6;\n",
+ (long long)vd->buildtime) < 0)
return -1;
if (!excludeaspa) {
Index: output-json.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/output-json.c,v
diff -u -p -r1.57 output-json.c
--- output-json.c 17 Sep 2025 12:10:08 -0000 1.57
+++ output-json.c 30 Oct 2025 19:36:21 -0000
@@ -28,11 +28,9 @@ outputheader_json(struct validation_data
{
char hn[NI_MAXHOST], tbuf[26];
struct tm *tp;
- time_t t;
int i;
- time(&t);
- tp = gmtime(&t);
+ tp = gmtime(&vd->buildtime);
strftime(tbuf, sizeof tbuf, "%FT%TZ", tp);
gethostname(hn, sizeof hn);
Index: output.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/output.c,v
diff -u -p -r1.42 output.c
--- output.c 23 Aug 2025 09:13:14 -0000 1.42
+++ output.c 30 Oct 2025 19:36:21 -0000
@@ -76,7 +76,7 @@ static const struct outputs {
static FILE *output_createtmp(char *);
static void output_cleantmp(void);
-static int output_finish(FILE *);
+static int output_finish(FILE *, time_t);
static void sig_handler(int);
static void set_signal_handler(void);
@@ -152,7 +152,7 @@ outputfiles(struct validation_data *vd,
rc = 1;
continue;
}
- if (output_finish(fout) != 0) {
+ if (output_finish(fout, vd->buildtime) != 0) {
warn("finish for %s format failed", outputs[i].name);
output_cleantmp();
rc = 1;
@@ -187,12 +187,23 @@ output_createtmp(char *name)
}
static int
-output_finish(FILE *out)
+output_finish(FILE *out, time_t buildtime)
{
+ struct timespec ts[2];
+
if (fclose(out) != 0)
return -1;
+
+ ts[0].tv_nsec = UTIME_OMIT;
+ ts[1].tv_sec = buildtime;
+ ts[1].tv_nsec = 0;
+
+ if (utimensat(AT_FDCWD, output_tmpname, ts, 0) == -1)
+ return -1;
+
if (rename(output_tmpname, output_name) == -1)
return -1;
+
output_tmpname[0] = '\0';
return 0;
}
@@ -243,11 +254,9 @@ outputheader(FILE *out, struct validatio
{
char hn[NI_MAXHOST], tbuf[80];
struct tm *tp;
- time_t t;
int i;
- time(&t);
- tp = gmtime(&t);
+ tp = gmtime(&vd->buildtime);
strftime(tbuf, sizeof tbuf, "%a %b %e %H:%M:%S UTC %Y", tp);
gethostname(hn, sizeof hn);
rpki-client: normalize 'buildtime' in the output