diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2018-08-22 17:26:08 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2018-08-22 17:36:23 +0200 |
commit | febb9c275b5247df596876e4eea7fa17b7ec45e7 (patch) | |
tree | 214a192cc6b019fb25a659cfdb84601da74438bf /libbutl/uuid-macos.cxx | |
parent | f8fc81a5c9fcd986473797df9286c6c9fef683bf (diff) |
Add support for UUID generation
Diffstat (limited to 'libbutl/uuid-macos.cxx')
-rw-r--r-- | libbutl/uuid-macos.cxx | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/libbutl/uuid-macos.cxx b/libbutl/uuid-macos.cxx new file mode 100644 index 0000000..1003501 --- /dev/null +++ b/libbutl/uuid-macos.cxx @@ -0,0 +1,81 @@ +// file : libbutl/uuid-macos.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_BOOTSTRAP + +#include <libbutl/uuid.hxx> + +#include <CoreFoundation/CFUUID.h> + +#include <cassert> +#include <cstring> // memcpy() + +using namespace std; + +namespace butl +{ + void + uuid_throw_weak (); // uuid.cxx + + uuid uuid_system_generator:: + generate (bool strong) + { + // The common way to generate a UUID on Mac OS is with the CFUUIDCreate() + // function from the CoreFoundation framework. Interestingly, if we look + // at the implementation (yes, the CF source code is available), we will + // see that it uses the <uuid/uuid.h> API which looks like a customized + // implementation from e2fsprogs that itself is a precursor to libuuid + // from util-linux. + // + // More specifically (and at least as of CF version 1153.18), it calls + // uuid_generate_random() unless the CFUUIDVersionNumber environment + // variable is set to 1, in which case it calls uuid_generate_time(). It + // also appears to serialize these calls so the implementation should be + // thread-safe (see the Linux implementation for background; this is also + // the reason why we don't want to use the low-level API directly even if + // we provide our own synchronization: if other code in the process calls + // CFUUIDCreate() then we will end up with a race). + // + // In theory the use of uuid_generate_random() is bad news since it will + // produce weak pseudo-random UUIDs if no high-quality randomness is + // available (unlike uuid_generate() which will only produce strong random + // UUIDs falling back to the MAC/time-based ones; see uuid_generate(3) for + // details). + // + // In practice (and at least as of Mac OS libc version 1244.30), however, + // uuid_generate_random() uses arc4random(3) which reportedly produces + // high-quality randomness (and uuid_generate() simply always calls it). + // + CFUUIDRef h (CFUUIDCreate (NULL)); + CFUUIDBytes d (CFUUIDGetUUIDBytes (h)); + CFRelease (h); + + uint8_t a[16]; + memcpy (a, &d, 16); // CFUUIDBytes is POD. + + uuid r (a); + assert (r.variant () == uuid_variant::dce); // Sanity check. + + // If this is a MAC/time-based UUID, then it's possible the time was not + // obtained in a collision-safe manner (looking at the implementation this + // seems to be the case; see the Linux implementation for background). + // + if (strong && r.version () != uuid_version::random) + uuid_throw_weak (); + + return r; + } + + void uuid_system_generator:: + initialize () + { + } + + void uuid_system_generator:: + terminate () + { + } +} + +#endif // BUILD2_BOOTSTRAP |