X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/5d08193126df54405dae3073c62b7c19ae03d1a4..1858da2faae3b6a8becf4f7eef3f712d6e4b986b:/src/util.c?ds=sidebyside diff --git a/src/util.c b/src/util.c index 5712241b..bcdafc63 100644 --- a/src/util.c +++ b/src/util.c @@ -1,9 +1,13 @@ +#include "fmacros.h" #include #include #include #include #include #include +#include +#include + #include "util.h" /* Glob-style pattern matching. */ @@ -207,8 +211,8 @@ int ll2string(char *s, size_t len, long long value) { /* Convert a string into a long long. Returns 1 if the string could be parsed * into a (non-overflowing) long long, 0 otherwise. The value will be set to * the parsed value when appropriate. */ -int string2ll(char *s, size_t slen, long long *value) { - char *p = s; +int string2ll(const char *s, size_t slen, long long *value) { + const char *p = s; size_t plen = 0; int negative = 0; unsigned long long v; @@ -273,7 +277,7 @@ int string2ll(char *s, size_t slen, long long *value) { /* Convert a string into a long. Returns 1 if the string could be parsed into a * (non-overflowing) long, 0 otherwise. The value will be set to the parsed * value when appropriate. */ -int string2l(char *s, size_t slen, long *lval) { +int string2l(const char *s, size_t slen, long *lval) { long long llval; if (!string2ll(s,slen,&llval)) @@ -325,6 +329,52 @@ int d2string(char *buf, size_t len, double value) { return len; } +/* Generate the Redis "Run ID", a SHA1-sized random number that identifies a + * given execution of Redis, so that if you are talking with an instance + * having run_id == A, and you reconnect and it has run_id == B, you can be + * sure that it is either a different instance or it was restarted. */ +void getRandomHexChars(char *p, unsigned int len) { + FILE *fp = fopen("/dev/urandom","r"); + char *charset = "0123456789abcdef"; + unsigned int j; + + if (fp == NULL || fread(p,len,1,fp) == 0) { + /* If we can't read from /dev/urandom, do some reasonable effort + * in order to create some entropy, since this function is used to + * generate run_id and cluster instance IDs */ + char *x = p; + unsigned int l = len; + struct timeval tv; + pid_t pid = getpid(); + + /* Use time and PID to fill the initial array. */ + gettimeofday(&tv,NULL); + if (l >= sizeof(tv.tv_usec)) { + memcpy(x,&tv.tv_usec,sizeof(tv.tv_usec)); + l -= sizeof(tv.tv_usec); + x += sizeof(tv.tv_usec); + } + if (l >= sizeof(tv.tv_sec)) { + memcpy(x,&tv.tv_sec,sizeof(tv.tv_sec)); + l -= sizeof(tv.tv_sec); + x += sizeof(tv.tv_sec); + } + if (l >= sizeof(pid)) { + memcpy(x,&pid,sizeof(pid)); + l -= sizeof(pid); + x += sizeof(pid); + } + /* Finally xor it with rand() output, that was already seeded with + * time() at startup. */ + for (j = 0; j < len; j++) + p[j] ^= rand(); + } + /* Turn it into hex digits taking just 4 bits out of 8 for every byte. */ + for (j = 0; j < len; j++) + p[j] = charset[p[j] & 0x0F]; + fclose(fp); +} + #ifdef UTIL_TEST_MAIN #include @@ -336,6 +386,14 @@ void test_string2ll(void) { strcpy(buf,"+1"); assert(string2ll(buf,strlen(buf),&v) == 0); + /* Leading space. */ + strcpy(buf," 1"); + assert(string2ll(buf,strlen(buf),&v) == 0); + + /* Trailing space. */ + strcpy(buf,"1 "); + assert(string2ll(buf,strlen(buf),&v) == 0); + /* May not start with 0. */ strcpy(buf,"01"); assert(string2ll(buf,strlen(buf),&v) == 0);