HaikuDepot: notify work status from main window
[haiku.git] / src / kits / support / Uuid.cpp
blobbc08a00e529a0b69d0a5df1b8f26afb855d1b130
1 /*
2 * Copyright 2013 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <Uuid.h>
9 #include <fcntl.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <time.h>
13 #include <unistd.h>
16 static const char* const kHexChars = "0123456789abcdef";
18 static const size_t kVersionByteIndex = 6;
19 static const size_t kVariantByteIndex = 8;
22 static bool
23 init_random_seed()
25 // set a time-based seed
26 timespec time;
27 clock_gettime(CLOCK_REALTIME, &time);
28 uint32 seed = (uint32)time.tv_sec ^ (uint32)time.tv_nsec;
30 // factor in a stack address -- with address space layout randomization
31 // that adds a bit of additional randomness
32 seed ^= (uint32)(addr_t)&time;
34 srandom(seed);
36 return true;
40 namespace BPrivate {
42 BUuid::BUuid()
44 memset(fValue, 0, sizeof(fValue));
48 BUuid::BUuid(const BUuid& other)
50 memcpy(fValue, other.fValue, sizeof(fValue));
54 BUuid::~BUuid()
59 bool
60 BUuid::IsNil() const
62 for (size_t i = 0; i < sizeof(fValue); i++) {
63 if (fValue[i] != 0)
64 return false;
67 return true;
71 BUuid&
72 BUuid::SetToRandom()
74 if (!BUuid::_SetToDevRandom())
75 BUuid::_SetToRandomFallback();
77 // set variant and version
78 fValue[kVariantByteIndex] &= 0x3f;
79 fValue[kVariantByteIndex] |= 0x80;
80 fValue[kVersionByteIndex] &= 0x0f;
81 fValue[kVersionByteIndex] |= 4 << 4;
82 // version 4
84 return *this;
88 BString
89 BUuid::ToString() const
91 char buffer[32];
92 for (size_t i = 0; i < 16; i++) {
93 buffer[2 * i] = kHexChars[fValue[i] >> 4];
94 buffer[2 * i + 1] = kHexChars[fValue[i] & 0xf];
97 return BString().SetToFormat("%.8s-%.4s-%.4s-%.4s-%.12s",
98 buffer, buffer + 8, buffer + 12, buffer + 16, buffer + 20);
103 BUuid::Compare(const BUuid& other) const
105 return memcmp(fValue, other.fValue, sizeof(fValue));
109 BUuid&
110 BUuid::operator=(const BUuid& other)
112 memcpy(fValue, other.fValue, sizeof(fValue));
114 return *this;
118 bool
119 BUuid::_SetToDevRandom()
121 // open device
122 int fd = open("/dev/urandom", O_RDONLY);
123 if (fd < 0) {
124 fd = open("/dev/random", O_RDONLY);
125 if (fd < 0)
126 return false;
129 // read bytes
130 ssize_t bytesRead = read(fd, fValue, sizeof(fValue));
131 close(fd);
133 return bytesRead == (ssize_t)sizeof(fValue);
137 void
138 BUuid::_SetToRandomFallback()
140 static bool sSeedInitialized = init_random_seed();
141 (void)sSeedInitialized;
143 for (int32 i = 0; i < 4; i++) {
144 uint32 value = random();
145 fValue[4 * i + 0] = uint8(value >> 24);
146 fValue[4 * i + 1] = uint8(value >> 16);
147 fValue[4 * i + 2] = uint8(value >> 8);
148 fValue[4 * i + 3] = uint8(value);
151 // random() returns 31 bit numbers only, so we move a few bits from where
152 // we overwrite them with the version anyway.
153 uint8 bitsToMove = fValue[kVersionByteIndex];
154 for (int32 i = 0; i < 4; i++)
155 fValue[4 * i] |= (bitsToMove << i) & 0x80;
158 } // namespace BPrivate
161 using BPrivate::BUuid;