diff options
Diffstat (limited to 'libudffs/misc.c')
-rw-r--r-- | libudffs/misc.c | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/libudffs/misc.c b/libudffs/misc.c index 6369078..a0e496a 100644 --- a/libudffs/misc.c +++ b/libudffs/misc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Pali Rohár <pali.rohar@gmail.com> + * Copyright (C) 2017-2018 Pali Rohár <pali.rohar@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,9 +19,15 @@ #include "config.h" #include <ctype.h> +#include <errno.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> #include "libudffs.h" @@ -82,3 +88,71 @@ size_t gen_uuid_from_vol_set_ident(char uuid[17], const dstring *vol_set_ident, return 16; } + +uint32_t strtou32(const char *str, int base, int *failed) +{ + char *endptr = NULL; + long long int ret; + + /* strtou* does not signal underflow, so use signed variant */ + errno = 0; + ret = strtoll(str, &endptr, base); + /* strto* skips leading whitespaces, so detect them via isspace */ + *failed = (!*str || isspace(*str) || *endptr || errno || ret < 0 || ret > UINT32_MAX) ? 1 : 0; + return ret; +} + +uint16_t strtou16(const char *str, int base, int *failed) +{ + uint32_t ret; + + ret = strtou32(str, base, failed); + *failed = (*failed || ret > UINT16_MAX) ? 1 : 0; + return ret; +} + +static inline unsigned int intlog2(unsigned int word) +{ + unsigned int result = 0; + + while (word >>= 1) + result++; + return result; +} + +uint32_t randu32(void) +{ + int fd; + uint32_t value; + unsigned int bits; + unsigned int rand_bits; + + static int srand_done = 0; + + fd = open("/dev/urandom", O_RDONLY); + if (fd >= 0) + { + if (read(fd, &value, sizeof(value)) == sizeof(value)) + { + close(fd); + return value; + } + close(fd); + } + + if (!srand_done) + { + srand(time(NULL) * getpid()); + srand_done = 1; + } + + value = 0; + rand_bits = intlog2((unsigned int)RAND_MAX+1); + for (bits = 0; bits < 32; bits += rand_bits) + { + value <<= rand_bits; + value |= rand(); + } + + return value; +} |