aboutsummaryrefslogtreecommitdiff
path: root/libbutl/uuid-freebsd.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-08-22 17:26:08 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-08-22 17:36:23 +0200
commitfebb9c275b5247df596876e4eea7fa17b7ec45e7 (patch)
tree214a192cc6b019fb25a659cfdb84601da74438bf /libbutl/uuid-freebsd.cxx
parentf8fc81a5c9fcd986473797df9286c6c9fef683bf (diff)
Add support for UUID generation
Diffstat (limited to 'libbutl/uuid-freebsd.cxx')
-rw-r--r--libbutl/uuid-freebsd.cxx90
1 files changed, 90 insertions, 0 deletions
diff --git a/libbutl/uuid-freebsd.cxx b/libbutl/uuid-freebsd.cxx
new file mode 100644
index 0000000..184799d
--- /dev/null
+++ b/libbutl/uuid-freebsd.cxx
@@ -0,0 +1,90 @@
+// file : libbutl/uuid-freebsd.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BUILD2_BOOTSTRAP
+
+#include <libbutl/uuid.hxx>
+
+#include <sys/uuid.h>
+
+#include <errno.h>
+
+#include <cassert>
+#include <cstring> // memcpy()
+#include <system_error>
+
+using namespace std;
+
+namespace butl
+{
+ void
+ uuid_throw_weak (); // uuid.cxx
+
+ uuid uuid_system_generator::
+ generate (bool strong)
+ {
+ // While FreeBSD shares the uuid_*() (<uuid.h>, uuid(3)) API with other
+ // BSDs, its documentation is quite light on the kind of UUID we get and
+ // with what guarantees. The implementation of uuid_create() simply calls
+ // the uuidgen() system call (<sys/uuid.h>, uuidgen(2)) which has some
+ // details.
+ //
+ // Specifically (and as of FreeBSD 11.2), we get a version 1 (MAC/time-
+ // based) UUID and it seems there is provision for getting the time in a
+ // collision-safe:
+ //
+ // "According to the algorithm of generating time-based UUIDs, this will
+ // also force a new random clock sequence, thereby increasing the
+ // likelihood for the identifier to be unique."
+ //
+ // So we will assume a MAC/time-based UUID is strong. We also assume a
+ // random UUID is strong as well in case in the future this will becomes
+ // the default (as seems to be the trend); presumably, FreeBSD folks are
+ // smart enough not to start return random UUIDs without a good source of
+ // randomness, at least not by default.
+ //
+ struct ::uuid d;
+
+ if (uuidgen (&d, 1) != 0)
+ throw system_error (errno, system_category ());
+
+ uuid r;
+
+ // This is effectively just memcpy() but let's reference the member names
+ // in case anything changes on either side.
+ //
+ r.time_low = d.time_low;
+ r.time_mid = d.time_mid;
+ r.time_hiv = d.time_hi_and_version;
+ r.clock_seq_hir = d.clock_seq_hi_and_reserved;
+ r.clock_seq_low = d.clock_seq_low;
+ memcpy (r.node, d.node, 6);
+
+ assert (r.variant () == uuid_variant::dce); // Sanity check.
+
+ if (strong)
+ {
+ switch (r.version ())
+ {
+ case uuid_version::time:
+ case uuid_version::random: break;
+ default: uuid_throw_weak ();
+ }
+ }
+
+ return r;
+ }
+
+ void uuid_system_generator::
+ initialize ()
+ {
+ }
+
+ void uuid_system_generator::
+ terminate ()
+ {
+ }
+}
+
+#endif // BUILD2_BOOTSTRAP