1 // =====================================================================
2 //
3 // util.cxx
4 //
5 // Author: Stelios Buonanos, M0GLD, Dave Freese, W1HKJ
6 // Copyright: 2010
7 //
8 // This file is part of FLCLUSTER.
9 //
10 // This is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // This software is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 //
23 // =====================================================================
24 
25 #include <string.h>
26 #include <time.h>
27 
28 #include "config.h"
29 #include "util.h"
30 #ifdef __MINGW32__
31 #  include "compat.h"
32 #endif
33 
34 /* Return the smallest power of 2 not less than n */
ceil2(uint32_t n)35 uint32_t ceil2(uint32_t n)
36 {
37 	--n;
38 	n |= n >> 1;
39 	n |= n >> 2;
40 	n |= n >> 4;
41 	n |= n >> 8;
42 	n |= n >> 16;
43 	return n + 1;
44 }
45 
46 /* Return the largest power of 2 not greater than n */
floor2(uint32_t n)47 uint32_t floor2(uint32_t n)
48 {
49 	n |= n >> 1;
50 	n |= n >> 2;
51 	n |= n >> 4;
52 	n |= n >> 8;
53 	n |= n >> 16;
54 	return n - (n >> 1);
55 }
56 
57 #include <stdlib.h>
ver2int(const char * version)58 unsigned long ver2int(const char* version)
59 {
60 	unsigned long v;
61 	char* p;
62 
63 	v = (unsigned long)(strtod(version, &p) * 1e7 + 0.5);
64 	while (*p)
65 		v += *p++;
66 
67 	return v;
68 }
69 
70 #if !HAVE_STRCASESTR
71 #  include <ctype.h>
72 // from git 1.6.1.2 compat/strcasestr.c
strcasestr(const char * haystack,const char * needle)73 char *strcasestr(const char *haystack, const char *needle)
74 {
75 	int nlen = strlen(needle);
76 	int hlen = strlen(haystack) - nlen + 1;
77 	int i;
78 
79 	for (i = 0; i < hlen; i++) {
80 		int j;
81 		for (j = 0; j < nlen; j++) {
82 			unsigned char c1 = haystack[i+j];
83 			unsigned char c2 = needle[j];
84 			if (toupper(c1) != toupper(c2))
85 				goto next;
86 		}
87 		return (char *) haystack + i;
88 	next: ;
89 	}
90 	return NULL;
91 }
92 #endif // !HAVE_STRCASESTR
93 
94 #if !HAVE_STRLCPY
95 // from git 1.6.1.2 compat/strcasestr.c
strlcpy(char * dest,const char * src,size_t size)96 size_t strlcpy(char *dest, const char *src, size_t size)
97 {
98 	size_t ret = strlen(src);
99 
100 	if (size) {
101 		size_t len = (ret >= size) ? size - 1 : ret;
102 		memcpy(dest, src, len);
103 		dest[len] = '\0';
104 	}
105 	return ret;
106 }
107 #endif // !HAVE_STRLCPY
108 
109 #ifdef __WIN32__
set_cloexec(int fd,unsigned char v)110 int set_cloexec(int fd, unsigned char v) { return 0; }
111 #else
112 #  include <unistd.h>
113 #  include <fcntl.h>
set_cloexec(int fd,unsigned char v)114 int set_cloexec(int fd, unsigned char v)
115 {
116 	int f = fcntl(fd, F_GETFD);
117 	return f == -1 ? f : fcntl(fd, F_SETFD, (v ? f | FD_CLOEXEC : f & ~FD_CLOEXEC));
118 }
119 #endif // __WIN32__
120 
121 
set_nonblock(int fd,unsigned char v)122 int set_nonblock(int fd, unsigned char v)
123 {
124 #ifndef __WIN32__
125 	int f = fcntl(fd, F_GETFL);
126 	return f == -1 ? f : fcntl(fd, F_SETFL, (v ? f | O_NONBLOCK : f & ~O_NONBLOCK));
127 #else // __WIN32__
128 	u_long v_ = (u_long)v;
129 	errno = 0;
130 	if (ioctlsocket(fd, FIONBIO, &v_) == SOCKET_ERROR) {
131 		errno = WSAGetLastError();
132 		return -1;
133 	}
134 	else
135 		return 0;
136 #endif // __WIN32__
137 }
138 
139 #ifndef __WIN32__
140 #  include <sys/types.h>
141 #  include <sys/socket.h>
142 #  include <netinet/in.h>
143 #  include <netinet/tcp.h>
144 #endif
set_nodelay(int fd,unsigned char v)145 int set_nodelay(int fd, unsigned char v)
146 {
147 	int val = v;
148 	return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&val, sizeof(val));
149 }
150 
151 
152 #ifdef __WIN32__
153 #  include <ws2tcpip.h>
154 #endif
155 
get_bufsize(int fd,int dir,int * len)156 int get_bufsize(int fd, int dir, int* len)
157 {
158 	socklen_t optlen = sizeof(*len);
159 	return getsockopt(fd, SOL_SOCKET, (dir == 0 ? SO_RCVBUF : SO_SNDBUF),
160 					  (char*)len, &optlen);
161 }
set_bufsize(int fd,int dir,int len)162 int set_bufsize(int fd, int dir, int len)
163 {
164 	return setsockopt(fd, SOL_SOCKET, (dir == 0 ? SO_RCVBUF : SO_SNDBUF),
165 					  (const char*)&len, sizeof(len));
166 }
167 
168 #ifndef __WIN32__
169 #include <pthread.h>
170 #include <signal.h>
171 #ifndef NSIG
172 #  define NSIG 64
173 #endif
174 static size_t nsig = 0;
175 static struct sigaction* sigact = 0;
176 static pthread_mutex_t sigmutex = PTHREAD_MUTEX_INITIALIZER;
177 #endif
178 
save_signals(void)179 void save_signals(void)
180 {
181 #ifndef __WIN32__
182 	pthread_mutex_lock(&sigmutex);
183 	if (!sigact)
184 		sigact = new struct sigaction[NSIG];
185 	for (nsig = 1; nsig <= NSIG; nsig++)
186 		if (sigaction(nsig, NULL, &sigact[nsig-1]) == -1)
187 			break;
188 	pthread_mutex_unlock(&sigmutex);
189 #endif
190 }
191 
restore_signals(void)192 void restore_signals(void)
193 {
194 #ifndef __WIN32__
195 	pthread_mutex_lock(&sigmutex);
196 	for (size_t i = 1; i <= nsig; i++)
197 		sigaction(i, &sigact[i-1], NULL);
198 	delete [] sigact;
199 	sigact = 0;
200 	nsig = 0;
201 	pthread_mutex_unlock(&sigmutex);
202 #endif
203 }
204 
205 
simple_hash_data(const unsigned char * buf,size_t len,uint32_t code)206 uint32_t simple_hash_data(const unsigned char* buf, size_t len, uint32_t code)
207 {
208 	for (size_t i = 0; i < len; i++)
209 		code = ((code << 4) | (code >> (32 - 4))) ^ (uint32_t)buf[i];
210 
211 	return code;
212 }
simple_hash_str(const unsigned char * str,uint32_t code)213 uint32_t simple_hash_str(const unsigned char* str, uint32_t code)
214 {
215 	while (*str)
216 		code = ((code << 4) | (code >> (32 - 4))) ^ (uint32_t)*str++;
217 	return code;
218 }
219 
220 #include <vector>
221 #include <climits>
222 
223 static const char hexsym[] = "0123456789ABCDEF";
224 static std::vector<char>* hexbuf;
str2hex(const unsigned char * str,size_t len)225 const char* str2hex(const unsigned char* str, size_t len)
226 {
227 	if (unlikely(len == 0))
228 		return "";
229 	if (unlikely(!hexbuf)) {
230 		hexbuf = new std::vector<char>;
231 		hexbuf->reserve(192);
232 	}
233 	if (unlikely(hexbuf->size() < len * 3))
234 		hexbuf->resize(len * 3);
235 
236 	char* p = &(*hexbuf)[0];
237 	size_t i;
238 	for (i = 0; i < len; i++) {
239 		*p++ = hexsym[str[i] >> 4];
240 		*p++ = hexsym[str[i] & 0xF];
241 		*p++ = ' ';
242 	}
243 	*(p - 1) = '\0';
244 
245 	return &(*hexbuf)[0];
246 }
247 
str2hex(const char * str,size_t len)248 const char* str2hex(const char* str, size_t len)
249 {
250 	return str2hex((const unsigned char*)str, len ? len : strlen(str));
251 }
252 
253 static std::vector<char>* binbuf;
uint2bin(unsigned u,size_t len)254 const char* uint2bin(unsigned u, size_t len)
255 {
256 	if (unlikely(len == 0))
257 		len = sizeof(u) * CHAR_BIT;
258 
259 	if (unlikely(!binbuf)) {
260 		binbuf = new std::vector<char>;
261 		binbuf->reserve(sizeof(u) * CHAR_BIT);
262 	}
263 	if (unlikely(binbuf->size() < len + 1))
264 		binbuf->resize(len + 1);
265 
266 	for (size_t i = 0; i < len; i++) {
267 		(*binbuf)[len - i - 1] = '0' + (u & 1);
268 		u >>= 1;
269 	}
270 	(*binbuf)[len] = '\0';
271 
272 	return &(*binbuf)[0];
273 }
274 
MilliSleep(long msecs)275 void MilliSleep(long msecs)
276 {
277 #ifndef __WIN32__
278 	struct timespec tv;
279 	tv.tv_sec = msecs / 1000;
280 	tv.tv_nsec = (msecs - tv.tv_sec * 1000) * 1000000L;
281 	nanosleep(&tv, NULL);
282 #else
283 	Sleep(msecs);
284 #endif
285 
286 }
287 
288 //======================================================================
289 
ucase(std::string & s)290 void ucase(std::string &s)
291 {
292 	for (size_t n = 0; n < s.length(); n++) s[n] = toupper(s[n]);
293 }
294 
strip_spaces(std::string & s)295 void strip_spaces(std::string &s)
296 {
297 	while (!s.empty() && s[0] == ' ') s.erase(0,1);
298 	while (!s.empty() && s[s.length() - 1] == ' ') s.erase(s.length() - 1, 1);
299 }
300 
strip_leading_zeros(std::string & s)301 void strip_leading_zeros(std::string &s)
302 {
303 	while(!s.empty() && s[0] == '0') s.erase(0,1);
304 }
305 
strip_lfs(std::string & s)306 void strip_lfs(std::string &s)
307 {
308 	while (!s.empty() && s[0] == '\n') s.erase(0,1);
309 	while (!s.empty() && s[s.length() - 1] == '\n') s.erase(s.length() - 1, 1);
310 }
311 
wordwrap(std::string & s,int cnt)312 std::string wordwrap(std::string &s, int cnt)
313 {
314 	static std::string nustr;
315 	nustr.clear();
316 	int cntr = 1;
317 	char c;
318 	for (size_t n = 0; n < s.length(); n++) {
319 		c = s[n];
320 		if (c == '\n') {nustr += c; cntr = 1; }
321 		else if (c == ' ' && cntr >= cnt) {
322 			nustr += '\n';
323 			cntr = 1;
324 		}
325 		else { nustr += c; cntr++; }
326 	}
327 	return nustr;
328 }
329 
330 #ifndef HAVE_STRNLEN
331 
strnlen(const char * cPtr,int limit)332 int strnlen(const char *cPtr, int limit)
333 {
334 	int count = 0;
335 	if(!cPtr || limit < 1) return 0;
336 	while((limit-- > 0) && *cPtr++) count++;
337 	return count;
338 }
339 
340 #endif
341