1 #include <stdio.h> 2 #include <assert.h> 3 #include <ctype.h> 4 #include <errno.h> 5 #include <string.h> 6 #include <stdlib.h> 7 #include <stdarg.h> 8 9 #include "memcached.h" 10 11 /* Avoid warnings on solaris, where isspace() is an index into an array, and gcc uses signed chars */ 12 #define xisspace(c) isspace((unsigned char)c) 13 14 bool safe_strtoull(const char *str, uint64_t *out) { 15 assert(out != NULL); 16 errno = 0; 17 *out = 0; 18 char *endptr; 19 unsigned long long ull = strtoull(str, &endptr, 10); 20 if ((errno == ERANGE) || (str == endptr)) { 21 return false; 22 } 23 24 if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) { 25 if ((long long) ull < 0) { 26 /* only check for negative signs in the uncommon case when 27 * the unsigned number is so big that it's negative as a 28 * signed number. */ 29 if (strchr(str, '-') != NULL) { 30 return false; 31 } 32 } 33 *out = ull; 34 return true; 35 } 36 return false; 37 } 38 39 bool safe_strtoll(const char *str, int64_t *out) { 40 assert(out != NULL); 41 errno = 0; 42 *out = 0; 43 char *endptr; 44 long long ll = strtoll(str, &endptr, 10); 45 if ((errno == ERANGE) || (str == endptr)) { 46 return false; 47 } 48 49 if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) { 50 *out = ll; 51 return true; 52 } 53 return false; 54 } 55 56 bool safe_strtoul(const char *str, uint32_t *out) { 57 char *endptr = NULL; 58 unsigned long l = 0; 59 assert(out); 60 assert(str); 61 *out = 0; 62 errno = 0; 63 64 l = strtoul(str, &endptr, 10); 65 if ((errno == ERANGE) || (str == endptr)) { 66 return false; 67 } 68 69 if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) { 70 if ((long) l < 0) { 71 /* only check for negative signs in the uncommon case when 72 * the unsigned number is so big that it's negative as a 73 * signed number. */ 74 if (strchr(str, '-') != NULL) { 75 return false; 76 } 77 } 78 *out = l; 79 return true; 80 } 81 82 return false; 83 } 84 85 bool safe_strtol(const char *str, int32_t *out) { 86 assert(out != NULL); 87 errno = 0; 88 *out = 0; 89 char *endptr; 90 long l = strtol(str, &endptr, 10); 91 if ((errno == ERANGE) || (str == endptr)) { 92 return false; 93 } 94 95 if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) { 96 *out = l; 97 return true; 98 } 99 return false; 100 } 101 102 void vperror(const char *fmt, ...) { 103 int old_errno = errno; 104 char buf[1024]; 105 va_list ap; 106 107 va_start(ap, fmt); 108 if (vsnprintf(buf, sizeof(buf), fmt, ap) == -1) { 109 buf[sizeof(buf) - 1] = '\0'; 110 } 111 va_end(ap); 112 113 errno = old_errno; 114 115 perror(buf); 116 } 117 118 #ifndef HAVE_HTONLL 119 static uint64_t mc_swap64(uint64_t in) { 120 #ifdef ENDIAN_LITTLE 121 /* Little endian, flip the bytes around until someone makes a faster/better 122 * way to do this. */ 123 int64_t rv = 0; 124 int i = 0; 125 for(i = 0; i<8; i++) { 126 rv = (rv << 8) | (in & 0xff); 127 in >>= 8; 128 } 129 return rv; 130 #else 131 /* big-endian machines don't need byte swapping */ 132 return in; 133 #endif 134 } 135 136 uint64_t ntohll(uint64_t val) { 137 return mc_swap64(val); 138 } 139 140 uint64_t htonll(uint64_t val) { 141 return mc_swap64(val); 142 } 143 #endif 144 145