From febb9c275b5247df596876e4eea7fa17b7ec45e7 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 22 Aug 2018 17:26:08 +0200 Subject: Add support for UUID generation --- libbutl/uuid-freebsd.cxx | 90 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 libbutl/uuid-freebsd.cxx (limited to 'libbutl/uuid-freebsd.cxx') 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 + +#include + +#include + +#include +#include // memcpy() +#include + +using namespace std; + +namespace butl +{ + void + uuid_throw_weak (); // uuid.cxx + + uuid uuid_system_generator:: + generate (bool strong) + { + // While FreeBSD shares the uuid_*() (, 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 (, 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 -- cgit v1.1