1 /*
2 * utils.c
3 *
4 * $Id: utils.c,v 1.199 2021/08/22 08:11:53 mjl Exp $
5 *
6 * Copyright (C) 2003-2006 Matthew Luckie
7 * Copyright (C) 2006-2011 The University of Waikato
8 * Copyright (C) 2011 Matthew Luckie
9 * Copyright (C) 2012-2015 The Regents of the University of California
10 * Copyright (C) 2015-2021 Matthew Luckie
11 * Author: Matthew Luckie
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation, version 2.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31 #include "internal.h"
32 #include "utils.h"
33
34 #if defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
sockaddr_len(const struct sockaddr * sa)35 int sockaddr_len(const struct sockaddr *sa)
36 {
37 return sa->sa_len;
38 }
39 #else
sockaddr_len(const struct sockaddr * sa)40 int sockaddr_len(const struct sockaddr *sa)
41 {
42 if(sa->sa_family == AF_INET) return sizeof(struct sockaddr_in);
43 if(sa->sa_family == AF_INET6) return sizeof(struct sockaddr_in6);
44
45 #if defined(AF_LINK)
46 if(sa->sa_family == AF_LINK) return sizeof(struct sockaddr_dl);
47 #endif
48
49 #if defined(AF_UNIX) && !defined(_WIN32)
50 if(sa->sa_family == AF_UNIX) return sizeof(struct sockaddr_un);
51 #endif
52
53 return -1;
54 }
55 #endif
56
addr_dup(const int af,const void * addr_in)57 void *addr_dup(const int af, const void *addr_in)
58 {
59 void *addr;
60 size_t size;
61
62 if(af == AF_INET)
63 {
64 size = sizeof(struct in_addr);
65 }
66 else if(af == AF_INET6)
67 {
68 size = sizeof(struct in6_addr);
69 }
70 else return NULL;
71
72 if((addr = malloc(size)) != NULL)
73 {
74 memcpy(addr, addr_in, size);
75 }
76
77 return addr;
78 }
79
sockaddr_dup(const struct sockaddr * sa)80 struct sockaddr *sockaddr_dup(const struct sockaddr *sa)
81 {
82 struct sockaddr *addr;
83 int len;
84
85 if((len = sockaddr_len(sa)) <= 0)
86 {
87 return NULL;
88 }
89
90 if((addr = malloc((size_t)len)) != NULL)
91 {
92 memcpy(addr, sa, (size_t)len);
93 }
94
95 return addr;
96 }
97
sockaddr_compose(struct sockaddr * sa,const int af,const void * addr,const int port)98 int sockaddr_compose(struct sockaddr *sa,
99 const int af, const void *addr, const int port)
100 {
101 socklen_t len;
102 struct sockaddr_in *sin4;
103 struct sockaddr_in6 *sin6;
104
105 assert(port >= 0);
106 assert(port <= 65535);
107
108 if(af == AF_INET)
109 {
110 len = sizeof(struct sockaddr_in);
111 memset(sa, 0, len);
112 sin4 = (struct sockaddr_in *)sa;
113 if(addr != NULL) memcpy(&sin4->sin_addr, addr, sizeof(struct in_addr));
114 sin4->sin_port = htons(port);
115 }
116 else if(af == AF_INET6)
117 {
118 len = sizeof(struct sockaddr_in6);
119 memset(sa, 0, len);
120 sin6 = (struct sockaddr_in6 *)sa;
121 if(addr != NULL) memcpy(&sin6->sin6_addr, addr, sizeof(struct in6_addr));
122 sin6->sin6_port = htons(port);
123 }
124 else return -1;
125
126 #if defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
127 sa->sa_len = len;
128 #endif
129
130 sa->sa_family = af;
131
132 return 0;
133 }
134
sockaddr_compose_un(struct sockaddr * sa,const char * file)135 int sockaddr_compose_un(struct sockaddr *sa, const char *file)
136 {
137 #if defined(AF_UNIX) && !defined(_WIN32)
138 struct sockaddr_un *sn = (struct sockaddr_un *)sa;
139
140 if(strlen(file) + 1 > sizeof(sn->sun_path))
141 return -1;
142 memset(sn, 0, sizeof(struct sockaddr_un));
143 sn->sun_family = AF_UNIX;
144 snprintf(sn->sun_path, sizeof(sn->sun_path), "%s", file);
145
146 #if defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
147 sn->sun_len = sizeof(struct sockaddr_un);
148 #endif
149
150 return 0;
151 #else
152 errno = EINVAL;
153 return -1;
154 #endif
155 }
156
sockaddr_compose_str(struct sockaddr * sa,const char * addr,const int port)157 int sockaddr_compose_str(struct sockaddr *sa, const char *addr, const int port)
158 {
159 struct addrinfo hints, *res, *res0;
160 int rc = -1;
161 void *va;
162
163 memset(&hints, 0, sizeof(struct addrinfo));
164 hints.ai_flags = AI_NUMERICHOST;
165 hints.ai_socktype = SOCK_DGRAM;
166 hints.ai_protocol = IPPROTO_UDP;
167 hints.ai_family = AF_UNSPEC;
168
169 if(getaddrinfo(addr, NULL, &hints, &res0) != 0 || res0 == NULL)
170 return rc;
171
172 for(res = res0; res != NULL; res = res->ai_next)
173 {
174 if(res->ai_family == PF_INET)
175 {
176 va = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
177 sockaddr_compose(sa, AF_INET, va, port);
178 rc = 0;
179 break;
180 }
181 else if(res->ai_family == PF_INET6)
182 {
183 va = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
184 sockaddr_compose(sa, AF_INET6, va, port);
185 rc = 0;
186 break;
187 }
188 }
189
190 freeaddrinfo(res0);
191 return rc;
192 }
193
194 #if defined(AF_LINK) && !defined(_WIN32)
link_tostr(const struct sockaddr_dl * sdl,char * buf,const size_t len)195 static char *link_tostr(const struct sockaddr_dl *sdl,
196 char *buf, const size_t len)
197 {
198 static const char hex[] = "01234567890abcdef";
199 size_t off = 0;
200 uint8_t *u8, i;
201
202 if((off = snprintf(buf, len, "t%d", sdl->sdl_type)) + 1 > len)
203 {
204 return NULL;
205 }
206
207 if(sdl->sdl_nlen == 0 && sdl->sdl_alen == 0)
208 {
209 return buf;
210 }
211 else
212 {
213 buf[off++] = '.';
214 }
215
216 /* check for enough remaining space */
217 if((size_t)(sdl->sdl_nlen + 1 + (3 * sdl->sdl_alen)) > len-off)
218 {
219 return NULL;
220 }
221
222 if(sdl->sdl_nlen > 0)
223 {
224 memcpy(buf+off, sdl->sdl_data, sdl->sdl_nlen);
225 off += sdl->sdl_nlen;
226 if(sdl->sdl_alen > 0)
227 {
228 buf[off++] = '.';
229 }
230 else
231 {
232 buf[off] = '\0';
233 return buf;
234 }
235 }
236
237 if(sdl->sdl_alen > 0)
238 {
239 u8 = (uint8_t *)LLADDR(sdl);
240 for(i=0; i<sdl->sdl_alen; i++)
241 {
242 buf[off++] = hex[u8[i] & 0xf];
243 buf[off++] = hex[(u8[i] >> 4) & 0xf];
244 buf[off++] = ':';
245 }
246 buf[off-1] = '\0';
247 }
248
249 return buf;
250 }
251 #endif
252
sockaddr_tostr(const struct sockaddr * sa,char * buf,const size_t len)253 char *sockaddr_tostr(const struct sockaddr *sa, char *buf, const size_t len)
254 {
255 char addr[128];
256
257 if(sa->sa_family == AF_INET)
258 {
259 #ifndef _WIN32
260 if(inet_ntop(AF_INET, &((const struct sockaddr_in *)sa)->sin_addr,
261 addr, sizeof(addr)) == NULL)
262 {
263 return NULL;
264 }
265 #else
266 if(getnameinfo(sa, sizeof(struct sockaddr_in), addr, sizeof(addr),
267 NULL, 0, NI_NUMERICHOST) != 0)
268 {
269 return NULL;
270 }
271 #endif
272
273 snprintf(buf, len, "%s:%d", addr,
274 ntohs(((const struct sockaddr_in *)sa)->sin_port));
275 }
276 else if(sa->sa_family == AF_INET6)
277 {
278 #ifndef _WIN32
279 if(inet_ntop(AF_INET6, &((const struct sockaddr_in6 *)sa)->sin6_addr,
280 addr, sizeof(addr)) == NULL)
281 {
282 return NULL;
283 }
284 #else
285 if(getnameinfo(sa, sizeof(struct sockaddr_in6), addr, sizeof(addr),
286 NULL, 0, NI_NUMERICHOST) != 0)
287 {
288 return NULL;
289 }
290 #endif
291
292 snprintf(buf, len, "%s.%d", addr,
293 ntohs(((const struct sockaddr_in6 *)sa)->sin6_port));
294 }
295 #if defined(AF_LINK) && !defined(_WIN32)
296 else if(sa->sa_family == AF_LINK)
297 {
298 return link_tostr((const struct sockaddr_dl *)sa, buf, len);
299 }
300 #endif
301 #if defined(AF_UNIX) && !defined(_WIN32)
302 else if(sa->sa_family == AF_UNIX)
303 {
304 snprintf(buf, len, "%s", ((const struct sockaddr_un *)sa)->sun_path);
305 }
306 #endif
307 else
308 {
309 return NULL;
310 }
311
312 return buf;
313 }
314
addr4_cmp(const void * va,const void * vb)315 int addr4_cmp(const void *va, const void *vb)
316 {
317 const struct in_addr *a = (const struct in_addr *)va;
318 const struct in_addr *b = (const struct in_addr *)vb;
319 if(a->s_addr < b->s_addr) return -1;
320 if(a->s_addr > b->s_addr) return 1;
321 return 0;
322 }
323
addr4_human_cmp(const void * va,const void * vb)324 int addr4_human_cmp(const void *va, const void *vb)
325 {
326 const struct in_addr *a = (const struct in_addr *)va;
327 const struct in_addr *b = (const struct in_addr *)vb;
328 uint32_t ua = ntohl(a->s_addr);
329 uint32_t ub = ntohl(b->s_addr);
330 if(ua < ub) return -1;
331 if(ua > ub) return 1;
332 return 0;
333 }
334
addr6_cmp(const void * va,const void * vb)335 int addr6_cmp(const void *va, const void *vb)
336 {
337 const struct in6_addr *a = (const struct in6_addr *)va;
338 const struct in6_addr *b = (const struct in6_addr *)vb;
339 int i;
340
341 #ifndef _WIN32
342 for(i=0; i<4; i++)
343 {
344 if(a->s6_addr32[i] < b->s6_addr32[i]) return -1;
345 if(a->s6_addr32[i] > b->s6_addr32[i]) return 1;
346 }
347 #else
348 for(i=0; i<8; i++)
349 {
350 if(a->u.Word[i] < b->u.Word[i]) return -1;
351 if(a->u.Word[i] > b->u.Word[i]) return 1;
352 }
353 #endif
354
355 return 0;
356 }
357
addr6_human_cmp(const void * va,const void * vb)358 int addr6_human_cmp(const void *va, const void *vb)
359 {
360 const struct in6_addr *a = (const struct in6_addr *)va;
361 const struct in6_addr *b = (const struct in6_addr *)vb;
362 int i;
363
364 #ifndef _WIN32
365 uint32_t ua, ub;
366 for(i=0; i<4; i++)
367 {
368 ua = ntohl(a->s6_addr32[i]);
369 ub = ntohl(b->s6_addr32[i]);
370 if(ua < ub) return -1;
371 if(ua > ub) return 1;
372 }
373 #else
374 uint16_t ua, ub;
375 for(i=0; i<8; i++)
376 {
377 ua = ntohs(a->u.Word[i]);
378 ub = ntohs(b->u.Word[i]);
379 if(ua < ub) return -1;
380 if(ua > ub) return 1;
381 }
382 #endif
383
384 return 0;
385 }
386
387 /*
388 * addr_cmp:
389 * this function is used to provide a sorting order, not for advising the
390 * numerical order of the addresses passed in.
391 */
addr_cmp(const int af,const void * a,const void * b)392 int addr_cmp(const int af, const void *a, const void *b)
393 {
394 if(af == AF_INET) return addr4_cmp(a, b);
395 if(af == AF_INET6) return addr6_cmp(a, b);
396 return 0;
397 }
398
399 #ifndef _WIN32
addr_tostr(int af,const void * addr,char * buf,size_t len)400 const char *addr_tostr(int af, const void *addr, char *buf, size_t len)
401 {
402 return inet_ntop(af, addr, buf, len);
403 }
404 #endif
405
406 #ifdef _WIN32
addr_tostr(int af,const void * addr,char * buf,size_t len)407 const char *addr_tostr(int af, const void *addr, char *buf, size_t len)
408 {
409 struct sockaddr_storage sas;
410
411 if(sockaddr_compose((struct sockaddr *)&sas, af, addr, 0) != 0)
412 return NULL;
413
414 if(getnameinfo((const struct sockaddr *)&sas, sizeof(sas), buf, len,
415 NULL, 0, NI_NUMERICHOST) != 0)
416 {
417 return NULL;
418 }
419
420 return buf;
421 }
422 #endif
423
424 /*
425 * memdup
426 *
427 * duplicate some memory.
428 */
429 #ifndef DMALLOC
memdup(const void * ptr,const size_t len)430 void *memdup(const void *ptr, const size_t len)
431 {
432 void *d;
433 assert(ptr != NULL);
434 if((d = malloc(len)) != NULL)
435 {
436 memcpy(d, ptr, len);
437 }
438 return d;
439 }
440 #endif
441
442 /*
443 * malloc_zero
444 *
445 * allocate some memory, zero it, and return a pointer to it.
446 */
447 #if !defined(DMALLOC) && !defined(HAVE_CALLOC)
malloc_zero(const size_t size)448 void *malloc_zero(const size_t size)
449 {
450 void *ptr;
451 if((ptr = malloc(size)) != NULL)
452 {
453 memset(ptr, 0, size);
454 }
455 return ptr;
456 }
457 #endif
458
459 #ifdef DMALLOC
malloc_zero_dm(const size_t size,const char * file,const int line)460 void *malloc_zero_dm(const size_t size, const char *file, const int line)
461 {
462 void *ptr;
463 if((ptr = dmalloc_malloc(file,line,size,DMALLOC_FUNC_MALLOC,0,0)) != NULL)
464 {
465 memset(ptr, 0, size);
466 }
467 return ptr;
468 }
469 #endif
470
471 #ifndef DMALLOC
realloc_wrap(void ** ptr,size_t len)472 int realloc_wrap(void **ptr, size_t len)
473 {
474 void *tmp;
475
476 if(len != 0)
477 {
478 if(*ptr != NULL)
479 tmp = realloc(*ptr, len);
480 else
481 tmp = malloc(len);
482
483 if(tmp != NULL)
484 {
485 *ptr = tmp;
486 return 0;
487 }
488 }
489 else
490 {
491 if(*ptr != NULL)
492 {
493 free(*ptr);
494 *ptr = NULL;
495 }
496 return 0;
497 }
498
499 return -1;
500 }
501 #endif
502
503 #ifdef DMALLOC
realloc_wrap_dm(void ** ptr,size_t len,const char * file,const int line)504 int realloc_wrap_dm(void **ptr, size_t len, const char *file, const int line)
505 {
506 void *tmp;
507
508 if(len != 0)
509 {
510 if(*ptr != NULL)
511 tmp = dmalloc_realloc(file, line, *ptr, len, DMALLOC_FUNC_REALLOC, 0);
512 else
513 tmp = dmalloc_malloc(file, line, len, DMALLOC_FUNC_MALLOC, 0, 0);
514
515 if(tmp != NULL)
516 {
517 *ptr = tmp;
518 return 0;
519 }
520 }
521 else
522 {
523 if(*ptr != NULL)
524 {
525 dmalloc_free(file, line, *ptr, DMALLOC_FUNC_FREE);
526 *ptr = NULL;
527 }
528 return 0;
529 }
530
531 return -1;
532 }
533 #endif
534
array_findpos(void ** array,int nmemb,const void * item,array_cmp_t cmp)535 int array_findpos(void **array, int nmemb, const void *item, array_cmp_t cmp)
536 {
537 int l, r, k, i;
538
539 if(nmemb == 0)
540 {
541 return -1;
542 }
543
544 l = 0;
545 r = nmemb-1;
546
547 if(r == 0)
548 {
549 if(cmp(array[0], item) == 0)
550 return 0;
551 return -1;
552 }
553
554 while(l <= r)
555 {
556 k = (l + r) / 2;
557 i = cmp(array[k], item);
558 if(i > 0)
559 r = k-1;
560 else if(i < 0)
561 l = k+1;
562 else
563 return k;
564 }
565
566 return -1;
567 }
568
array_find(void ** array,int nmemb,const void * item,array_cmp_t cmp)569 void *array_find(void **array, int nmemb, const void *item, array_cmp_t cmp)
570 {
571 int k = array_findpos(array, nmemb, item, cmp);
572 if(k >= 0)
573 return array[k];
574 return NULL;
575 }
576
577 /*
578 * array_insert_0
579 *
580 * handy function that deals with inserting an element into an array
581 * and then sorting the array, if necessary. using mergesort because
582 * the array is likely to have pre-existing order.
583 */
array_insert_0(void ** array,int * nmemb,void * item,array_cmp_t cmp)584 static int array_insert_0(void **array,int *nmemb,void *item,array_cmp_t cmp)
585 {
586 assert(array != NULL);
587 array[*nmemb] = item;
588 *nmemb = *nmemb + 1;
589 if(cmp != NULL)
590 array_qsort(array, *nmemb, cmp);
591 return 0;
592 }
593
594 #ifndef DMALLOC
array_insert(void *** array,int * nmemb,void * item,array_cmp_t cmp)595 int array_insert(void ***array, int *nmemb, void *item, array_cmp_t cmp)
596 {
597 size_t len;
598 assert(nmemb != NULL); assert(*nmemb >= 0);
599 len = ((*nmemb) + 1) * sizeof(void *);
600 if(realloc_wrap((void **)array, len) != 0)
601 return -1;
602 return array_insert_0(*array, nmemb, item, cmp);
603 }
604
array_insert_gb(void *** array,int * nmemb,int * mmemb,int growby,void * item,array_cmp_t cmp)605 int array_insert_gb(void ***array, int *nmemb, int *mmemb, int growby,
606 void *item, array_cmp_t cmp)
607 {
608 size_t len;
609
610 assert(nmemb != NULL && *nmemb >= 0);
611 if(*nmemb + 1 >= *mmemb)
612 {
613 assert(*mmemb + growby > *nmemb);
614 len = (*mmemb + growby) * sizeof(void *);
615 if(realloc_wrap((void **)array, len) != 0)
616 return -1;
617 *mmemb += growby;
618 }
619
620 return array_insert_0(*array, nmemb, item, cmp);
621 }
622 #endif
623
624 #ifdef DMALLOC
array_insert_dm(void *** array,int * nmemb,void * item,array_cmp_t cmp,const char * file,const int line)625 int array_insert_dm(void ***array, int *nmemb, void *item,
626 array_cmp_t cmp, const char *file, const int line)
627 {
628 size_t len;
629
630 assert(nmemb != NULL && *nmemb >= 0);
631 len = ((*nmemb) + 1) * sizeof(void *);
632 if(realloc_wrap_dm((void **)array, len, file, line) != 0)
633 return -1;
634
635 return array_insert_0(*array, nmemb, item, cmp);
636 }
637
array_insert_gb_dm(void *** array,int * nmemb,int * mmemb,int growby,void * item,array_cmp_t cmp,const char * file,const int line)638 int array_insert_gb_dm(void ***array, int *nmemb, int *mmemb, int growby,
639 void *item, array_cmp_t cmp,
640 const char *file, const int line)
641 {
642 size_t len;
643
644 assert(nmemb != NULL && *nmemb >= 0);
645 if(*nmemb + 1 >= *mmemb)
646 {
647 assert(*mmemb + growby > *nmemb);
648 len = (*mmemb + growby) * sizeof(void *);
649 if(realloc_wrap_dm((void **)array, len, file, line) != 0)
650 return -1;
651 *mmemb += growby;
652 }
653
654 return array_insert_0(*array, nmemb, item, cmp);
655 }
656 #endif
657
array_remove(void ** array,int * nmemb,int p)658 void array_remove(void **array, int *nmemb, int p)
659 {
660 assert(p >= 0 && p < *nmemb);
661 memmove(array+p, array+p+1, ((*nmemb)-p-1) * sizeof(void *));
662 *nmemb = *nmemb - 1;
663 return;
664 }
665
array_swap(void ** a,int i,int j)666 static void array_swap(void **a, int i, int j)
667 {
668 void *item = a[i];
669 a[i] = a[j];
670 a[j] = item;
671 return;
672 }
673
array_qsort_3(void ** a,array_cmp_t cmp,int l,int r)674 static void array_qsort_3(void **a, array_cmp_t cmp, int l, int r)
675 {
676 int lt, gt, i, rc;
677 void *c;
678
679 if(l >= r)
680 return;
681
682 lt = l;
683 gt = r;
684 i = l;
685 c = a[l];
686
687 while(i <= gt)
688 {
689 rc = a[i] != c ? cmp(a[i], c) : 0;
690 if(rc < 0)
691 array_swap(a, lt++, i++);
692 else if(rc > 0)
693 array_swap(a, i, gt--);
694 else
695 i++;
696 }
697
698 array_qsort_3(a, cmp, l, lt-1);
699 array_qsort_3(a, cmp, gt+1, r);
700 return;
701 }
702
array_qsort(void ** a,int n,array_cmp_t cmp)703 void array_qsort(void **a, int n, array_cmp_t cmp)
704 {
705 array_qsort_3(a, cmp, 0, n-1);
706 return;
707 }
708
709 #ifndef _WIN32
gettimeofday_wrap(struct timeval * tv)710 void gettimeofday_wrap(struct timeval *tv)
711 {
712 struct timezone tz;
713 gettimeofday(tv, &tz);
714 return;
715 }
716 #endif
717
718 #ifdef _WIN32
gettimeofday_wrap(struct timeval * tv)719 void gettimeofday_wrap(struct timeval *tv)
720 {
721 FILETIME ft;
722 uint64_t u64;
723 GetSystemTimeAsFileTime(&ft);
724 u64 = ft.dwHighDateTime;
725 u64 <<= 32;
726 u64 |= ft.dwLowDateTime;
727
728 u64 /= 10;
729 u64 -= 11644473600000000LL;
730 tv->tv_sec = (long)(u64 / 1000000UL);
731 tv->tv_usec = (long)(u64 % 1000000UL);
732 return;
733 }
734 #endif
735
timeval_cmp(const struct timeval * a,const struct timeval * b)736 int timeval_cmp(const struct timeval *a, const struct timeval *b)
737 {
738 if(a->tv_sec < b->tv_sec) return -1;
739 if(a->tv_sec > b->tv_sec) return 1;
740
741 if(a->tv_usec < b->tv_usec) return -1;
742 if(a->tv_usec > b->tv_usec) return 1;
743
744 return 0;
745 }
746
timeval_handlewrap(struct timeval * tv)747 static void timeval_handlewrap(struct timeval *tv)
748 {
749 if(tv->tv_usec >= 1000000)
750 {
751 tv->tv_sec++;
752 tv->tv_usec -= 1000000;
753 }
754 else if(tv->tv_usec < 0)
755 {
756 tv->tv_sec--;
757 tv->tv_usec += 1000000;
758 }
759 return;
760 }
761
timeval_add_cs(struct timeval * out,const struct timeval * in,int cs)762 void timeval_add_cs(struct timeval *out, const struct timeval *in, int cs)
763 {
764 out->tv_sec = in->tv_sec + (cs / 100);
765 out->tv_usec = in->tv_usec + ((cs % 100) * 10000);
766 timeval_handlewrap(out);
767 return;
768 }
769
timeval_add_ms(struct timeval * out,const struct timeval * in,int msec)770 void timeval_add_ms(struct timeval *out, const struct timeval *in, int msec)
771 {
772 out->tv_sec = in->tv_sec + (msec / 1000);
773 out->tv_usec = in->tv_usec + ((msec % 1000) * 1000);
774 timeval_handlewrap(out);
775 return;
776 }
777
timeval_add_us(struct timeval * out,const struct timeval * in,int us)778 void timeval_add_us(struct timeval *out, const struct timeval *in, int us)
779 {
780 out->tv_sec = in->tv_sec + (us / 1000000);
781 out->tv_usec = in->tv_usec + (us % 1000000);
782 timeval_handlewrap(out);
783 return;
784 }
785
timeval_add_s(struct timeval * out,const struct timeval * in,int s)786 void timeval_add_s(struct timeval *out, const struct timeval *in, int s)
787 {
788 out->tv_sec = in->tv_sec + s;
789 out->tv_usec = in->tv_usec;
790 return;
791 }
792
timeval_sub_us(struct timeval * out,const struct timeval * in,int us)793 void timeval_sub_us(struct timeval *out, const struct timeval *in, int us)
794 {
795 out->tv_sec = in->tv_sec - (us / 1000000);
796 out->tv_usec = in->tv_usec - (us % 1000000);
797 timeval_handlewrap(out);
798 return;
799 }
800
timeval_add_tv(struct timeval * tv,const struct timeval * add)801 void timeval_add_tv(struct timeval *tv, const struct timeval *add)
802 {
803 assert(add->tv_sec >= 0);
804 assert(add->tv_usec >= 0);
805
806 tv->tv_sec += add->tv_sec;
807 tv->tv_usec += add->tv_usec;
808
809 /* check for overflow */
810 if(tv->tv_usec > 1000000)
811 {
812 tv->tv_sec++;
813 tv->tv_usec -= 1000000;
814 }
815
816 return;
817 }
818
timeval_add_tv3(struct timeval * out,const struct timeval * a,const struct timeval * b)819 void timeval_add_tv3(struct timeval *out,
820 const struct timeval *a, const struct timeval *b)
821 {
822 assert(a->tv_sec >= 0); assert(a->tv_usec >= 0);
823 assert(b->tv_sec >= 0); assert(b->tv_usec >= 0);
824
825 out->tv_sec = a->tv_sec + b->tv_sec;
826 out->tv_usec = a->tv_usec + b->tv_usec;
827 if(out->tv_usec > 1000000)
828 {
829 out->tv_sec++;
830 out->tv_usec -= 1000000;
831 }
832
833 return;
834 }
835
timeval_diff_tv(struct timeval * rtt,const struct timeval * from,const struct timeval * to)836 void timeval_diff_tv(struct timeval *rtt,
837 const struct timeval *from, const struct timeval *to)
838 {
839 rtt->tv_sec = to->tv_sec - from->tv_sec;
840 rtt->tv_usec = to->tv_usec - from->tv_usec;
841
842 if(rtt->tv_usec < 0)
843 {
844 rtt->tv_sec--;
845 rtt->tv_usec += 1000000;
846 }
847
848 return;
849 }
850
851 /*
852 * timeval_diff_ms
853 * return the millisecond difference between the two timevals.
854 * a - b
855 */
timeval_diff_ms(const struct timeval * a,const struct timeval * b)856 int timeval_diff_ms(const struct timeval *a, const struct timeval *b)
857 {
858 struct timeval tv;
859 timeval_diff_tv(&tv, b, a);
860 return ((int)tv.tv_sec * 1000) + ((int)tv.tv_usec / 1000);
861 }
862
863 /*
864 * timeval_diff_us
865 * return the microsecond difference between the two timevals.
866 * a - b
867 */
timeval_diff_us(const struct timeval * a,const struct timeval * b)868 int timeval_diff_us(const struct timeval *a, const struct timeval *b)
869 {
870 struct timeval tv;
871 timeval_diff_tv(&tv, b, a);
872 return ((int)tv.tv_sec * 1000000) + tv.tv_usec;
873 }
874
timeval_cpy(struct timeval * dst,const struct timeval * src)875 void timeval_cpy(struct timeval *dst, const struct timeval *src)
876 {
877 memcpy(dst, src, sizeof(struct timeval));
878 return;
879 }
880
timeval_inrange_us(const struct timeval * a,const struct timeval * b,int c)881 int timeval_inrange_us(const struct timeval *a, const struct timeval *b, int c)
882 {
883 struct timeval tv;
884 int rc = timeval_cmp(a, b);
885 if(rc < 0)
886 {
887 timeval_add_us(&tv, a, c);
888 if(timeval_cmp(&tv, b) < 0)
889 return 0;
890 }
891 else if(rc > 0)
892 {
893 timeval_add_us(&tv, b, c);
894 if(timeval_cmp(&tv, a) < 0)
895 return 0;
896 }
897 return 1;
898 }
899
timeval_tostr_us(const struct timeval * rtt,char * str,size_t len)900 char *timeval_tostr_us(const struct timeval *rtt, char *str, size_t len)
901 {
902 uint32_t usec = (rtt->tv_sec * 1000000) + rtt->tv_usec;
903 snprintf(str, len, "%d.%03d", usec / 1000, usec % 1000);
904 return str;
905 }
906
907 #ifndef _WIN32
fcntl_unset(const int fd,const int flags)908 int fcntl_unset(const int fd, const int flags)
909 {
910 int i;
911
912 if((i = fcntl(fd, F_GETFL, 0)) == -1)
913 {
914 return -1;
915 }
916
917 if(fcntl(fd, F_SETFL, i & (~flags)) == -1)
918 {
919 return -1;
920 }
921
922 return 0;
923 }
924
fcntl_set(const int fd,const int flags)925 int fcntl_set(const int fd, const int flags)
926 {
927 int i;
928
929 if((i = fcntl(fd, F_GETFL, 0)) == -1)
930 {
931 return -1;
932 }
933
934 if(fcntl(fd, F_SETFL, i | flags) == -1)
935 {
936 return -1;
937 }
938
939 return 0;
940 }
941 #endif
942
json_esc(const char * in,char * out,size_t len)943 char *json_esc(const char *in, char *out, size_t len)
944 {
945 size_t off = 0;
946
947 while(*in != '\0')
948 {
949 if(isprint(*in) == 0)
950 break;
951
952 switch(*in)
953 {
954 case '"':
955 if(off + 2 >= len)
956 goto done;
957 out[off++] = '\\';
958 out[off++] = '"';
959 break;
960
961 case '\\':
962 if(off + 2 >= len)
963 goto done;
964 out[off++] = '\\';
965 out[off++] = '\\';
966 break;
967
968 default:
969 out[off++] = *in;
970 break;
971 }
972 in++;
973 }
974 out[off++] = '\0';
975
976 done:
977 return out;
978 }
979
string_isprint(const char * str,const size_t len)980 int string_isprint(const char *str, const size_t len)
981 {
982 size_t i = 0;
983
984 for(i=0; i<len; i++)
985 {
986 if(isprint((int)str[i]) != 0)
987 {
988 continue;
989 }
990 else if(str[i] == '\0')
991 {
992 break;
993 }
994 else return 0;
995 }
996
997 return 1;
998 }
999
string_toupper(char * buf,size_t len,const char * in)1000 char *string_toupper(char *buf, size_t len, const char *in)
1001 {
1002 size_t off = 0;
1003 while(in[off] != '\0' && len - off > 1)
1004 {
1005 buf[off] = toupper(in[off]);
1006 off++;
1007 }
1008 buf[off] = '\0';
1009 return buf;
1010 }
1011
string_tolong(const char * str,long * l)1012 int string_tolong(const char *str, long *l)
1013 {
1014 char *endptr;
1015
1016 errno = 0;
1017 *l = strtol(str, &endptr, 0);
1018 if(*l == 0)
1019 {
1020 if(errno == EINVAL)
1021 return -1;
1022 }
1023 else if(*l == LONG_MIN || *l == LONG_MAX)
1024 {
1025 if(errno == ERANGE)
1026 return -1;
1027 }
1028
1029 return 0;
1030 }
1031
string_tollong(const char * str,long long * l)1032 int string_tollong(const char *str, long long *l)
1033 {
1034 char *endptr;
1035
1036 errno = 0;
1037 *l = strtoll(str, &endptr, 0);
1038 if(*l == 0)
1039 {
1040 if(errno == EINVAL)
1041 return -1;
1042 }
1043 else if(*l == LLONG_MIN || *l == LLONG_MAX)
1044 {
1045 if(errno == ERANGE)
1046 return -1;
1047 }
1048
1049 return 0;
1050 }
1051
1052 /*
1053 * string_isalnum
1054 *
1055 * scan the word to establish if it is made up entirely of
1056 * alphanumeric characters.
1057 */
string_isalnum(const char * str)1058 int string_isalnum(const char *str)
1059 {
1060 if(*str == '\0')
1061 return 0;
1062 while(isalnum(*str) != 0)
1063 str++;
1064 if(*str == '\0')
1065 return 1;
1066 return 0;
1067 }
1068
1069 /*
1070 * string_isdigit
1071 *
1072 * scan the word to establish if it is made up entirely of digits,
1073 * with no + or - at the start.
1074 */
string_isdigit(const char * str)1075 int string_isdigit(const char *str)
1076 {
1077 if(*str == '\0')
1078 return 0;
1079 while(isdigit(*str) != 0)
1080 str++;
1081 if(*str == '\0')
1082 return 1;
1083 return 0;
1084 }
1085
1086 /*
1087 * string_isalpha
1088 *
1089 * scan the string to establish if it is made up entirely of alphabetic
1090 * characters.
1091 */
string_isalpha(const char * str)1092 int string_isalpha(const char *str)
1093 {
1094 if(*str == '\0')
1095 return 0;
1096 while(isalpha(*str) != 0)
1097 str++;
1098 if(*str == '\0')
1099 return 1;
1100 return 0;
1101 }
1102
1103 /*
1104 * string_isnumber
1105 *
1106 * scan the word to establish if it an integer.
1107 */
string_isnumber(const char * str)1108 int string_isnumber(const char *str)
1109 {
1110 int i = 1;
1111
1112 if(str[0] != '-' && str[0] != '+' && isdigit((int)str[0]) == 0)
1113 {
1114 return 0;
1115 }
1116
1117 while(str[i] != '\0')
1118 {
1119 if(isdigit((int)str[i]) != 0)
1120 {
1121 i++;
1122 continue;
1123 }
1124
1125 return 0;
1126 }
1127
1128 return 1;
1129 }
1130
1131 /*
1132 * string_isfloat
1133 *
1134 * scan the word to establish if it is a float.
1135 */
string_isfloat(const char * str)1136 int string_isfloat(const char *str)
1137 {
1138 int seen_dp = 0;
1139 int i = 1;
1140
1141 if(str[0] != '-' && str[0] != '+' && isdigit((int)str[0]) == 0)
1142 {
1143 if(str[0] == '.')
1144 {
1145 seen_dp = 1;
1146 }
1147 else return 0;
1148 }
1149
1150 while(str[i] != '\0')
1151 {
1152 if(isdigit((int)str[i]) != 0)
1153 {
1154 i++;
1155 continue;
1156 }
1157 else if(str[i] == '.')
1158 {
1159 /* if the decimal point has already been seen */
1160 if(seen_dp == 1)
1161 {
1162 return 0;
1163 }
1164
1165 i++;
1166 seen_dp = 1;
1167 continue;
1168 }
1169 return 0;
1170 }
1171
1172 return 1;
1173 }
1174
1175 /*
1176 * string_nextword
1177 *
1178 * scan for the next word occurance in the string, after the current
1179 * word. if there is no other word after this one, return NULL.
1180 */
string_nextword(char * buf)1181 char *string_nextword(char *buf)
1182 {
1183 /* scan for a start of a word */
1184 while(*buf != '\0' && isspace((int)*buf) == 0)
1185 {
1186 buf++;
1187 }
1188
1189 if(*buf == '\0')
1190 {
1191 return NULL;
1192 }
1193 *buf = '\0';
1194 buf++;
1195
1196 /* now scan for the end of the word */
1197 while(*buf != '\0' && isspace((int)*buf) != 0)
1198 {
1199 buf++;
1200 }
1201
1202 if(*buf == '\0')
1203 {
1204 return NULL;
1205 }
1206
1207 return buf;
1208 }
1209
string_findlc(const char * str,const char * find)1210 const char *string_findlc(const char *str, const char *find)
1211 {
1212 const char *sp = str;
1213 int i;
1214
1215 assert(*find != '\0');
1216 for(;;)
1217 {
1218 for(i=0; find[i] != '\0'; i++)
1219 if(tolower((int)sp[i]) != find[i])
1220 break;
1221 if(find[i] == '\0')
1222 return sp;
1223 if(sp[i] == '\0')
1224 break;
1225 sp++;
1226 }
1227
1228 return NULL;
1229 }
1230
1231 /*
1232 * string_nullterm
1233 *
1234 * null terminate the string pointed to by buf at the first occurance of
1235 * a character in the delim string.
1236 *
1237 * if null termination occurs, this function returns a pointer to the first
1238 * byte of the buf (i.e. the buf parameter passed)
1239 */
string_nullterm(char * buf,const char * delim,char ** next)1240 char *string_nullterm(char *buf, const char *delim, char **next)
1241 {
1242 const char *dtmp;
1243 char *tmp;
1244
1245 if(delim == NULL || *delim == '\0' || (tmp = buf) == NULL)
1246 return NULL;
1247
1248 while(*tmp != '\0')
1249 {
1250 dtmp = delim;
1251
1252 while(*dtmp != '\0')
1253 {
1254 if(*tmp != *dtmp)
1255 {
1256 dtmp++;
1257 continue;
1258 }
1259
1260 *tmp = '\0';
1261 if(next != NULL)
1262 {
1263 tmp++;
1264 *next = tmp;
1265 }
1266 return buf;
1267 }
1268
1269 tmp++;
1270 }
1271
1272 if(next != NULL)
1273 *next = NULL;
1274 return buf;
1275 }
1276
string_nullterm_char(char * buf,const char delim,char ** next)1277 char *string_nullterm_char(char *buf, const char delim, char **next)
1278 {
1279 char *tmp;
1280
1281 if((tmp = buf) == NULL)
1282 return NULL;
1283
1284 while(*tmp != '\0')
1285 {
1286 if(*tmp == delim)
1287 {
1288 *tmp = '\0';
1289 if(next != NULL)
1290 {
1291 tmp++;
1292 *next = tmp;
1293 }
1294 return buf;
1295 }
1296
1297 tmp++;
1298 }
1299
1300 if(next != NULL)
1301 *next = NULL;
1302 return buf;
1303 }
1304
string_lastof(char * str,const char * delim)1305 char *string_lastof(char *str, const char *delim)
1306 {
1307 char *lastof = NULL;
1308 const char *d;
1309 int i;
1310
1311 if(delim == NULL || *delim == '\0' || str == NULL)
1312 return NULL;
1313
1314 for(i=0; str[i] != '\0'; i++)
1315 {
1316 for(d = delim; *d != '\0'; d++)
1317 {
1318 if(str[i] == *d)
1319 {
1320 lastof = &str[i];
1321 break;
1322 }
1323 }
1324 }
1325
1326 return lastof;
1327 }
1328
string_lastof_char(char * str,const char delim)1329 char *string_lastof_char(char *str, const char delim)
1330 {
1331 char *lastof = NULL;
1332 int i;
1333
1334 if(str == NULL)
1335 return NULL;
1336
1337 for(i=0; str[i] != '\0'; i++)
1338 {
1339 if(str[i] == delim)
1340 {
1341 lastof = &str[i];
1342 }
1343 }
1344
1345 return lastof;
1346 }
1347
string_firstof_char(char * str,const char delim)1348 char *string_firstof_char(char *str, const char delim)
1349 {
1350 char *firstof = NULL;
1351 int i;
1352
1353 if(str == NULL)
1354 return NULL;
1355
1356 for(i=0; str[i] != '\0'; i++)
1357 {
1358 if(str[i] == delim)
1359 {
1360 firstof = &str[i];
1361 break;
1362 }
1363 }
1364
1365 return firstof;
1366 }
1367
string_concat(char * str,size_t len,size_t * off,const char * fs,...)1368 char *string_concat(char *str, size_t len, size_t *off, const char *fs, ...)
1369 {
1370 va_list ap;
1371 size_t left;
1372 int wc;
1373
1374 if(len < *off)
1375 return NULL;
1376
1377 if((left = len - *off) == 0)
1378 return str;
1379
1380 va_start(ap, fs);
1381 wc = vsnprintf(str + *off, left, fs, ap);
1382 va_end(ap);
1383
1384 if(wc < 0)
1385 return NULL;
1386
1387 *off = *off + ((size_t)wc < left ? wc : left);
1388 return str;
1389 }
1390
1391 /*
1392 * string_addrport
1393 *
1394 * given an input string, return the ip address / name in the first part
1395 * (if present) and the port number in the second. do some basic sanity
1396 * checking as well.
1397 */
string_addrport(const char * in,char ** first,int * port)1398 int string_addrport(const char *in, char **first, int *port)
1399 {
1400 char *ptr, *dup = NULL, *first_tmp = NULL;
1401 long lo;
1402
1403 if(string_isnumber(in))
1404 {
1405 if(string_tolong(in, &lo) == -1 || lo < 1 || lo > 65535)
1406 goto err;
1407 *first = NULL;
1408 *port = lo;
1409 return 0;
1410 }
1411
1412 if((dup = strdup(in)) == NULL)
1413 goto err;
1414
1415 if(dup[0] == '[')
1416 {
1417 string_nullterm_char(dup, ']', &ptr);
1418 if(ptr == NULL || *ptr != ':' || (first_tmp = strdup(dup+1)) == NULL)
1419 goto err;
1420 ptr++;
1421 }
1422 else
1423 {
1424 string_nullterm_char(dup, ':', &ptr);
1425 if(ptr == NULL || (first_tmp = strdup(dup)) == NULL)
1426 goto err;
1427 }
1428
1429 if(string_tolong(ptr, &lo) != 0 || lo < 1 || lo > 65535)
1430 goto err;
1431
1432 *first = first_tmp;
1433 *port = lo;
1434 free(dup);
1435 return 0;
1436
1437 err:
1438 if(first_tmp != NULL) free(first_tmp);
1439 if(dup != NULL) free(dup);
1440 return -1;
1441 }
1442
1443 #ifndef NDEBUG
string_isdash(const char * str)1444 int string_isdash(const char *str)
1445 {
1446 if(str[0] == '-' && str[1] == '\0')
1447 return 1;
1448 return 0;
1449 }
1450 #endif
1451
mem_concat(void * dst,const void * src,size_t len,size_t * off,size_t size)1452 void mem_concat(void *dst,const void *src,size_t len,size_t *off,size_t size)
1453 {
1454 assert(*off + len <= size);
1455 memcpy(((uint8_t *)dst) + *off, src, len);
1456 *off += len;
1457 return;
1458 }
1459
ishex(char c)1460 int ishex(char c)
1461 {
1462 if((c >= '0' && c <= '9') ||
1463 (c >= 'a' && c <= 'f') ||
1464 (c >= 'A' && c <= 'F'))
1465 {
1466 return 1;
1467 }
1468 return 0;
1469 }
1470
hex2byte(char a,char b)1471 uint8_t hex2byte(char a, char b)
1472 {
1473 uint8_t out;
1474
1475 assert(ishex(a));
1476 assert(ishex(b));
1477
1478 if(a <= '9') out = (((int)a - (int)'0') << 4);
1479 else if(a <= 'F') out = (((int)a - (int)'A' + 10) << 4);
1480 else out = (((int)a - (int)'a' + 10) << 4);
1481
1482 if(b <= '9') out |= ((int)b - (int)'0');
1483 else if(b <= 'F') out |= ((int)b - (int)'A' + 10);
1484 else out |= ((int)b - (int)'a' + 10);
1485
1486 return out;
1487 }
1488
byte2hex(uint8_t byte,char * a)1489 void byte2hex(uint8_t byte, char *a)
1490 {
1491 static const char hex[] = "01234567890abcdef";
1492 a[0] = hex[(byte >> 4)];
1493 a[1] = hex[byte & 0x0f];
1494 return;
1495 }
1496
bytes_ntohs(const uint8_t * bytes)1497 uint16_t bytes_ntohs(const uint8_t *bytes)
1498 {
1499 uint16_t u16;
1500 memcpy(&u16, bytes, 2);
1501 return ntohs(u16);
1502 }
1503
bytes_ntohl(const uint8_t * bytes)1504 uint32_t bytes_ntohl(const uint8_t *bytes)
1505 {
1506 uint32_t u32;
1507 memcpy(&u32, bytes, 4);
1508 return ntohl(u32);
1509 }
1510
bytes_htons(uint8_t * bytes,uint16_t u16)1511 void bytes_htons(uint8_t *bytes, uint16_t u16)
1512 {
1513 uint16_t tmp = htons(u16);
1514 memcpy(bytes, &tmp, 2);
1515 return;
1516 }
1517
bytes_htonl(uint8_t * bytes,uint32_t u32)1518 void bytes_htonl(uint8_t *bytes, uint32_t u32)
1519 {
1520 uint32_t tmp = htonl(u32);
1521 memcpy(bytes, &tmp, 4);
1522 return;
1523 }
1524
read_wrap(const int fd,void * ptr,size_t * rc_out,const size_t rt)1525 int read_wrap(const int fd, void *ptr, size_t *rc_out, const size_t rt)
1526 {
1527 uint8_t *buf;
1528 int ret = 0;
1529 ssize_t r;
1530 size_t rc;
1531
1532 assert(rt > 0);
1533 assert(ptr != NULL);
1534
1535 buf = (uint8_t *)ptr;
1536
1537 for(rc = 0; rc < rt; rc += r)
1538 {
1539 if((r = read(fd, buf+rc, rt-rc)) < 0)
1540 {
1541 if(errno == EINTR)
1542 {
1543 r = 0;
1544 continue;
1545 }
1546 ret = -1;
1547 break;
1548 }
1549 else if(r == 0)
1550 {
1551 ret = -2;
1552 break;
1553 }
1554 }
1555
1556 if(rc_out != NULL)
1557 {
1558 *rc_out = rc;
1559 }
1560
1561 return ret;
1562 }
1563
write_wrap(const int fd,const void * ptr,size_t * wc_out,const size_t wt)1564 int write_wrap(const int fd, const void *ptr, size_t *wc_out, const size_t wt)
1565 {
1566 int ret = 0;
1567 ssize_t w;
1568 size_t wc;
1569
1570 assert(wt > 0);
1571 assert(ptr != NULL);
1572
1573 for(wc = 0; wc < wt; wc += w)
1574 {
1575 if((w = write(fd, ((const uint8_t *)ptr)+wc, wt-wc)) < 0)
1576 {
1577 if(errno == EINTR)
1578 {
1579 w = 0;
1580 continue;
1581 }
1582 ret = -1;
1583 break;
1584 }
1585 }
1586
1587 if(wc_out != NULL)
1588 {
1589 *wc_out = wc;
1590 }
1591
1592 return ret;
1593 }
1594
1595 /*
1596 * mkdir_wrap
1597 *
1598 * iteratively call mkdir until the full path has been created
1599 */
1600 #ifndef _WIN32
mkdir_wrap(const char * path,mode_t mode)1601 int mkdir_wrap(const char *path, mode_t mode)
1602 #else
1603 int mkdir_wrap(const char *path)
1604 #endif
1605 {
1606 char *d = NULL;
1607 char *ptr;
1608
1609 /* ensure there is actually a path to create ... */
1610 if(path[0] == '\0' || (path[0] == '/' && path[1] == '\0'))
1611 {
1612 return 0;
1613 }
1614
1615 /* make a duplicate copy of the path that we are going to create */
1616 if((d = strdup(path)) == NULL)
1617 {
1618 goto err;
1619 }
1620 ptr = d;
1621
1622 /* don't need to create the root directory ... */
1623 if(ptr[0] == '/') ptr++;
1624
1625 while(ptr[0] != '\0')
1626 {
1627 if(ptr[0] == '/')
1628 {
1629 /* temporarily replace the path delimeter */
1630 ptr[0] = '\0';
1631
1632 if(mkdir(d, mode) != 0 && errno != EEXIST)
1633 {
1634 goto err;
1635 }
1636
1637 ptr[0] = '/';
1638 }
1639
1640 ptr++;
1641 }
1642
1643 /* create the last directory in the path */
1644 if(ptr[-1] != '/')
1645 {
1646 if(mkdir(d, mode) != 0 && errno != EEXIST)
1647 {
1648 goto err;
1649 }
1650 }
1651
1652 free(d);
1653 return 0;
1654
1655 err:
1656 if(d != NULL) free(d);
1657 return -1;
1658 }
1659
1660 /*
1661 * fstat_mtime
1662 *
1663 * simple utility function that gets the mtime field from
1664 * a fstat call as a time_t.
1665 */
fstat_mtime(int fd,time_t * mtime)1666 int fstat_mtime(int fd, time_t *mtime)
1667 {
1668 struct stat sb;
1669
1670 if(fstat(fd, &sb) != 0)
1671 {
1672 return -1;
1673 }
1674
1675 *mtime = sb.st_mtime;
1676 return 0;
1677 }
1678
1679 /*
1680 * stat_mtime
1681 *
1682 * simple utility function that gets the mtime field from
1683 * a stat call as a time_t.
1684 */
stat_mtime(const char * filename,time_t * mtime)1685 int stat_mtime(const char *filename, time_t *mtime)
1686 {
1687 struct stat sb;
1688
1689 if(stat(filename, &sb) != 0)
1690 {
1691 return -1;
1692 }
1693
1694 *mtime = sb.st_mtime;
1695 return 0;
1696 }
1697
1698 #if defined(HAVE_SYSCTL)
sysctl_wrap(int * mib,u_int len,void ** buf,size_t * size)1699 int sysctl_wrap(int *mib, u_int len, void **buf, size_t *size)
1700 {
1701 if(sysctl(mib, len, NULL, size, NULL, 0) != 0)
1702 {
1703 return -1;
1704 }
1705
1706 if(*size == 0)
1707 {
1708 *buf = NULL;
1709 return 0;
1710 }
1711
1712 if((*buf = malloc(*size)) == NULL)
1713 {
1714 return -1;
1715 }
1716
1717 if(sysctl(mib, len, *buf, size, NULL, 0) != 0)
1718 {
1719 free(*buf);
1720 return -1;
1721 }
1722
1723 return 0;
1724 }
1725 #endif
1726
random_seed(void)1727 void random_seed(void)
1728 {
1729 #if defined(_WIN32) || defined(HAVE_ARC4RANDOM)
1730 return;
1731 #else
1732 struct timeval tv;
1733 gettimeofday_wrap(&tv);
1734 srandom(tv.tv_usec);
1735 return;
1736 #endif
1737 }
1738
random_u32(uint32_t * r)1739 int random_u32(uint32_t *r)
1740 {
1741 #if defined(_WIN32)
1742 unsigned int ui;
1743 if(rand_s(&ui) != 0)
1744 return -1;
1745 *r = ui;
1746 #elif defined(HAVE_ARC4RANDOM)
1747 *r = arc4random();
1748 #else
1749 *r = random();
1750 #endif
1751 return 0;
1752 }
1753
random_u16(uint16_t * r)1754 int random_u16(uint16_t *r)
1755 {
1756 #ifdef _WIN32
1757 unsigned int ui;
1758 if(rand_s(&ui) != 0)
1759 return -1;
1760 *r = ui;
1761 #elif defined(HAVE_ARC4RANDOM)
1762 *r = arc4random();
1763 #else
1764 *r = random();
1765 #endif
1766 return 0;
1767 }
1768
random_u8(uint8_t * r)1769 int random_u8(uint8_t *r)
1770 {
1771 #ifdef _WIN32
1772 unsigned int ui;
1773 if(rand_s(&ui) != 0)
1774 return -1;
1775 *r = ui;
1776 #elif defined(HAVE_ARC4RANDOM)
1777 *r = arc4random();
1778 #else
1779 *r = random();
1780 #endif
1781 return 0;
1782 }
1783
1784 /*
1785 * countbits32
1786 *
1787 * count the number of bits set in v. first published by Peter Wegner in
1788 * CACM 3 (1960), 322.
1789 */
countbits32(uint32_t v)1790 int countbits32(uint32_t v)
1791 {
1792 int c;
1793 for(c=0; v != 0; c++)
1794 v &= v - 1;
1795 return c;
1796 }
1797
1798 /* Fisher-Yates shuffle */
shuffle16(uint16_t * array,int len)1799 int shuffle16(uint16_t *array, int len)
1800 {
1801 int x, n = len;
1802 uint32_t k;
1803 uint16_t tmp;
1804
1805 while(n > 1)
1806 {
1807 n--;
1808 if(random_u32(&k) != 0)
1809 return -1;
1810
1811 x = k % (n+1);
1812
1813 tmp = array[x];
1814 array[x] = array[n];
1815 array[n] = tmp;
1816 }
1817
1818 return 0;
1819 }
1820
1821 /* Fisher-Yates shuffle */
shuffle32(uint32_t * array,int len)1822 int shuffle32(uint32_t *array, int len)
1823 {
1824 int n = len;
1825 uint32_t k, tmp;
1826
1827 while(n > 1)
1828 {
1829 n--;
1830 if(random_u32(&k) != 0)
1831 return -1;
1832 k %= n+1;
1833
1834 tmp = array[k];
1835 array[k] = array[n];
1836 array[n] = tmp;
1837 }
1838
1839 return 0;
1840 }
1841
min_array(int * array,int len)1842 int min_array(int *array, int len)
1843 {
1844 int x, i;
1845 x = array[0];
1846 for(i=1; i<len; i++)
1847 if(x > array[i])
1848 x = array[i];
1849 return x;
1850 }
1851
in_cksum(const void * buf,size_t len)1852 uint16_t in_cksum(const void *buf, size_t len)
1853 {
1854 uint16_t *w = (uint16_t *)buf;
1855 size_t l = len;
1856 int sum = 0;
1857
1858 while(l > 1)
1859 {
1860 sum += *w++;
1861 l -= 2;
1862 }
1863
1864 if(l != 0)
1865 {
1866 sum += ((uint8_t *)w)[0];
1867 }
1868
1869 sum = (sum >> 16) + (sum & 0xffff);
1870 sum += (sum >> 16);
1871
1872 return ~sum;
1873 }
1874
1875 /*
1876 * uudecode_4
1877 *
1878 * decode four ascii characters to form up to 3 binary bytes.
1879 */
uudecode_4(uint8_t * out,const char * in,size_t c)1880 static int uudecode_4(uint8_t *out, const char *in, size_t c)
1881 {
1882 char a, b;
1883
1884 if(c == 0)
1885 return -1;
1886
1887 if(in[0] >= '!' && in[0] <= '`')
1888 a = in[0];
1889 else return -1;
1890
1891 if(in[1] >= '!' && in[1] <= '`')
1892 b = in[1];
1893 else return -1;
1894
1895 out[0] = (((a - 32) & 0x3f) << 2 & 0xfc) | (((b - 32) & 0x3f) >> 4 & 0x3);
1896
1897 if(in[2] >= '!' && in[2] <= '`')
1898 a = in[2];
1899 else return -1;
1900
1901 if(c > 1)
1902 out[1] = (((b - 32) & 0x3f) << 4 & 0xf0) | (((a - 32) & 0x3f) >> 2 & 0xf);
1903
1904 if(in[3] >= '!' && in[3] <= '`')
1905 b = in[3];
1906 else return -1;
1907
1908 if(c > 2)
1909 out[2] = (((a - 32) & 0x3f) << 6 & 0xc0) | ((b - 32) & 0x3f);
1910
1911 return 0;
1912 }
1913
1914 /*
1915 * uudecode_line
1916 *
1917 * decode a uuencoded line into binary bytes.
1918 */
uudecode_line(const char * in,size_t ilen,uint8_t * out,size_t * olen)1919 int uudecode_line(const char *in, size_t ilen, uint8_t *out, size_t *olen)
1920 {
1921 size_t i, j, o;
1922
1923 if(ilen == 0)
1924 goto err;
1925
1926 /* EOF */
1927 if(in[0] == '`')
1928 {
1929 *olen = 0;
1930 return 0;
1931 }
1932
1933 /* figure out the number of binary bytes that should be found */
1934 if(in[0] >= '!' && in[0] <= '`')
1935 o = in[0] - 32;
1936 else goto err;
1937
1938 /* make sure we can uudecode to the buffer provided */
1939 if(o > *olen)
1940 goto err;
1941
1942 i = 0;
1943 j = 1;
1944
1945 for(;;)
1946 {
1947 /* there needs to be at least four characters remaining */
1948 if(ilen - j < 4)
1949 goto err;
1950
1951 /* decode 4 characters into 3 bytes */
1952 if(uudecode_4(out+i, in+j, o-i) != 0)
1953 goto err;
1954
1955 /* next block of 4 characters */
1956 j += 4;
1957
1958 /* advance */
1959 if(o-i > 3)
1960 i += 3;
1961 else break;
1962 }
1963
1964 *olen = o;
1965 return 0;
1966
1967 err:
1968 return -1;
1969 }
1970
uudecode(const char * in,size_t len)1971 void *uudecode(const char *in, size_t len)
1972 {
1973 uint8_t *out = NULL;
1974 size_t i, j, k, x;
1975
1976 /* if the first character is a ` (EOF) there is nothing to decode */
1977 if(in[0] == '`')
1978 return NULL;
1979
1980 i = 0;
1981 x = 0;
1982
1983 /* first, figure out how much memory to allocate */
1984 for(;;)
1985 {
1986 /* make sure character is valid */
1987 if(in[i] < '!' || in[i] > '`')
1988 {
1989 goto err;
1990 }
1991
1992 /* check for EOF */
1993 if(in[i] == '`')
1994 break;
1995
1996 /* number of uuencoded bytes on this line */
1997 j = in[i++] - 32;
1998
1999 /* number of ascii bytes required */
2000 k = j + (j/3);
2001 if((k % 4) != 0)
2002 {
2003 k /= 4;
2004 k++;
2005 k *= 4;
2006 }
2007
2008 /* advance to the end of the line */
2009 if(len - i < k+1 || in[i+k] != '\n')
2010 {
2011 goto err;
2012 }
2013 i += k + 1;
2014 x += j;
2015 }
2016
2017 /* make sure the uuencoded data ends with a new line */
2018 if(len - i < 1 || in[i+1] != '\n')
2019 {
2020 goto err;
2021 }
2022
2023 if((out = malloc(x)) == NULL)
2024 goto err;
2025
2026 i = 0;
2027 j = 0;
2028 for(;;)
2029 {
2030 /* number of uuencoded bytes on this line */
2031 k = in[i++] - 32;
2032 for(;;)
2033 {
2034 /* there needs to be at least four characters remaining */
2035 if(len - i < 4)
2036 goto err;
2037
2038 /* decode the next four */
2039 if(uudecode_4(out+j, in+i, x-j) != 0)
2040 goto err;
2041
2042 i += 4;
2043
2044 if(k > 3)
2045 {
2046 j += 3;
2047 k -= 3;
2048 }
2049 else
2050 {
2051 j += k;
2052 break;
2053 }
2054 }
2055
2056 /* advance to next line */
2057 if(in[i] != '\n')
2058 goto err;
2059 i++;
2060
2061 if(j == x)
2062 break;
2063 }
2064
2065 return out;
2066
2067 err:
2068 if(out != NULL) free(out);
2069 return NULL;
2070 }
2071
uuencode_3(uint8_t * out,uint8_t a,uint8_t b,uint8_t c)2072 static void uuencode_3(uint8_t *out, uint8_t a, uint8_t b, uint8_t c)
2073 {
2074 uint8_t t;
2075
2076 out[0] = (t = ((a >> 2) & 0x3f)) != 0 ? t + 32 : '`';
2077 out[1] = (t = (((a << 4) | ((b >> 4) & 0xf)) & 0x3f)) != 0 ? t + 32 : '`';
2078 out[2] = (t = (((b << 2) | ((c >> 6) & 0x3)) & 0x3f)) != 0 ? t + 32 : '`';
2079 out[3] = (t = (c & 0x3f)) != 0 ? t + 32 : '`';
2080
2081 return;
2082 }
2083
uuencode_len(size_t ilen,size_t * complete,size_t * leftover)2084 size_t uuencode_len(size_t ilen, size_t *complete, size_t *leftover)
2085 {
2086 size_t len;
2087 size_t complete_lines;
2088 size_t leftover_bytes;
2089
2090 assert(ilen != 0);
2091
2092 /*
2093 * figure out how many complete lines there are,
2094 * and then how many leftover bytes there are
2095 */
2096 complete_lines = ilen / 45;
2097 leftover_bytes = ilen % 45;
2098
2099 /*
2100 * an input line of 45 characters is transformed into an 60 character
2101 * sequence, with the length encoded as a character at the start, and
2102 * a new-line character at the end of the line
2103 */
2104 len = (complete_lines * 62);
2105
2106 /*
2107 * if there are leftover bytes, then each group of three characters
2108 * will take four output bytes. if the number of leftover bytes is not
2109 * a multiple of three, then they are encoded in a 4 character sequence.
2110 * finally, there's a length character at the start and a new line at the
2111 * end.
2112 */
2113 if(leftover_bytes != 0)
2114 {
2115 len += ((leftover_bytes / 3) * 4);
2116 if((leftover_bytes % 3) > 0)
2117 {
2118 len += 4;
2119 }
2120 len += 2;
2121 }
2122
2123 /* allocate the end-of-data bytes */
2124 len += 2;
2125
2126 if(complete != NULL) *complete = complete_lines;
2127 if(leftover != NULL) *leftover = leftover_bytes;
2128
2129 return len;
2130 }
2131
2132 /*
2133 * uuencode_bytes
2134 *
2135 * take an input buffer, and an offset into that buffer, and encode as
2136 * much of it as possible into the output buffer
2137 */
uuencode_bytes(const uint8_t * in,size_t len,size_t * off,uint8_t * out,size_t olen)2138 size_t uuencode_bytes(const uint8_t *in, size_t len, size_t *off,
2139 uint8_t *out, size_t olen)
2140 {
2141 static const uint8_t b[] = {
2142 2, 6,6,6, 10,10,10, 14,14,14, 18,18,18, 22,22,22, 26,26,26, 30,30,30,
2143 34,34,34, 38,38,38, 42,42,42, 46,46,46, 50,50,50, 54,54,54, 58,58,58,
2144 62,62,62};
2145 size_t ooff = 0, i, lc, bb;
2146
2147 assert(*off < len);
2148
2149 for(;;)
2150 {
2151 /* determine how many characters will be written out this time */
2152 if(len - *off >= 45)
2153 lc = 45;
2154 else
2155 lc = len - *off;
2156
2157 /* determine how many bytes will be required */
2158 bb = b[lc];
2159 if(*off + lc == len)
2160 bb += 2;
2161
2162 /* if not enough space, then stop now */
2163 if(olen - ooff < bb)
2164 break;
2165
2166 /* write out the line */
2167 out[ooff++] = 32 + lc;
2168 for(i=0; i+3<=lc; i+=3)
2169 {
2170 uuencode_3(out+ooff, in[*off], in[*off+1], in[*off+2]);
2171 *off += 3;
2172 ooff += 4;
2173 }
2174 if(i != lc)
2175 {
2176 lc -= i;
2177 uuencode_3(out+ooff, in[*off], lc == 2 ? in[*off+1] : 0, 0);
2178 *off += lc;
2179 ooff += 4;
2180 }
2181 out[ooff++] = '\n';
2182
2183 /* encode eof */
2184 if(*off == len)
2185 {
2186 out[ooff++] = '`';
2187 out[ooff++] = '\n';
2188 break;
2189 }
2190 }
2191
2192 return ooff;
2193 }
2194
uuencode(const uint8_t * in,size_t ilen,uint8_t ** out,size_t * olen)2195 int uuencode(const uint8_t *in, size_t ilen, uint8_t **out, size_t *olen)
2196 {
2197 uint8_t *ptr;
2198 size_t len;
2199 size_t complete_lines;
2200 size_t leftover_bytes;
2201 size_t i, j;
2202
2203 /* figure out how large the allocated buffer needs to be */
2204 len = uuencode_len(ilen, &complete_lines, &leftover_bytes);
2205 assert(len != 0);
2206
2207 /* allocate memory to encode the data to */
2208 if((ptr = malloc(len)) == NULL)
2209 return -1;
2210 *out = ptr;
2211 *olen = len;
2212
2213 /* encode all complete lines */
2214 for(i=0; i<complete_lines; i++)
2215 {
2216 *ptr = (32 + 45); ptr++;
2217 for(j=0; j<15; j++)
2218 {
2219 uuencode_3(ptr, in[0], in[1], in[2]);
2220 in += 3;
2221 ptr += 4;
2222 }
2223 *ptr = '\n'; ptr++;
2224 }
2225
2226 /* encode the last line */
2227 if(leftover_bytes != 0)
2228 {
2229 /* encode groups of 3 input bytes */
2230 *ptr = (32 + leftover_bytes); ptr++;
2231 for(j=0; j<leftover_bytes/3; j++)
2232 {
2233 uuencode_3(ptr, in[0], in[1], in[2]);
2234 in += 3;
2235 ptr += 4;
2236 }
2237
2238 /* if there are one or two straggling bytes left, encode those */
2239 if((leftover_bytes % 3) > 0)
2240 {
2241 uuencode_3(ptr, in[0], (leftover_bytes % 3) == 2 ? in[1] : 0, 0);
2242 ptr += 4;
2243 }
2244
2245 *ptr = '\n'; ptr++;
2246 }
2247
2248 /* this line has no data -- uuencode EOF */
2249 *ptr = '`'; ptr++;
2250 *ptr = '\n';
2251
2252 return 0;
2253 }
2254
byteswap16(const uint16_t word)2255 uint16_t byteswap16(const uint16_t word)
2256 {
2257 return ((word >> 8) | (word << 8));
2258 }
2259
byteswap32(const uint32_t word)2260 uint32_t byteswap32(const uint32_t word)
2261 {
2262 return ((word << 24) | (word >> 24) |
2263 ((word & 0xff00) << 8) | ((word >> 8) & 0xff00));
2264 }
2265
fd_lines(int fd,int (* func)(char *,void *),void * param)2266 int fd_lines(int fd, int (*func)(char *, void *), void *param)
2267 {
2268 char *readbuf = NULL;
2269 size_t readbuf_len, readbuf_off;
2270 size_t start, end, off;
2271 int rc = -1;
2272 ssize_t ss;
2273
2274 readbuf_len = 8192; readbuf_off = 0;
2275 if((readbuf = malloc(readbuf_len)) == NULL)
2276 goto done;
2277
2278 while((ss = read(fd, readbuf+readbuf_off, readbuf_len-readbuf_off-1)) >= 0)
2279 {
2280 start = 0; off = 0;
2281 end = readbuf_off + ss;
2282
2283 while(off <= end)
2284 {
2285 if(off == end && ss != 0)
2286 break;
2287 if(readbuf[off] == '\n' || (off == end && start < off))
2288 {
2289 readbuf[off] = '\0';
2290 if(func(readbuf+start, param) != 0)
2291 goto done;
2292 start = ++off;
2293 }
2294 else
2295 {
2296 ++off;
2297 }
2298 }
2299
2300 if(ss == 0)
2301 {
2302 rc = 0;
2303 break;
2304 }
2305 else if(start == 0)
2306 {
2307 readbuf_len += 8192;
2308 readbuf_off = off;
2309 if(realloc_wrap((void **)&readbuf, readbuf_len) != 0)
2310 goto done;
2311 }
2312 else
2313 {
2314 memmove(readbuf, readbuf+start, end - start);
2315 readbuf_off = end - start;
2316 }
2317 }
2318
2319 done:
2320 if(readbuf != NULL) free(readbuf);
2321 return rc;
2322 }
2323
2324 /* process a text file, line by line */
file_lines(const char * filename,int (* func)(char *,void *),void * param)2325 int file_lines(const char *filename, int (*func)(char *, void *), void *param)
2326 {
2327 int rc, fd = -1;
2328 if((fd = open(filename, O_RDONLY)) < 0)
2329 return -1;
2330 rc = fd_lines(fd, func, param);
2331 close(fd);
2332 return rc;
2333 }
2334
offt_tostr(char * buf,size_t len,off_t off,int lz,char c)2335 char *offt_tostr(char *buf, size_t len, off_t off, int lz, char c)
2336 {
2337 char sp[8];
2338
2339 assert(lz >= 0);
2340
2341 if(sizeof(int) == sizeof(off_t))
2342 {
2343 if(lz == 0)
2344 snprintf(sp, sizeof(sp), "%%%c", c);
2345 else
2346 snprintf(sp, sizeof(sp), "%%0%d%c", lz, c);
2347 }
2348 else if(sizeof(long int) == sizeof(off_t))
2349 {
2350 if(lz == 0)
2351 snprintf(sp, sizeof(sp), "%%l%c", c);
2352 else
2353 snprintf(sp, sizeof(sp), "%%0%dl%c", lz, c);
2354 }
2355 else if(sizeof(long long int) == sizeof(off_t))
2356 {
2357 if(lz == 0)
2358 snprintf(sp, sizeof(sp), "%%ll%c", c);
2359 else
2360 snprintf(sp, sizeof(sp), "%%0%dll%c", lz, c);
2361 }
2362 else
2363 {
2364 return NULL;
2365 }
2366
2367 snprintf(buf, len, sp, off);
2368 return buf;
2369 }
2370