The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=393fefa3d9c78948d911e5de0182a9b858b23475
commit 393fefa3d9c78948d911e5de0182a9b858b23475 Author: Mark Johnston <ma...@freebsd.org> AuthorDate: 2025-07-07 20:27:24 +0000 Commit: Mark Johnston <ma...@freebsd.org> CommitDate: 2025-07-07 20:27:24 +0000 mkimg: Make output reproducible using a specific timestamp In commit 95ac5b0e27e9 ("mkimg: Add a reproducible mode"), I added a -R flag to mkimg, indicating that output should be reproducible. There is one place in the VHD image backend that uses time(3) to populate an image metadata field; this field is visible to tools which know how to process VHD images. Rather than picking an arbitrary value for that timestamp, it seems better to behave like makefs(8) and let the invoker pick a suitable timestamp. So, remove -R and instead add a -t option which lets the timestamp be specified directly. Then, modify the VHD backend to use that timestamp. Fixes: 95ac5b0e27e9 ("mkimg: Add a reproducible mode") Reviewed by: bnovkov MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D51077 --- usr.bin/mkimg/mkimg.1 | 8 ++++---- usr.bin/mkimg/mkimg.c | 24 ++++++++++++++++-------- usr.bin/mkimg/mkimg.h | 4 ++-- usr.bin/mkimg/uuid.c | 7 ++++--- usr.bin/mkimg/vhd.c | 2 +- 5 files changed, 27 insertions(+), 18 deletions(-) diff --git a/usr.bin/mkimg/mkimg.1 b/usr.bin/mkimg/mkimg.1 index f6b151d2d5c7..ae48904eb16c 100644 --- a/usr.bin/mkimg/mkimg.1 +++ b/usr.bin/mkimg/mkimg.1 @@ -41,7 +41,7 @@ .Op Fl f Ar format .Op Fl o Ar outfile .Op Fl a Ar active -.Op Fl R +.Op Fl t Ar timestamp .Op Fl v .Op Fl y .Op Fl s Ar scheme Op Fl p Ar partition ... @@ -139,9 +139,9 @@ option is a shorthand to specify the minimum and maximum capacity at the same time. .Pp The -.Fl R -option enables reproducible mode: any timestamps or random identifiers will -be fixed so as to ensure consistent output. +.Fl t +option causes any timestamps embedded in the output file to be set to the +given time, specified in seconds since the epoch. .Pp The .Fl v diff --git a/usr.bin/mkimg/mkimg.c b/usr.bin/mkimg/mkimg.c index c8872ebb1bc6..a7409b686560 100644 --- a/usr.bin/mkimg/mkimg.c +++ b/usr.bin/mkimg/mkimg.c @@ -61,7 +61,8 @@ static struct option longopts[] = { static uint64_t min_capacity = 0; static uint64_t max_capacity = 0; -bool reproducible = false; +/* Fixed timestamp for reproducible builds. */ +time_t timestamp = (time_t)-1; struct partlisthead partlist = TAILQ_HEAD_INITIALIZER(partlist); u_int nparts = 0; @@ -563,7 +564,7 @@ main(int argc, char *argv[]) bcfd = -1; outfd = 1; /* Write to stdout by default */ - while ((c = getopt_long(argc, argv, "a:b:c:C:f:o:p:s:vyH:P:RS:T:", + while ((c = getopt_long(argc, argv, "a:b:c:C:f:o:p:s:t:vyH:P:S:T:", longopts, NULL)) != -1) { switch (c) { case 'a': /* ACTIVE PARTITION, if supported */ @@ -608,9 +609,6 @@ main(int argc, char *argv[]) if (error) errc(EX_DATAERR, error, "partition"); break; - case 'R': - reproducible = true; - break; case 's': /* SCHEME */ if (scheme_selected() != NULL) usage("multiple schemes given"); @@ -618,6 +616,19 @@ main(int argc, char *argv[]) if (error) errc(EX_DATAERR, error, "scheme"); break; + case 't': { + char *ep; + long long val; + + errno = 0; + val = strtoll(optarg, &ep, 0); + if (ep == optarg || *ep != '\0') + errno = EINVAL; + if (errno != 0) + errc(EX_DATAERR, errno, "timestamp"); + timestamp = (time_t)val; + break; + } case 'y': unit_testing++; break; @@ -680,9 +691,6 @@ main(int argc, char *argv[]) if (max_capacity != 0 && min_capacity > max_capacity) usage("minimum capacity cannot be larger than the maximum one"); - if (reproducible) - srandom(42); - if (secsz > blksz) { if (blksz != 0) errx(EX_DATAERR, "the physical block size cannot " diff --git a/usr.bin/mkimg/mkimg.h b/usr.bin/mkimg/mkimg.h index 608de458e83c..aa0ec2a8d944 100644 --- a/usr.bin/mkimg/mkimg.h +++ b/usr.bin/mkimg/mkimg.h @@ -29,9 +29,9 @@ #include <sys/queue.h> #include <sys/types.h> -#include <stdbool.h> +#include <time.h> -extern bool reproducible; /* Generate reproducible output. */ +extern time_t timestamp; struct part { TAILQ_ENTRY(part) link; diff --git a/usr.bin/mkimg/uuid.c b/usr.bin/mkimg/uuid.c index f3415a8c1111..885a6c36b522 100644 --- a/usr.bin/mkimg/uuid.c +++ b/usr.bin/mkimg/uuid.c @@ -57,9 +57,10 @@ osdep_uuidgen(mkimg_uuid_t *uuid) u_int i; uint16_t seq; - if (reproducible) - memset(&tv, 0, sizeof(tv)); - else if (gettimeofday(&tv, NULL) == -1) + if (timestamp != (time_t)-1) { + tv.tv_sec = timestamp; + tv.tv_usec = 0; + } else if (gettimeofday(&tv, NULL) == -1) abort(); time += (uint64_t)tv.tv_sec * 10000000LL; diff --git a/usr.bin/mkimg/vhd.c b/usr.bin/mkimg/vhd.c index 1e1f1e7f3c3e..c0fe45ab416e 100644 --- a/usr.bin/mkimg/vhd.c +++ b/usr.bin/mkimg/vhd.c @@ -188,7 +188,7 @@ vhd_timestamp(void) time_t t; if (!unit_testing) { - t = time(NULL); + t = timestamp != (time_t)-1 ? timestamp : time(NULL); return (t - 0x386d4380); }