]> git.ipfire.org Git - people/ms/strongswan.git/blame - src/libstrongswan/utils/utils.h
travis: --disable-aikgen in "all" tests
[people/ms/strongswan.git] / src / libstrongswan / utils / utils.h
CommitLineData
552cc11b 1/*
766141bc 2 * Copyright (C) 2008-2014 Tobias Brunner
552cc11b
MW
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
552cc11b
MW
15 */
16
17/**
bca34c37
TB
18 * @defgroup utils_i utils
19 * @{ @ingroup utils
552cc11b
MW
20 */
21
22#ifndef UTILS_H_
23#define UTILS_H_
24
25#include <sys/types.h>
26#include <stdlib.h>
27#include <stddef.h>
3f310c0d 28#include <sys/time.h>
0be12e35
MW
29#include <arpa/inet.h>
30#include <string.h>
552cc11b 31
bca34c37 32#include "enum.h"
ba10cd3c 33#include "utils/strerror.h"
552cc11b 34
eab241fb
AS
35/**
36 * strongSwan program return codes
37 */
38#define SS_RC_LIBSTRONGSWAN_INTEGRITY 64
39#define SS_RC_DAEMON_INTEGRITY 65
3646c8a1 40#define SS_RC_INITIALIZATION_FAILED 66
eab241fb 41
5d8306de
AS
42#define SS_RC_FIRST SS_RC_LIBSTRONGSWAN_INTEGRITY
43#define SS_RC_LAST SS_RC_INITIALIZATION_FAILED
44
552cc11b
MW
45/**
46 * Number of bits in a byte
47 */
48#define BITS_PER_BYTE 8
49
50/**
51 * Default length for various auxiliary text buffers
52 */
53#define BUF_LEN 512
54
55/**
a2a28d90 56 * General purpose boolean type.
552cc11b 57 */
a2a28d90
TB
58#ifdef HAVE_STDBOOL_H
59# include <stdbool.h>
60#else
61# ifndef HAVE__BOOL
62# define _Bool signed char
63# endif /* HAVE__BOOL */
64# define bool _Bool
65# define false 0
66# define true 1
67# define __bool_true_false_are_defined 1
68#endif /* HAVE_STDBOOL_H */
69#ifndef FALSE
70# define FALSE false
71#endif /* FALSE */
72#ifndef TRUE
73# define TRUE true
74#endif /* TRUE */
75
76/**
77 * Helper function that compares two strings for equality
78 */
79static inline bool streq(const char *x, const char *y)
80{
81 return strcmp(x, y) == 0;
82}
552cc11b
MW
83
84/**
985dcab1 85 * Helper function that compares two strings for equality, length limited
552cc11b 86 */
985dcab1
TB
87static inline bool strneq(const char *x, const char *y, size_t len)
88{
89 return strncmp(x, y, len) == 0;
90}
552cc11b 91
f460facd
TB
92/**
93 * Helper function that checks if a string starts with a given prefix
94 */
95static inline bool strpfx(const char *x, const char *prefix)
96{
97 return strneq(x, prefix, strlen(prefix));
98}
99
63176bbc 100/**
a2a28d90 101 * Helper function that compares two strings for equality ignoring case
63176bbc 102 */
a2a28d90
TB
103static inline bool strcaseeq(const char *x, const char *y)
104{
105 return strcasecmp(x, y) == 0;
106}
63176bbc 107
7a3e0a63 108/**
985dcab1 109 * Helper function that compares two strings for equality ignoring case, length limited
7a3e0a63 110 */
985dcab1
TB
111static inline bool strncaseeq(const char *x, const char *y, size_t len)
112{
113 return strncasecmp(x, y, len) == 0;
114}
7a3e0a63 115
32a145fd
TB
116/**
117 * Helper function that checks if a string starts with a given prefix
118 */
119static inline bool strcasepfx(const char *x, const char *prefix)
120{
121 return strncaseeq(x, prefix, strlen(prefix));
122}
123
1038d9fe
MW
124/**
125 * NULL-safe strdup variant
126 */
753ca22f
TB
127static inline char *strdupnull(const char *s)
128{
129 return s ? strdup(s) : NULL;
130}
1038d9fe 131
552cc11b 132/**
985dcab1 133 * Helper function that compares two binary blobs for equality
552cc11b 134 */
985dcab1
TB
135static inline bool memeq(const void *x, const void *y, size_t len)
136{
137 return memcmp(x, y, len) == 0;
138}
552cc11b
MW
139
140/**
141 * Macro gives back larger of two values.
142 */
e822fc57
TB
143#define max(x,y) ({ \
144 typeof(x) _x = (x); \
145 typeof(y) _y = (y); \
146 _x > _y ? _x : _y; })
147
552cc11b
MW
148
149/**
150 * Macro gives back smaller of two values.
151 */
e822fc57
TB
152#define min(x,y) ({ \
153 typeof(x) _x = (x); \
154 typeof(y) _y = (y); \
155 _x < _y ? _x : _y; })
552cc11b
MW
156
157/**
158 * Call destructor of an object, if object != NULL
159 */
160#define DESTROY_IF(obj) if (obj) (obj)->destroy(obj)
161
162/**
163 * Call offset destructor of an object, if object != NULL
164 */
165#define DESTROY_OFFSET_IF(obj, offset) if (obj) obj->destroy_offset(obj, offset);
166
167/**
168 * Call function destructor of an object, if object != NULL
169 */
170#define DESTROY_FUNCTION_IF(obj, fn) if (obj) obj->destroy_function(obj, fn);
171
172/**
173 * Debug macro to follow control flow
174 */
175#define POS printf("%s, line %d\n", __FILE__, __LINE__)
176
74eed73a
MW
177/**
178 * Object allocation/initialization macro, using designated initializer.
179 */
2e1f4a46
MW
180#define INIT(this, ...) { (this) = malloc(sizeof(*(this))); \
181 *(this) = (typeof(*(this))){ __VA_ARGS__ }; }
74eed73a 182
1a1ff9d1
MW
183/**
184 * Method declaration/definition macro, providing private and public interface.
185 *
186 * Defines a method name with this as first parameter and a return value ret,
187 * and an alias for this method with a _ prefix, having the this argument
188 * safely casted to the public interface iface.
189 * _name is provided a function pointer, but will get optimized out by GCC.
190 */
191#define METHOD(iface, name, ret, this, ...) \
23d2bf84
MW
192 static ret name(union {iface *_public; this;} \
193 __attribute__((transparent_union)), ##__VA_ARGS__); \
d185b6ac 194 static typeof(name) *_##name = (typeof(name)*)name; \
23d2bf84
MW
195 static ret name(this, ##__VA_ARGS__)
196
197/**
198 * Same as METHOD(), but is defined for two public interfaces.
199 */
200#define METHOD2(iface1, iface2, name, ret, this, ...) \
201 static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
202 __attribute__((transparent_union)), ##__VA_ARGS__); \
d185b6ac 203 static typeof(name) *_##name = (typeof(name)*)name; \
1a1ff9d1
MW
204 static ret name(this, ##__VA_ARGS__)
205
7ba89ccd
MW
206/**
207 * Architecture independent bitfield definition helpers (at least with GCC).
208 *
209 * Defines a bitfield with a type t and a fixed size of bitfield members, e.g.:
210 * BITFIELD2(u_int8_t,
211 * low: 4,
212 * high: 4,
213 * ) flags;
214 * The member defined first placed at bit 0.
215 */
216#if BYTE_ORDER == LITTLE_ENDIAN
217#define BITFIELD2(t, a, b,...) struct { t a; t b; __VA_ARGS__}
218#define BITFIELD3(t, a, b, c,...) struct { t a; t b; t c; __VA_ARGS__}
219#define BITFIELD4(t, a, b, c, d,...) struct { t a; t b; t c; t d; __VA_ARGS__}
220#define BITFIELD5(t, a, b, c, d, e,...) struct { t a; t b; t c; t d; t e; __VA_ARGS__}
221#elif BYTE_ORDER == BIG_ENDIAN
222#define BITFIELD2(t, a, b,...) struct { t b; t a; __VA_ARGS__}
223#define BITFIELD3(t, a, b, c,...) struct { t c; t b; t a; __VA_ARGS__}
224#define BITFIELD4(t, a, b, c, d,...) struct { t d; t c; t b; t a; __VA_ARGS__}
225#define BITFIELD5(t, a, b, c, d, e,...) struct { t e; t d; t c; t b; t a; __VA_ARGS__}
226#endif
227
552cc11b
MW
228/**
229 * Macro to allocate a sized type.
230 */
231#define malloc_thing(thing) ((thing*)malloc(sizeof(thing)))
232
fca4d3ee
MW
233/**
234 * Get the number of elements in an array
235 */
236#define countof(array) (sizeof(array)/sizeof(array[0]))
237
479f2950
MW
238/**
239 * Ignore result of functions tagged with warn_unused_result attributes
240 */
d0230850 241#define ignore_result(call) { if(call){}; }
479f2950 242
552cc11b
MW
243/**
244 * Assign a function as a class method
245 */
246#define ASSIGN(method, function) (method = (typeof(method))function)
247
248/**
249 * time_t not defined
250 */
251#define UNDEFINED_TIME 0
252
9f0327e6
AS
253/**
254 * Maximum time since epoch causing wrap-around on Jan 19 03:14:07 UTC 2038
255 */
256#define TIME_32_BIT_SIGNED_MAX 0x7fffffff
257
cc396286
TB
258/**
259 * define some missing fixed width int types on OpenSolaris.
260 * TODO: since the uintXX_t types are defined by the C99 standard we should
261 * probably use those anyway
262 */
263#ifdef __sun
264 #include <stdint.h>
265 typedef uint8_t u_int8_t;
266 typedef uint16_t u_int16_t;
267 typedef uint32_t u_int32_t;
268 typedef uint64_t u_int64_t;
269#endif
270
552cc11b
MW
271typedef enum status_t status_t;
272
273/**
274 * Return values of function calls.
275 */
276enum status_t {
277 /**
278 * Call succeeded.
279 */
280 SUCCESS,
7daf5226 281
552cc11b
MW
282 /**
283 * Call failed.
284 */
285 FAILED,
7daf5226 286
552cc11b
MW
287 /**
288 * Out of resources.
289 */
290 OUT_OF_RES,
7daf5226 291
552cc11b
MW
292 /**
293 * The suggested operation is already done
294 */
295 ALREADY_DONE,
7daf5226 296
552cc11b
MW
297 /**
298 * Not supported.
299 */
300 NOT_SUPPORTED,
7daf5226 301
552cc11b
MW
302 /**
303 * One of the arguments is invalid.
304 */
305 INVALID_ARG,
7daf5226 306
552cc11b
MW
307 /**
308 * Something could not be found.
309 */
310 NOT_FOUND,
7daf5226 311
552cc11b
MW
312 /**
313 * Error while parsing.
314 */
315 PARSE_ERROR,
7daf5226 316
552cc11b
MW
317 /**
318 * Error while verifying.
319 */
320 VERIFY_ERROR,
7daf5226 321
552cc11b
MW
322 /**
323 * Object in invalid state.
324 */
325 INVALID_STATE,
7daf5226 326
552cc11b
MW
327 /**
328 * Destroy object which called method belongs to.
329 */
330 DESTROY_ME,
7daf5226 331
552cc11b
MW
332 /**
333 * Another call to the method is required.
334 */
335 NEED_MORE,
336};
337
338/**
339 * enum_names for type status_t.
340 */
341extern enum_name_t *status_names;
342
4d174272
MW
343typedef enum tty_escape_t tty_escape_t;
344
345/**
346 * Excape codes for tty colors
347 */
348enum tty_escape_t {
349 /** text properties */
350 TTY_RESET,
351 TTY_BOLD,
352 TTY_UNDERLINE,
353 TTY_BLINKING,
354
355 /** foreground colors */
356 TTY_FG_BLACK,
357 TTY_FG_RED,
358 TTY_FG_GREEN,
359 TTY_FG_YELLOW,
360 TTY_FG_BLUE,
361 TTY_FG_MAGENTA,
362 TTY_FG_CYAN,
363 TTY_FG_WHITE,
364 TTY_FG_DEF,
365
366 /** background colors */
367 TTY_BG_BLACK,
368 TTY_BG_RED,
369 TTY_BG_GREEN,
370 TTY_BG_YELLOW,
371 TTY_BG_BLUE,
372 TTY_BG_MAGENTA,
373 TTY_BG_CYAN,
374 TTY_BG_WHITE,
375 TTY_BG_DEF,
376};
377
378/**
379 * Get the escape string for a given TTY color, empty string on non-tty fd
380 */
381char* tty_escape_get(int fd, tty_escape_t escape);
382
552cc11b
MW
383/**
384 * deprecated pluto style return value:
385 * error message, NULL for success
386 */
387typedef const char *err_t;
388
389/**
390 * Handle struct timeval like an own type.
391 */
392typedef struct timeval timeval_t;
393
394/**
395 * Handle struct timespec like an own type.
396 */
397typedef struct timespec timespec_t;
398
399/**
400 * Handle struct chunk_t like an own type.
401 */
402typedef struct sockaddr sockaddr_t;
403
552cc11b
MW
404/**
405 * Same as memcpy, but XORs src into dst instead of copy
406 */
407void memxor(u_int8_t dest[], u_int8_t src[], size_t n);
408
ed678b52
MW
409/**
410 * Safely overwrite n bytes of memory at ptr with zero, non-inlining variant.
411 */
412void memwipe_noinline(void *ptr, size_t n);
413
414/**
415 * Safely overwrite n bytes of memory at ptr with zero, inlining variant.
416 */
417static inline void memwipe_inline(void *ptr, size_t n)
418{
419 volatile char *c = (volatile char*)ptr;
d45b242b 420 size_t m, i;
ed678b52
MW
421
422 /* byte wise until long aligned */
d45b242b 423 for (i = 0; (uintptr_t)&c[i] % sizeof(long) && i < n; i++)
ed678b52
MW
424 {
425 c[i] = 0;
426 }
d45b242b
MW
427 /* word wise */
428 if (n >= sizeof(long))
ed678b52 429 {
d45b242b
MW
430 for (m = n - sizeof(long); i <= m; i += sizeof(long))
431 {
432 *(volatile long*)&c[i] = 0;
433 }
ed678b52
MW
434 }
435 /* byte wise of the rest */
436 for (; i < n; i++)
437 {
438 c[i] = 0;
439 }
440}
441
442/**
443 * Safely overwrite n bytes of memory at ptr with zero, auto-inlining variant.
444 */
445static inline void memwipe(void *ptr, size_t n)
446{
c480b5f4
TB
447 if (!ptr)
448 {
449 return;
450 }
ed678b52
MW
451 if (__builtin_constant_p(n))
452 {
453 memwipe_inline(ptr, n);
454 }
455 else
456 {
457 memwipe_noinline(ptr, n);
458 }
459}
460
81736d7d
TB
461/**
462 * A variant of strstr with the characteristics of memchr, where haystack is not
463 * a null-terminated string but simply a memory area of length n.
464 */
465void *memstr(const void *haystack, const char *needle, size_t n);
466
2ed241ae
TB
467/**
468 * Replacement for memrchr(3) if it is not provided by the C library.
469 *
470 * @param s start of the memory area to search
471 * @param c character to search
472 * @param n length of memory area to search
473 * @return pointer to the found character or NULL
474 */
475void *utils_memrchr(const void *s, int c, size_t n);
476
477#ifndef HAVE_MEMRCHR
478#define memrchr(s,c,n) utils_memrchr(s,c,n)
479#endif
480
d543d9ca
TB
481/**
482 * Translates the characters in the given string, searching for characters
483 * in 'from' and mapping them to characters in 'to'.
484 * The two characters sets 'from' and 'to' must contain the same number of
485 * characters.
486 */
487char *translate(char *str, const char *from, const char *to);
488
ccb6758e 489/**
4ab38d98 490 * Replaces all occurrences of search in the given string with replace.
ccb6758e
TB
491 *
492 * Allocates memory only if anything is replaced in the string. The original
493 * string is also returned if any of the arguments are invalid (e.g. if search
494 * is empty or any of them are NULL).
495 *
496 * @param str original string
497 * @param search string to search for and replace
4ab38d98 498 * @param replace string to replace found occurrences with
ccb6758e
TB
499 * @return allocated string, if anything got replaced, str otherwise
500 */
501char *strreplace(const char *str, const char *search, const char *replace);
502
766141bc
TB
503/**
504 * Like dirname(3) returns the directory part of the given null-terminated
505 * pathname, up to but not including the final '/' (or '.' if no '/' is found).
506 * Trailing '/' are not counted as part of the pathname.
507 *
508 * The difference is that it does this in a thread-safe manner (i.e. it does not
509 * use static buffers) and does not modify the original path.
510 *
511 * @param path original pathname
512 * @return allocated directory component
513 */
514char *path_dirname(const char *path);
515
516/**
517 * Like basename(3) returns the filename part of the given null-terminated path,
518 * i.e. the part following the final '/' (or '.' if path is empty or NULL).
519 * Trailing '/' are not counted as part of the pathname.
520 *
521 * The difference is that it does this in a thread-safe manner (i.e. it does not
522 * use static buffers) and does not modify the original path.
523 *
524 * @param path original pathname
525 * @return allocated filename component
526 */
527char *path_basename(const char *path);
528
6c20579a 529/**
7daf5226 530 * Creates a directory and all required parent directories.
6c20579a 531 *
3f310c0d 532 * @param path path to the new directory
7daf5226 533 * @param mode permissions of the new directory/directories
6c20579a
TB
534 * @return TRUE on success
535 */
536bool mkdir_p(const char *path, mode_t mode);
537
9a8fdc15
TB
538#ifndef HAVE_CLOSEFROM
539/**
540 * Close open file descriptors greater than or equal to lowfd.
541 *
4ab38d98 542 * @param lowfd start closing file descriptors from here
9a8fdc15
TB
543 */
544void closefrom(int lowfd);
545#endif
546
3f310c0d
MW
547/**
548 * Get a timestamp from a monotonic time source.
549 *
550 * While the time()/gettimeofday() functions are affected by leap seconds
551 * and system time changes, this function returns ever increasing monotonic
552 * time stamps.
553 *
554 * @param tv timeval struct receiving monotonic timestamps, or NULL
555 * @return monotonic timestamp in seconds
556 */
557time_t time_monotonic(timeval_t *tv);
558
eecd41e3
TB
559/**
560 * Add the given number of milliseconds to the given timeval struct
561 *
562 * @param tv timeval struct to modify
563 * @param ms number of milliseconds
564 */
565static inline void timeval_add_ms(timeval_t *tv, u_int ms)
566{
567 tv->tv_usec += ms * 1000;
819c02db 568 while (tv->tv_usec >= 1000000 /* 1s */)
eecd41e3
TB
569 {
570 tv->tv_usec -= 1000000;
571 tv->tv_sec++;
572 }
573}
574
081ae2eb
MW
575/**
576 * returns null
577 */
578void *return_null();
579
233b853d
MW
580/**
581 * No-Operation function
582 */
583void nop();
584
da17b016
MW
585/**
586 * returns TRUE
587 */
588bool return_true();
589
590/**
591 * returns FALSE
592 */
593bool return_false();
594
502edf42
MW
595/**
596 * returns FAILED
597 */
598status_t return_failed();
599
4755ab50
MW
600/**
601 * returns SUCCESS
602 */
603status_t return_success();
604
0be12e35
MW
605/**
606 * Write a 16-bit host order value in network order to an unaligned address.
607 *
608 * @param host host order 16-bit value
609 * @param network unaligned address to write network order value to
610 */
611static inline void htoun16(void *network, u_int16_t host)
612{
dbee988e
MW
613 char *unaligned = (char*)network;
614
0be12e35 615 host = htons(host);
dbee988e 616 memcpy(unaligned, &host, sizeof(host));
0be12e35
MW
617}
618
619/**
620 * Write a 32-bit host order value in network order to an unaligned address.
621 *
622 * @param host host order 32-bit value
623 * @param network unaligned address to write network order value to
624 */
625static inline void htoun32(void *network, u_int32_t host)
626{
dbee988e
MW
627 char *unaligned = (char*)network;
628
0be12e35 629 host = htonl(host);
dbee988e 630 memcpy((char*)unaligned, &host, sizeof(host));
0be12e35
MW
631}
632
fbeb9454
AS
633/**
634 * Write a 64-bit host order value in network order to an unaligned address.
635 *
a91462df 636 * @param host host order 64-bit value
fbeb9454
AS
637 * @param network unaligned address to write network order value to
638 */
639static inline void htoun64(void *network, u_int64_t host)
640{
641 char *unaligned = (char*)network;
f4e25e60
MW
642
643#ifdef be64toh
644 host = htobe64(host);
645 memcpy((char*)unaligned, &host, sizeof(host));
646#else
fbeb9454
AS
647 u_int32_t high_part, low_part;
648
649 high_part = host >> 32;
650 high_part = htonl(high_part);
651 low_part = host & 0xFFFFFFFFLL;
652 low_part = htonl(low_part);
653
654 memcpy(unaligned, &high_part, sizeof(high_part));
655 unaligned += sizeof(high_part);
656 memcpy(unaligned, &low_part, sizeof(low_part));
f4e25e60 657#endif
fbeb9454
AS
658}
659
0be12e35
MW
660/**
661 * Read a 16-bit value in network order from an unaligned address to host order.
662 *
663 * @param network unaligned address to read network order value from
664 * @return host order value
665 */
666static inline u_int16_t untoh16(void *network)
667{
dbee988e 668 char *unaligned = (char*)network;
0be12e35
MW
669 u_int16_t tmp;
670
dbee988e 671 memcpy(&tmp, unaligned, sizeof(tmp));
0be12e35
MW
672 return ntohs(tmp);
673}
674
675/**
676 * Read a 32-bit value in network order from an unaligned address to host order.
677 *
678 * @param network unaligned address to read network order value from
679 * @return host order value
680 */
681static inline u_int32_t untoh32(void *network)
682{
dbee988e 683 char *unaligned = (char*)network;
0be12e35
MW
684 u_int32_t tmp;
685
dbee988e 686 memcpy(&tmp, unaligned, sizeof(tmp));
f8f4f31a 687 return ntohl(tmp);
0be12e35
MW
688}
689
fbeb9454
AS
690/**
691 * Read a 64-bit value in network order from an unaligned address to host order.
692 *
693 * @param network unaligned address to read network order value from
694 * @return host order value
695 */
696static inline u_int64_t untoh64(void *network)
697{
698 char *unaligned = (char*)network;
f4e25e60
MW
699
700#ifdef be64toh
701 u_int64_t tmp;
702
703 memcpy(&tmp, unaligned, sizeof(tmp));
704 return be64toh(tmp);
705#else
fbeb9454
AS
706 u_int32_t high_part, low_part;
707
708 memcpy(&high_part, unaligned, sizeof(high_part));
709 unaligned += sizeof(high_part);
710 memcpy(&low_part, unaligned, sizeof(low_part));
711
712 high_part = ntohl(high_part);
713 low_part = ntohl(low_part);
714
715 return (((u_int64_t)high_part) << 32) + low_part;
f4e25e60 716#endif
fbeb9454
AS
717}
718
84044f9c 719/**
812ae898 720 * Get the padding required to make size a multiple of alignment
84044f9c 721 */
812ae898 722static inline size_t pad_len(size_t size, size_t alignment)
84044f9c 723{
812ae898 724 size_t remainder;
84044f9c 725
812ae898
TB
726 remainder = size % alignment;
727 return remainder ? alignment - remainder : 0;
728}
729
730/**
731 * Round up size to be multiple of alignment
732 */
733static inline size_t round_up(size_t size, size_t alignment)
734{
735 return size + pad_len(size, alignment);
84044f9c
MW
736}
737
738/**
812ae898 739 * Round down size to be a multiple of alignment
84044f9c 740 */
812ae898 741static inline size_t round_down(size_t size, size_t alignment)
84044f9c 742{
812ae898 743 return size - (size % alignment);
84044f9c
MW
744}
745
552cc11b
MW
746/**
747 * Special type to count references
748 */
4d04e2c6 749typedef u_int refcount_t;
efd0fe21 750
a0c2370e
TB
751/* use __atomic* built-ins with GCC 4.7 and newer */
752#ifdef __GNUC__
753# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
754# define HAVE_GCC_ATOMIC_OPERATIONS
755# endif
756#endif
757
efd0fe21
MW
758#ifdef HAVE_GCC_ATOMIC_OPERATIONS
759
0f603d42
TB
760#define ref_get(ref) __atomic_add_fetch(ref, 1, __ATOMIC_RELAXED)
761/* The relaxed memory model works fine for increments as these (usually) don't
762 * change the state of refcounted objects. But here we have to ensure that we
763 * free the right stuff if ref counted objects are mutable. So we have to sync
764 * with other threads that call ref_put(). It would be sufficient to use
765 * __ATOMIC_RELEASE here and then call __atomic_thread_fence() with
766 * __ATOMIC_ACQUIRE if we reach 0, but since we don't have control over the use
767 * of ref_put() we have to make sure. */
768#define ref_put(ref) (!__atomic_sub_fetch(ref, 1, __ATOMIC_ACQ_REL))
769#define ref_cur(ref) __atomic_load_n(ref, __ATOMIC_RELAXED)
770
771#define _cas_impl(ptr, oldval, newval) ({ typeof(oldval) _old = oldval; \
772 __atomic_compare_exchange_n(ptr, &_old, newval, FALSE, \
773 __ATOMIC_SEQ_CST, __ATOMIC_RELAXED); })
774#define cas_bool(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
775#define cas_ptr(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
776
777#elif defined(HAVE_GCC_SYNC_OPERATIONS)
778
3160b92a 779#define ref_get(ref) __sync_add_and_fetch(ref, 1)
efd0fe21 780#define ref_put(ref) (!__sync_sub_and_fetch(ref, 1))
efedd0d2 781#define ref_cur(ref) __sync_fetch_and_add(ref, 0)
efd0fe21 782
5317dd68
TB
783#define cas_bool(ptr, oldval, newval) \
784 (__sync_bool_compare_and_swap(ptr, oldval, newval))
785#define cas_ptr(ptr, oldval, newval) \
786 (__sync_bool_compare_and_swap(ptr, oldval, newval))
787
0f603d42 788#else /* !HAVE_GCC_ATOMIC_OPERATIONS && !HAVE_GCC_SYNC_OPERATIONS */
efd0fe21 789
552cc11b
MW
790/**
791 * Get a new reference.
792 *
efedd0d2 793 * Increments the reference counter atomically.
552cc11b
MW
794 *
795 * @param ref pointer to ref counter
3160b92a 796 * @return new value of ref
552cc11b 797 */
3160b92a 798refcount_t ref_get(refcount_t *ref);
552cc11b
MW
799
800/**
801 * Put back a unused reference.
802 *
efedd0d2 803 * Decrements the reference counter atomically and
552cc11b
MW
804 * says if more references available.
805 *
806 * @param ref pointer to ref counter
807 * @return TRUE if no more references counted
808 */
809bool ref_put(refcount_t *ref);
810
efedd0d2
TB
811/**
812 * Get the current value of the reference counter.
813 *
814 * @param ref pointer to ref counter
815 * @return current value of ref
816 */
817refcount_t ref_cur(refcount_t *ref);
818
5317dd68
TB
819/**
820 * Atomically replace value of ptr with newval if it currently equals oldval.
821 *
822 * @param ptr pointer to variable
823 * @param oldval old value of the variable
824 * @param newval new value set if possible
825 * @return TRUE if value equaled oldval and newval was written
826 */
827bool cas_bool(bool *ptr, bool oldval, bool newval);
828
829/**
830 * Atomically replace value of ptr with newval if it currently equals oldval.
831 *
832 * @param ptr pointer to variable
833 * @param oldval old value of the variable
834 * @param newval new value set if possible
835 * @return TRUE if value equaled oldval and newval was written
836 */
837bool cas_ptr(void **ptr, void *oldval, void *newval);
838
efd0fe21
MW
839#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
840
2077d996
MW
841#ifndef HAVE_FMEMOPEN
842# ifdef HAVE_FUNOPEN
9df621d2
MW
843# define HAVE_FMEMOPEN
844# define HAVE_FMEMOPEN_FALLBACK
5ac29360 845# include <stdio.h>
2077d996
MW
846/**
847 * fmemopen(3) fallback using BSD funopen.
848 *
849 * We could also provide one using fopencookie(), but should we have it we
850 * most likely have fmemopen().
851 *
852 * fseek() is currently not supported.
853 */
854FILE *fmemopen(void *buf, size_t size, const char *mode);
855# endif /* FUNOPEN */
856#endif /* FMEMOPEN */
857
552cc11b 858/**
d25ce370 859 * printf hook for time_t.
552cc11b 860 *
7daf5226 861 * Arguments are:
323f9f99 862 * time_t* time, bool utc
552cc11b 863 */
1b40b74d 864int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
d25ce370 865 const void *const *args);
552cc11b
MW
866
867/**
d25ce370 868 * printf hook for time_t deltas.
552cc11b 869 *
7daf5226 870 * Arguments are:
323f9f99 871 * time_t* begin, time_t* end
552cc11b 872 */
1b40b74d 873int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
d25ce370 874 const void *const *args);
552cc11b
MW
875
876/**
d25ce370 877 * printf hook for memory areas.
552cc11b 878 *
7daf5226 879 * Arguments are:
817ab8a8 880 * u_char *ptr, u_int len
552cc11b 881 */
1b40b74d 882int mem_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
d25ce370 883 const void *const *args);
552cc11b 884
1490ff4d 885#endif /** UTILS_H_ @}*/