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