mirror of
https://github.com/isar/libmdbx.git
synced 2025-11-06 19:08:56 +08:00
mdbx: добавление UUID для идентификации БД.
This commit is contained in:
215
src/osal.c
215
src/osal.c
@@ -2931,17 +2931,40 @@ __cold static void bootid_collect(bin128_t *p, const void *s, size_t n) {
|
||||
bootid_shake(p);
|
||||
|
||||
/* minor non-linear tomfoolery */
|
||||
const unsigned z = p->x % 61;
|
||||
const unsigned z = p->x % 61 + 1;
|
||||
p->y = p->y << z | p->y >> (64 - z);
|
||||
bootid_shake(p);
|
||||
bootid_shake(p);
|
||||
const unsigned q = p->x % 59;
|
||||
const unsigned q = p->x % 59 + 1;
|
||||
p->y = p->y << q | p->y >> (64 - q);
|
||||
bootid_shake(p);
|
||||
bootid_shake(p);
|
||||
bootid_shake(p);
|
||||
}
|
||||
|
||||
static size_t hamming_weight(size_t v) {
|
||||
const size_t m1 = (size_t)UINT64_C(0x5555555555555555);
|
||||
const size_t m2 = (size_t)UINT64_C(0x3333333333333333);
|
||||
const size_t m4 = (size_t)UINT64_C(0x0f0f0f0f0f0f0f0f);
|
||||
const size_t h01 = (size_t)UINT64_C(0x0101010101010101);
|
||||
v -= (v >> 1) & m1;
|
||||
v = (v & m2) + ((v >> 2) & m2);
|
||||
v = (v + (v >> 4)) & m4;
|
||||
return (v * h01) >> (sizeof(v) * 8 - 8);
|
||||
}
|
||||
|
||||
static inline size_t hw64(uint64_t v) {
|
||||
size_t r = hamming_weight((size_t)v);
|
||||
if (sizeof(v) > sizeof(r))
|
||||
r += hamming_weight((size_t)(v >> sizeof(r) * 4 >> sizeof(r) * 4));
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool check_uuid(bin128_t uuid) {
|
||||
size_t hw = hw64(uuid.x) + hw64(uuid.y) + hw64(uuid.x ^ uuid.y);
|
||||
return (hw >> 6) == 1;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
__cold static uint64_t windows_systemtime_ms() {
|
||||
@@ -3043,7 +3066,7 @@ bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
|
||||
s->y += aligned.y;
|
||||
} else
|
||||
bootid_collect(s, p, n);
|
||||
return true;
|
||||
return check_uuid(*s);
|
||||
}
|
||||
|
||||
if (n)
|
||||
@@ -3051,28 +3074,33 @@ bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(__linux__) || defined(__gnu_linux__)
|
||||
__cold static bool proc_read_uuid(const char *path, bin128_t *target) {
|
||||
const int fd = open(path, O_RDONLY | O_NOFOLLOW);
|
||||
if (fd != -1) {
|
||||
struct statfs fs;
|
||||
char buf[42];
|
||||
const ssize_t len =
|
||||
(fstatfs(fd, &fs) == 0 && fs.f_type == /* procfs */ 0x9FA0)
|
||||
? read(fd, buf, sizeof(buf))
|
||||
: -1;
|
||||
const int err = close(fd);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
if (len > 0)
|
||||
return bootid_parse_uuid(target, buf, len);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif /* Linux */
|
||||
|
||||
__cold static bin128_t osal_bootid(void) {
|
||||
bin128_t bin = {{0, 0}};
|
||||
bin128_t uuid = {{0, 0}};
|
||||
bool got_machineid = false, got_boottime = false, got_bootseq = false;
|
||||
|
||||
#if defined(__linux__) || defined(__gnu_linux__)
|
||||
{
|
||||
const int fd =
|
||||
open("/proc/sys/kernel/random/boot_id", O_RDONLY | O_NOFOLLOW);
|
||||
if (fd != -1) {
|
||||
struct statfs fs;
|
||||
char buf[42];
|
||||
const ssize_t len =
|
||||
(fstatfs(fd, &fs) == 0 && fs.f_type == /* procfs */ 0x9FA0)
|
||||
? read(fd, buf, sizeof(buf))
|
||||
: -1;
|
||||
const int err = close(fd);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
if (len > 0 && bootid_parse_uuid(&bin, buf, len))
|
||||
return bin;
|
||||
}
|
||||
}
|
||||
if (proc_read_uuid("/proc/sys/kernel/random/boot_id", &uuid))
|
||||
return uuid;
|
||||
#endif /* Linux */
|
||||
|
||||
#if defined(__APPLE__) || defined(__MACH__)
|
||||
@@ -3080,16 +3108,15 @@ __cold static bin128_t osal_bootid(void) {
|
||||
char buf[42];
|
||||
size_t len = sizeof(buf);
|
||||
if (!sysctlbyname("kern.bootsessionuuid", buf, &len, nullptr, 0) &&
|
||||
bootid_parse_uuid(&bin, buf, len))
|
||||
return bin;
|
||||
bootid_parse_uuid(&uuid, buf, len))
|
||||
return uuid;
|
||||
|
||||
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
|
||||
__MAC_OS_X_VERSION_MIN_REQUIRED > 1050
|
||||
uuid_t uuid;
|
||||
uuid_t hostuuid;
|
||||
struct timespec wait = {0, 1000000000u / 42};
|
||||
if (!gethostuuid(uuid, &wait) &&
|
||||
bootid_parse_uuid(&bin, uuid, sizeof(uuid)))
|
||||
got_machineid = true;
|
||||
if (!gethostuuid(hostuuid, &wait))
|
||||
got_machineid = bootid_parse_uuid(&uuid, hostuuid, sizeof(hostuuid));
|
||||
#endif /* > 10.5 */
|
||||
|
||||
struct timeval boottime;
|
||||
@@ -3127,7 +3154,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
"MachineGuid", &buf.MachineGuid,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len < sizeof(buf))
|
||||
got_machineid = bootid_parse_uuid(&bin, &buf.MachineGuid, len);
|
||||
got_machineid = bootid_parse_uuid(&uuid, &buf.MachineGuid, len);
|
||||
|
||||
if (!got_machineid) {
|
||||
/* again, Windows is madness */
|
||||
@@ -3145,7 +3172,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
"DigitalProductId", &buf.DigitalProductId,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len > 42 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.DigitalProductId, len);
|
||||
bootid_collect(&uuid, &buf.DigitalProductId, len);
|
||||
got_machineid = true;
|
||||
}
|
||||
len = sizeof(buf);
|
||||
@@ -3153,7 +3180,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
"DigitalProductId", &buf.DigitalProductId,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len > 42 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.DigitalProductId, len);
|
||||
bootid_collect(&uuid, &buf.DigitalProductId, len);
|
||||
got_machineid = true;
|
||||
}
|
||||
len = sizeof(buf);
|
||||
@@ -3161,7 +3188,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
"DigitalProductId", &buf.DigitalProductId,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len > 42 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.DigitalProductId, len);
|
||||
bootid_collect(&uuid, &buf.DigitalProductId, len);
|
||||
got_machineid = true;
|
||||
}
|
||||
}
|
||||
@@ -3173,7 +3200,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BootId",
|
||||
&buf.BootId, &len) == ERROR_SUCCESS &&
|
||||
len > 1 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.BootId, len);
|
||||
bootid_collect(&uuid, &buf.BootId, len);
|
||||
got_bootseq = true;
|
||||
}
|
||||
|
||||
@@ -3181,7 +3208,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BaseTime",
|
||||
&buf.BaseTime, &len) == ERROR_SUCCESS &&
|
||||
len >= sizeof(buf.BaseTime) && buf.BaseTime) {
|
||||
bootid_collect(&bin, &buf.BaseTime, len);
|
||||
bootid_collect(&uuid, &buf.BaseTime, len);
|
||||
got_boottime = true;
|
||||
}
|
||||
|
||||
@@ -3197,7 +3224,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
buf.SysTimeOfDayInfoHacked.BootTime.QuadPart -
|
||||
buf.SysTimeOfDayInfoHacked.BootTimeBias;
|
||||
if (UnbiasedBootTime) {
|
||||
bootid_collect(&bin, &UnbiasedBootTime, sizeof(UnbiasedBootTime));
|
||||
bootid_collect(&uuid, &UnbiasedBootTime, sizeof(UnbiasedBootTime));
|
||||
got_boottime = true;
|
||||
}
|
||||
}
|
||||
@@ -3205,7 +3232,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
if (!got_boottime) {
|
||||
uint64_t boottime = windows_bootime();
|
||||
if (boottime) {
|
||||
bootid_collect(&bin, &boottime, sizeof(boottime));
|
||||
bootid_collect(&uuid, &boottime, sizeof(boottime));
|
||||
got_boottime = true;
|
||||
}
|
||||
}
|
||||
@@ -3223,7 +3250,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
#endif
|
||||
mib,
|
||||
ARRAY_LENGTH(mib), &buf, &len, nullptr, 0) == 0)
|
||||
got_machineid = bootid_parse_uuid(&bin, buf, len);
|
||||
got_machineid = bootid_parse_uuid(&uuid, buf, len);
|
||||
}
|
||||
#endif /* CTL_HW && HW_UUID */
|
||||
|
||||
@@ -3238,7 +3265,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
#endif
|
||||
mib,
|
||||
ARRAY_LENGTH(mib), &buf, &len, nullptr, 0) == 0)
|
||||
got_machineid = bootid_parse_uuid(&bin, buf, len);
|
||||
got_machineid = bootid_parse_uuid(&uuid, buf, len);
|
||||
}
|
||||
#endif /* CTL_KERN && KERN_HOSTUUID */
|
||||
|
||||
@@ -3247,7 +3274,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
char buf[42];
|
||||
size_t len = sizeof(buf);
|
||||
if (sysctlbyname("machdep.dmi.system-uuid", buf, &len, nullptr, 0) == 0)
|
||||
got_machineid = bootid_parse_uuid(&bin, buf, len);
|
||||
got_machineid = bootid_parse_uuid(&uuid, buf, len);
|
||||
}
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
@@ -3255,7 +3282,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
if (!got_machineid) {
|
||||
const int hostid = gethostid();
|
||||
if (hostid > 0) {
|
||||
bootid_collect(&bin, &hostid, sizeof(hostid));
|
||||
bootid_collect(&uuid, &hostid, sizeof(hostid));
|
||||
got_machineid = true;
|
||||
}
|
||||
}
|
||||
@@ -3263,8 +3290,8 @@ __cold static bin128_t osal_bootid(void) {
|
||||
|
||||
if (!got_machineid) {
|
||||
lack:
|
||||
bin.x = bin.y = 0;
|
||||
return bin;
|
||||
uuid.x = uuid.y = 0;
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -3281,7 +3308,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
mib,
|
||||
ARRAY_LENGTH(mib), &boottime, &len, nullptr, 0) == 0 &&
|
||||
len == sizeof(boottime) && boottime.tv_sec) {
|
||||
bootid_collect(&bin, &boottime, len);
|
||||
bootid_collect(&uuid, &boottime, len);
|
||||
got_boottime = true;
|
||||
}
|
||||
}
|
||||
@@ -3298,11 +3325,11 @@ __cold static bin128_t osal_bootid(void) {
|
||||
switch (kn->data_type) {
|
||||
case KSTAT_DATA_INT32:
|
||||
case KSTAT_DATA_UINT32:
|
||||
bootid_collect(&bin, &kn->value, sizeof(int32_t));
|
||||
bootid_collect(&uuid, &kn->value, sizeof(int32_t));
|
||||
got_boottime = true;
|
||||
case KSTAT_DATA_INT64:
|
||||
case KSTAT_DATA_UINT64:
|
||||
bootid_collect(&bin, &kn->value, sizeof(int64_t));
|
||||
bootid_collect(&uuid, &kn->value, sizeof(int64_t));
|
||||
got_boottime = true;
|
||||
}
|
||||
}
|
||||
@@ -3318,12 +3345,12 @@ __cold static bin128_t osal_bootid(void) {
|
||||
const struct utmpx id = {.ut_type = BOOT_TIME};
|
||||
const struct utmpx *entry = getutxid(&id);
|
||||
if (entry) {
|
||||
bootid_collect(&bin, entry, sizeof(*entry));
|
||||
bootid_collect(&uuid, entry, sizeof(*entry));
|
||||
got_boottime = true;
|
||||
while (unlikely((entry = getutxid(&id)) != nullptr)) {
|
||||
/* have multiple reboot records, assuming we can distinguish next
|
||||
* bootsession even if RTC is wrong or absent */
|
||||
bootid_collect(&bin, entry, sizeof(*entry));
|
||||
bootid_collect(&uuid, entry, sizeof(*entry));
|
||||
got_bootseq = true;
|
||||
}
|
||||
}
|
||||
@@ -3352,7 +3379,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
goto lack;
|
||||
}
|
||||
|
||||
return bin;
|
||||
return uuid;
|
||||
}
|
||||
|
||||
__cold int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages,
|
||||
@@ -3474,6 +3501,100 @@ __cold int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages,
|
||||
return MDBX_SUCCESS;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/uuid.h>
|
||||
#endif /* FreeBSD */
|
||||
|
||||
#if __GLIBC_PREREQ(2, 25) || defined(__FreeBSD__) || defined(__NetBSD__) || \
|
||||
defined(__BSD__) || defined(__bsdi__) || defined(__DragonFly__) || \
|
||||
defined(__APPLE__) || __has_include(<sys/random.h>)
|
||||
#include <sys/random.h>
|
||||
#endif /* sys/random.h */
|
||||
|
||||
MDBX_INTERNAL bin128_t osal_guid(const MDBX_env *env) {
|
||||
struct {
|
||||
uint64_t begin, end, cputime;
|
||||
uintptr_t thread, pid;
|
||||
const void *x, *y;
|
||||
bin128_t (*z)(const MDBX_env *env);
|
||||
} salt;
|
||||
|
||||
salt.begin = osal_monotime();
|
||||
bin128_t uuid = {{0, 0}};
|
||||
|
||||
#if defined(__linux__) || defined(__gnu_linux__)
|
||||
if (proc_read_uuid("/proc/sys/kernel/random/uuid", &uuid) && check_uuid(uuid))
|
||||
return uuid;
|
||||
#endif /* Linux */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
STATIC_ASSERT(sizeof(uuid) == sizeof(struct uuid));
|
||||
if (uuidgen((struct uuid *)&uuid, 1) == 0 && check_uuid(uuid))
|
||||
return uuid;
|
||||
#endif /* FreeBSD */
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (imports.CoCreateGuid && imports.CoCreateGuid(&uuid) == 0 &&
|
||||
check_uuid(uuid))
|
||||
return uuid;
|
||||
|
||||
HCRYPTPROV hCryptProv = 0;
|
||||
if (CryptAcquireContextW(&hCryptProv, nullptr, nullptr, PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
|
||||
const BOOL ok =
|
||||
CryptGenRandom(hCryptProv, sizeof(uuid), (unsigned char *)&uuid);
|
||||
CryptReleaseContext(hCryptProv, 0);
|
||||
if (ok && check_uuid(uuid))
|
||||
return uuid;
|
||||
}
|
||||
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_8_0)
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0
|
||||
if (CCRandomGenerateBytes(&uuid, sizeof(uuid)) == kCCSuccess &&
|
||||
check_uuid(uuid))
|
||||
return uuid;
|
||||
#endif /* iOS >= 8.x */
|
||||
#else
|
||||
const int fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd != -1) {
|
||||
const ssize_t len = read(fd, &uuid, sizeof(uuid));
|
||||
const int err = close(fd);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
if (len == sizeof(uuid) && check_uuid(uuid))
|
||||
return uuid;
|
||||
}
|
||||
#if (__GLIBC_PREREQ(2, 25) || defined(__FreeBSD__) || defined(__NetBSD__) || \
|
||||
defined(__BSD__) || defined(__bsdi__) || defined(__DragonFly__)) && \
|
||||
!defined(__APPLE__) && !defined(__ANDROID_API__)
|
||||
if (getrandom(&uuid, sizeof(uuid), 0) == sizeof(uuid) && check_uuid(uuid))
|
||||
return uuid;
|
||||
#elif defined(__OpenBSD__) || (defined(__sun) && defined(__SVR4)) || \
|
||||
(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
|
||||
__MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
|
||||
if (getentropy(&uuid, sizeof(uuid)) == 0 && check_uuid(uuid))
|
||||
return uuid;
|
||||
#endif /* getrandom() / getentropy() */
|
||||
#endif /* !Windows */
|
||||
|
||||
uuid = globals.bootid;
|
||||
bootid_collect(&uuid, env, sizeof(*env));
|
||||
salt.thread = osal_thread_self();
|
||||
salt.pid = osal_getpid();
|
||||
salt.x = &salt;
|
||||
salt.y = env;
|
||||
salt.z = &osal_guid;
|
||||
do {
|
||||
salt.cputime = osal_cputime(nullptr);
|
||||
salt.end = osal_monotime();
|
||||
bootid_collect(&uuid, &salt, sizeof(salt));
|
||||
} while (!check_uuid(uuid));
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void osal_ctor(void) {
|
||||
#if MDBX_HAVE_PWRITEV && defined(_SC_IOV_MAX)
|
||||
osal_iov_max = sysconf(_SC_IOV_MAX);
|
||||
|
||||
Reference in New Issue
Block a user