Index: sbin/gpt/gpt.c =================================================================== RCS file: /cvsroot/src/sbin/gpt/gpt.c,v retrieving revision 1.89 diff -p -u -r1.89 gpt.c --- sbin/gpt/gpt.c 10 Jun 2024 09:17:29 -0000 1.89 +++ sbin/gpt/gpt.c 13 Sep 2024 11:42:57 -0000 @@ -495,6 +495,7 @@ gpt_open(const char *dev, int flags, int gpt->mediasz = mediasz; gpt->secsz = secsz; gpt->timestamp = timestamp; + gpt->uuidgen = 0; mode = (gpt->flags & GPT_READONLY) ? O_RDONLY : O_RDWR|O_EXCL; Index: sbin/gpt/gpt_private.h =================================================================== RCS file: /cvsroot/src/sbin/gpt/gpt_private.h,v retrieving revision 1.3 diff -p -u -r1.3 gpt_private.h --- sbin/gpt/gpt_private.h 30 Jun 2019 11:38:16 -0000 1.3 +++ sbin/gpt/gpt_private.h 13 Sep 2024 11:42:57 -0000 @@ -31,6 +31,7 @@ #include #include +#include #include struct gpt { @@ -44,5 +45,6 @@ struct gpt { u_int secsz; off_t mediasz; time_t timestamp; + u_int uuidgen; struct stat sb; }; Index: sbin/gpt/gpt_uuid.c =================================================================== RCS file: /cvsroot/src/sbin/gpt/gpt_uuid.c,v retrieving revision 1.22 diff -p -u -r1.22 gpt_uuid.c --- sbin/gpt/gpt_uuid.c 19 Aug 2024 17:15:38 -0000 1.22 +++ sbin/gpt/gpt_uuid.c 13 Sep 2024 11:42:57 -0000 @@ -272,7 +272,7 @@ gpt_uuid_create(gpt_type_t t, gpt_uuid_t } static int -gpt_uuid_random(gpt_t gpt, void *v, size_t n) +gpt_uuid_random(gpt_t gpt, struct dce_uuid *u, size_t n) { int fd; uint8_t *p; @@ -284,7 +284,7 @@ gpt_uuid_random(gpt_t gpt, void *v, size gpt_warn(gpt, "Can't open `/dev/urandom'"); return -1; } - for (p = v; n > 0; p += nread, n -= (size_t)nread) { + for (p = (uint8_t *)u; n > 0; p += nread, n -= (size_t)nread) { nread = read(fd, p, n); if (nread < 0) { gpt_warn(gpt, "Can't read `/dev/urandom'"); @@ -300,21 +300,59 @@ gpt_uuid_random(gpt_t gpt, void *v, size } } (void)close(fd); + + /* Set the version number to 4. */ + u->time_hi_and_version &= (uint16_t)~0xf000; + u->time_hi_and_version |= 0x4000; + return 0; out: (void)close(fd); return -1; } +/* + * For reproducable builds, we can base UUIDs on one external timestamp. + * + * Bump timestamp by one 100ns unit to make them unique within a GPT. + * Use zero clock sequence and node id, ideally these should also be + * passed as input. + */ static int -gpt_uuid_tstamp(gpt_t gpt, void *v, size_t l) +gpt_uuid_tstamp(gpt_t gpt, struct dce_uuid *u, size_t l) { - uint8_t *p; - // Perhaps use SHA? - uint32_t x = (uint32_t)gpt->timestamp; + uint64_t x; - for (p = v; l > 0; p += sizeof(x), l -= sizeof(x)) - memcpy(p, &x, sizeof(x)); + /* check for underflow/overflow of 60bit UUID time */ + if (gpt->timestamp < -12219292800 || + gpt->timestamp > 103072857660) + return -1; + + /* + * Convert to UUID epoch (Gregorian) + * and 100ns units + */ + x = (uint64_t)(gpt->timestamp + 12219292800) * 10000000; + + /* Make UUID unique */ + x += gpt->uuidgen++; + + /* Set UUID fields for version 1 */ + u->time_low = x & 0xffffffff; + u->time_mid = (x >> 32) & 0xffff; + u->time_hi_and_version = 0x1000 | ((x >> 48) & 0xfff); + + /* + * The clock sequence should make UUIDs unique in case + * the clock went backwards. + */ + u->clock_seq_hi_and_reserved = 0; + u->clock_seq_low = 0; + + /* + * A unique system identifier (usually MAC address) + */ + memset(u->node, 0, sizeof(u->node)); return 0; } @@ -324,6 +362,7 @@ gpt_uuid_generate(gpt_t gpt, gpt_uuid_t { int rv; struct dce_uuid u; + if (gpt && (gpt->flags & GPT_TIMESTAMP)) rv = gpt_uuid_tstamp(gpt, &u, sizeof(u)); else @@ -332,10 +371,6 @@ gpt_uuid_generate(gpt_t gpt, gpt_uuid_t if (rv == -1) return -1; - /* Set the version number to 4. */ - u.time_hi_and_version &= (uint16_t)~0xf000; - u.time_hi_and_version |= 0x4000; - /* Fix the reserved bits. */ u.clock_seq_hi_and_reserved &= (uint8_t)~0x40; u.clock_seq_hi_and_reserved |= 0x80; Index: sbin/gpt/uuid.c =================================================================== RCS file: /cvsroot/src/sbin/gpt/uuid.c,v retrieving revision 1.2 diff -p -u -r1.2 uuid.c --- sbin/gpt/uuid.c 19 Aug 2024 17:15:38 -0000 1.2 +++ sbin/gpt/uuid.c 13 Sep 2024 11:42:57 -0000 @@ -65,26 +65,34 @@ struct gpt_cmd c_uuid = { #define usage() gpt_usage(NULL, &c_uuid) +struct uuidctx { + gpt_t gpt; + gpt_uuid_t *uuid; +}; + static void change_ent(struct gpt_ent *ent, void *v, int backup) { + struct uuidctx *ctx = v; static gpt_uuid_t uuidstore; - if (v != NULL) { - memcpy(uuidstore, v, sizeof(uuidstore)); + if (!backup) { + if (ctx->uuid != NULL) + memcpy(uuidstore, ctx->uuid, sizeof(uuidstore)); + else + gpt_uuid_generate(ctx->gpt, uuidstore); } - else if (!backup) - gpt_uuid_generate(NULL, uuidstore); memmove(ent->ent_guid, uuidstore, sizeof(ent->ent_guid)); } static void change_hdr(struct gpt_hdr *hdr, void *v, int backup) { + struct uuidctx *ctx = v; static gpt_uuid_t uuidstore; if (!backup) - gpt_uuid_generate(NULL, uuidstore); + gpt_uuid_generate(ctx->gpt, uuidstore); memmove(hdr->hdr_guid, uuidstore, sizeof(hdr->hdr_guid)); } @@ -94,7 +102,7 @@ cmd_uuid(gpt_t gpt, int argc, char *argv int ch, rc; struct gpt_find find; gpt_uuid_t new_uuid; - void *v; + struct uuidctx ctx; if (gpt == NULL) return usage(); @@ -103,13 +111,14 @@ cmd_uuid(gpt_t gpt, int argc, char *argv find.msg = "UUID changed"; /* Get the uuid options */ - v = NULL; + ctx.gpt = gpt; + ctx.uuid = NULL; while ((ch = getopt(argc, argv, GPT_FIND "U:")) != -1) { switch (ch) { case 'U': if (gpt_uuid_parse(optarg, new_uuid) == -1) return usage(); - v = new_uuid; + ctx.uuid = &new_uuid; break; default: if (gpt_add_find(gpt, &find, ch) == -1) @@ -121,12 +130,12 @@ cmd_uuid(gpt_t gpt, int argc, char *argv if (argc != optind) return usage(); - rc = gpt_change_ent(gpt, &find, change_ent, v); + rc = gpt_change_ent(gpt, &find, change_ent, &ctx); if (rc != 0) return rc; if (find.all) - return gpt_change_hdr(gpt, &find, change_hdr, NULL); + return gpt_change_hdr(gpt, &find, change_hdr, &ctx); return 0; }