diff --git a/bin/uuidgen/uuidgen.1 b/bin/uuidgen/uuidgen.1 index f793fb248cdf..83326e3a189a 100644 --- a/bin/uuidgen/uuidgen.1 +++ b/bin/uuidgen/uuidgen.1 @@ -1,83 +1,86 @@ .\" Copyright (c) 2002 Marcel Moolenaar .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" $FreeBSD$ .\" .Dd May 23, 2012 .Dt UUIDGEN 1 .Os .Sh NAME .Nm uuidgen .Nd generate universally unique identifiers .Sh SYNOPSIS .Nm .Op Fl 1 +.Op Fl r .Op Fl n Ar count .Op Fl o Ar filename .Sh DESCRIPTION The .Nm utility by default generates a single DCE version 1 universally unique identifier (UUID), also known as a globally unique identifier (GUID). The UUID is written to stdout by default. The following options can be used to change the behaviour of .Nm : .Bl -tag -width indent .It Fl 1 This option only has effect if multiple identifiers are to be generated and instructs .Nm to not generate them in batch, but one at a time. +.It Fl r +This option controls creation of random UUID (version 4). .It Fl n This option controls the number of identifiers generated. By default, multiple identifiers are generated in batch. The upper hard limit is 2048 .Po see .Xr uuidgen 2 .Pc . .It Fl o Redirect output to .Ar filename instead of stdout. .El .Pp Batched generation yields a dense set of identifiers in such a way that there is no identifier that is larger than the smallest identifier in the set and smaller than the largest identifier in the set and that is not already in the set. .Pp When generating the identifiers one at a time, the identifiers will be close to each other, but operating system latency and processing time will be reflected in the distance between two successive identifiers. .Sh EXIT STATUS .Ex -std .Sh SEE ALSO .Xr uuidgen 2 , .Xr uuid 3 .Sh HISTORY The .Nm command first appeared in .Fx 5.0 . diff --git a/bin/uuidgen/uuidgen.c b/bin/uuidgen/uuidgen.c index e135dfc4b6e0..061907f57109 100644 --- a/bin/uuidgen/uuidgen.c +++ b/bin/uuidgen/uuidgen.c @@ -1,124 +1,176 @@ /* * Copyright (c) 2002 Marcel Moolenaar + * Copyright (c) 2022 Tobias C. Berner * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include static void usage(void) { - (void)fprintf(stderr, "usage: uuidgen [-1] [-n count] [-o filename]\n"); + (void)fprintf(stderr, + "usage: uuidgen [-1] [-r] [-n count] [-o filename]\n"); exit(1); } +static int +uuidgen_v4(struct uuid *store, int count) +{ + int size; + struct uuid *item; + + if (count < 1) { + errno = EINVAL; + return (-1); + } + size = sizeof(struct uuid) * count; + arc4random_buf(store, size); + item = store; + for (int i = 0; i < count; ++i) { + /* + * Set the two most significant bits (bits 6 and 7) of the + * clock_seq_hi_and_reserved to zero and one, respectively. + */ + item->clock_seq_hi_and_reserved &= ~(3 << 6); + item->clock_seq_hi_and_reserved |= (2 << 6); + /* + * Set the four most significant bits (bits 12 through 15) of + * the time_hi_and_version field to the 4-bit version number + * from Section 4.1.3. + */ + item->time_hi_and_version &= ~(15 << 12); + item->time_hi_and_version |= (4 << 12); + item++; + }; + return (0); +} + int main(int argc, char *argv[]) { FILE *fp; uuid_t *store, *uuid; char *p; - int ch, count, i, iterate, status; + int ch, count, i, iterate, status, version; - count = -1; /* no count yet */ - fp = stdout; /* default output file */ - iterate = 0; /* not one at a time */ - while ((ch = getopt(argc, argv, "1n:o:")) != -1) + count = -1; /* no count yet */ + fp = stdout; /* default output file */ + iterate = 0; /* not one at a time */ + version = 1; /* create uuid v1 by default */ + while ((ch = getopt(argc, argv, "1rn:o:")) != -1) switch (ch) { case '1': iterate = 1; break; + case 'r': + version = 4; + break; case 'n': if (count > 0) usage(); count = strtol(optarg, &p, 10); if (*p != 0 || count < 1) usage(); break; case 'o': if (fp != stdout) errx(1, "multiple output files not allowed"); fp = fopen(optarg, "w"); if (fp == NULL) err(1, "fopen"); break; default: usage(); } argv += optind; argc -= optind; if (argc) usage(); caph_cache_catpages(); if (caph_limit_stdio() < 0) err(1, "Unable to limit stdio"); if (caph_enter() < 0) err(1, "Unable to enter capability mode"); if (count == -1) count = 1; - store = (uuid_t*)malloc(sizeof(uuid_t) * count); + store = (uuid_t *)malloc(sizeof(uuid_t) * count); if (store == NULL) err(1, "malloc()"); if (!iterate) { /* Get them all in a single batch */ - if (uuidgen(store, count) != 0) - err(1, "uuidgen()"); + if (version == 1) { + if (uuidgen(store, count) != 0) + err(1, "uuidgen()"); + } else if (version == 4) { + if (uuidgen_v4(store, count) != 0) + err(1, "uuidgen_v4()"); + } else { + err(1, "unsupported version"); + } } else { uuid = store; for (i = 0; i < count; i++) { - if (uuidgen(uuid++, 1) != 0) - err(1, "uuidgen()"); + if (version == 1) { + if (uuidgen(uuid++, 1) != 0) + err(1, "uuidgen()"); + } else if (version == 4) { + if (uuidgen_v4(uuid++, 1) != 0) + err(1, "uuidgen_v4()"); + } else { + err(1, "unsupported version"); + } } } uuid = store; while (count--) { uuid_to_string(uuid++, &p, &status); if (status != uuid_s_ok) - err(1, "cannot stringify a UUID"); + err(1, "cannot stringify a UUID"); fprintf(fp, "%s\n", p); free(p); } free(store); if (fp != stdout) fclose(fp); return (0); }