#include #include #include #include #include #include #include #include "memcached.h" static char *uriencode_map[256]; static char uriencode_str[768]; void uriencode_init(void) { int x; char *str = uriencode_str; for (x = 0; x < 256; x++) { if (isalnum(x) || x == '-' || x == '.' || x == '_' || x == '~') { uriencode_map[x] = NULL; } else { snprintf(str, 4, "%%%02X", x); uriencode_map[x] = str; str += 3; /* lobbing off the \0 is fine */ } } } bool uriencode(const char *src, char *dst, const size_t srclen, const size_t dstlen) { int x; size_t d = 0; for (x = 0; x < srclen; x++) { if (d + 4 >= dstlen) return false; if (uriencode_map[(unsigned char) src[x]] != NULL) { memcpy(&dst[d], uriencode_map[(unsigned char) src[x]], 3); d += 3; } else { dst[d] = src[x]; d++; } } dst[d] = '\0'; return true; } /* Avoid warnings on solaris, where isspace() is an index into an array, and gcc uses signed chars */ #define xisspace(c) isspace((unsigned char)c) bool safe_strtoull(const char *str, uint64_t *out) { assert(out != NULL); errno = 0; *out = 0; char *endptr; unsigned long long ull = strtoull(str, &endptr, 10); if ((errno == ERANGE) || (str == endptr)) { return false; } if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) { if ((long long) ull < 0) { /* only check for negative signs in the uncommon case when * the unsigned number is so big that it's negative as a * signed number. */ if (strchr(str, '-') != NULL) { return false; } } *out = ull; return true; } return false; } bool safe_strtoll(const char *str, int64_t *out) { assert(out != NULL); errno = 0; *out = 0; char *endptr; long long ll = strtoll(str, &endptr, 10); if ((errno == ERANGE) || (str == endptr)) { return false; } if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) { *out = ll; return true; } return false; } bool safe_strtoul(const char *str, uint32_t *out) { char *endptr = NULL; unsigned long l = 0; assert(out); assert(str); *out = 0; errno = 0; l = strtoul(str, &endptr, 10); if ((errno == ERANGE) || (str == endptr)) { return false; } if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) { if ((long) l < 0) { /* only check for negative signs in the uncommon case when * the unsigned number is so big that it's negative as a * signed number. */ if (strchr(str, '-') != NULL) { return false; } } *out = l; return true; } return false; } bool safe_strtol(const char *str, int32_t *out) { assert(out != NULL); errno = 0; *out = 0; char *endptr; long l = strtol(str, &endptr, 10); if ((errno == ERANGE) || (str == endptr)) { return false; } if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) { *out = l; return true; } return false; } bool safe_strtod(const char *str, double *out) { assert(out != NULL); errno = 0; *out = 0; char *endptr; double d = strtod(str, &endptr); if ((errno == ERANGE) || (str == endptr)) { return false; } if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) { *out = d; return true; } return false; } void vperror(const char *fmt, ...) { int old_errno = errno; char buf[1024]; va_list ap; va_start(ap, fmt); if (vsnprintf(buf, sizeof(buf), fmt, ap) == -1) { buf[sizeof(buf) - 1] = '\0'; } va_end(ap); errno = old_errno; perror(buf); } #ifndef HAVE_HTONLL static uint64_t mc_swap64(uint64_t in) { #ifdef ENDIAN_LITTLE /* Little endian, flip the bytes around until someone makes a faster/better * way to do this. */ int64_t rv = 0; int i = 0; for(i = 0; i<8; i++) { rv = (rv << 8) | (in & 0xff); in >>= 8; } return rv; #else /* big-endian machines don't need byte swapping */ return in; #endif } uint64_t ntohll(uint64_t val) { return mc_swap64(val); } uint64_t htonll(uint64_t val) { return mc_swap64(val); } #endif