]> git.saurik.com Git - redis.git/blobdiff - src/util.c
Scripting: require at least one argument for redis.call().
[redis.git] / src / util.c
index 5712241b15df9748c9114512b335e4e7611a35ba..e3224f5012f90fc48fc25ee4965733ee15d03ec8 100644 (file)
@@ -1,9 +1,14 @@
+#include "fmacros.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <limits.h>
 #include <math.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <float.h>
+
 #include "util.h"
 
 /* Glob-style pattern matching. */
@@ -207,8 +212,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 +278,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))
@@ -315,7 +320,7 @@ int d2string(char *buf, size_t len, double value) {
          * integer printing function that is much faster. */
         double min = -4503599627370495; /* (2^52)-1 */
         double max = 4503599627370496; /* -(2^52) */
-        if (val > min && val < max && value == ((double)((long long)value)))
+        if (value > min && value < max && value == ((double)((long long)value)))
             len = ll2string(buf,len,(long long)value);
         else
 #endif
@@ -325,6 +330,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 <assert.h>
 
@@ -336,6 +387,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);