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