1177162Sjkoshy/* 2145256Sjkoshy * Copyright 2013 Haiku, Inc. All rights reserved. 3145256Sjkoshy * Distributed under the terms of the MIT License. 4145256Sjkoshy */ 5145256Sjkoshy 6145256Sjkoshy 7145256Sjkoshy#include <Uuid.h> 8145256Sjkoshy 9145256Sjkoshy#include <fcntl.h> 10145256Sjkoshy#include <stdlib.h> 11145256Sjkoshy#include <string.h> 12232151Sbrueffer#include <time.h> 13232151Sbrueffer#include <unistd.h> 14232151Sbrueffer 15232151Sbrueffer 16232151Sbruefferstatic const char* const kHexChars = "0123456789abcdef"; 17232151Sbrueffer 18232151Sbruefferstatic const size_t kVersionByteIndex = 6; 19232151Sbruefferstatic const size_t kVariantByteIndex = 8; 20232151Sbrueffer 21232151Sbrueffer 22232151Sbruefferstatic bool 23145256Sjkoshyinit_random_seed() 24145256Sjkoshy{ 25145256Sjkoshy // set a time-based seed 26183595Sjkoshy timespec time; 27206622Suqs clock_gettime(CLOCK_REALTIME, &time); 28145256Sjkoshy uint32 seed = (uint32)time.tv_sec ^ (uint32)time.tv_nsec; 29145256Sjkoshy 30183084Sjkoshy // factor in a stack address -- with address space layout randomization 31183084Sjkoshy // that adds a bit of additional randomness 32183084Sjkoshy seed ^= (uint32)(addr_t)&time; 33183084Sjkoshy 34183084Sjkoshy srandom(seed); 35183084Sjkoshy 36145256Sjkoshy return true; 37145256Sjkoshy} 38145256Sjkoshy 39145256Sjkoshy 40145256Sjkoshynamespace BPrivate { 41145256Sjkoshy 42145256SjkoshyBUuid::BUuid() 43145256Sjkoshy{ 44145256Sjkoshy memset(fValue, 0, sizeof(fValue)); 45183084Sjkoshy} 46183084Sjkoshy 47183084Sjkoshy 48183084SjkoshyBUuid::BUuid(const BUuid& other) 49145256Sjkoshy{ 50145256Sjkoshy memcpy(fValue, other.fValue, sizeof(fValue)); 51145256Sjkoshy} 52145256Sjkoshy 53145256Sjkoshy 54145256SjkoshyBUuid::~BUuid() 55145256Sjkoshy{ 56145256Sjkoshy} 57145256Sjkoshy 58145256Sjkoshy 59145256Sjkoshybool 60145256SjkoshyBUuid::IsNil() const 61145256Sjkoshy{ 62145256Sjkoshy for (size_t i = 0; i < sizeof(fValue); i++) { 63145256Sjkoshy if (fValue[i] != 0) 64145440Sjkoshy return false; 65145440Sjkoshy } 66145440Sjkoshy 67147586Sru return true; 68145440Sjkoshy} 69145440Sjkoshy 70145440Sjkoshy 71183084SjkoshyBUuid& 72183084SjkoshyBUuid::SetToRandom() 73183084Sjkoshy{ 74183084Sjkoshy if (!BUuid::_SetToDevRandom()) 75183084Sjkoshy BUuid::_SetToRandomFallback(); 76183084Sjkoshy 77183084Sjkoshy // set variant and version 78183084Sjkoshy fValue[kVariantByteIndex] &= 0x3f; 79183084Sjkoshy fValue[kVariantByteIndex] |= 0x80; 80183084Sjkoshy fValue[kVersionByteIndex] &= 0x0f; 81183084Sjkoshy fValue[kVersionByteIndex] |= 4 << 4; 82183084Sjkoshy // version 4 83183084Sjkoshy 84183084Sjkoshy return *this; 85183084Sjkoshy} 86183084Sjkoshy 87183084Sjkoshy 88183084SjkoshyBString 89183084SjkoshyBUuid::ToString() const 90183084Sjkoshy{ 91183084Sjkoshy char buffer[32]; 92183084Sjkoshy for (size_t i = 0; i < 16; i++) { 93145256Sjkoshy buffer[2 * i] = kHexChars[fValue[i] >> 4]; 94145256Sjkoshy buffer[2 * i + 1] = kHexChars[fValue[i] & 0xf]; 95145256Sjkoshy } 96145256Sjkoshy 97145256Sjkoshy return BString().SetToFormat("%.8s-%.4s-%.4s-%.4s-%.12s", 98145256Sjkoshy buffer, buffer + 8, buffer + 12, buffer + 16, buffer + 20); 99145256Sjkoshy} 100145256Sjkoshy 101145256Sjkoshy 102145256Sjkoshyint 103147586SruBUuid::Compare(const BUuid& other) const 104145256Sjkoshy{ 105145256Sjkoshy return memcmp(fValue, other.fValue, sizeof(fValue)); 106145256Sjkoshy} 107145256Sjkoshy 108145256Sjkoshy 109145256SjkoshyBUuid& 110145256SjkoshyBUuid::operator=(const BUuid& other) 111145256Sjkoshy{ 112145256Sjkoshy memcpy(fValue, other.fValue, sizeof(fValue)); 113145256Sjkoshy 114147586Sru return *this; 115145256Sjkoshy} 116147586Sru 117145256Sjkoshy 118145256Sjkoshybool 119145256SjkoshyBUuid::_SetToDevRandom() 120145256Sjkoshy{ 121145256Sjkoshy // open device 122145256Sjkoshy int fd = open("/dev/urandom", O_RDONLY); 123145256Sjkoshy if (fd < 0) { 124196446Sjkoshy fd = open("/dev/random", O_RDONLY); 125145256Sjkoshy if (fd < 0) 126145256Sjkoshy return false; 127145256Sjkoshy } 128145256Sjkoshy 129145256Sjkoshy // read bytes 130145256Sjkoshy ssize_t bytesRead = read(fd, fValue, sizeof(fValue)); 131145256Sjkoshy close(fd); 132145256Sjkoshy 133145256Sjkoshy return bytesRead == (ssize_t)sizeof(fValue); 134145256Sjkoshy} 135145256Sjkoshy 136145256Sjkoshy 137145256Sjkoshyvoid 138145256SjkoshyBUuid::_SetToRandomFallback() 139145256Sjkoshy{ 140145256Sjkoshy static bool sSeedInitialized = init_random_seed(); 141145256Sjkoshy (void)sSeedInitialized; 142145256Sjkoshy 143145256Sjkoshy for (int32 i = 0; i < 4; i++) { 144145256Sjkoshy uint32 value = random(); 145145256Sjkoshy fValue[4 * i + 0] = uint8(value >> 24); 146145256Sjkoshy fValue[4 * i + 1] = uint8(value >> 16); 147145256Sjkoshy fValue[4 * i + 2] = uint8(value >> 8); 148145256Sjkoshy fValue[4 * i + 3] = uint8(value); 149145256Sjkoshy } 150145256Sjkoshy 151145256Sjkoshy // random() returns 31 bit numbers only, so we move a few bits from where 152145256Sjkoshy // we overwrite them with the version anyway. 153147586Sru uint8 bitsToMove = fValue[kVersionByteIndex]; 154145256Sjkoshy for (int32 i = 0; i < 4; i++) 155147586Sru fValue[4 * i] |= (bitsToMove << i) & 0x80; 156145256Sjkoshy} 157147586Sru 158145256Sjkoshy} // namespace BPrivate 159145256Sjkoshy 160145256Sjkoshy 161145256Sjkoshyusing BPrivate::BUuid; 162147586Sru