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