Moved utils.[ch] to utils folder

This commit is contained in:
Tobias Brunner
2012-10-24 16:07:53 +02:00
parent f9625952ad
commit bca34c3717
10 changed files with 13 additions and 13 deletions
+1 -1
View File
@@ -42,7 +42,7 @@ struct chunk_t {
size_t len;
};
#include "../utils.h"
#include "utils.h"
/**
* A { NULL, 0 }-chunk handy for initialization.
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef INTEGRITY_CHECKER_H_
#define INTEGRITY_CHECKER_H_
#include "../utils.h"
#include "utils.h"
typedef struct integrity_checker_t integrity_checker_t;
typedef struct integrity_checksum_t integrity_checksum_t;
+1 -1
View File
@@ -24,7 +24,7 @@
typedef struct settings_t settings_t;
#include "../utils.h"
#include "utils.h"
#include "collections/enumerator.h"
/**
+570
View File
@@ -0,0 +1,570 @@
/*
* Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "utils.h"
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdint.h>
#include <limits.h>
#include <dirent.h>
#include <time.h>
#include <pthread.h>
#include "collections/enumerator.h"
#include "utils/debug.h"
ENUM(status_names, SUCCESS, NEED_MORE,
"SUCCESS",
"FAILED",
"OUT_OF_RES",
"ALREADY_DONE",
"NOT_SUPPORTED",
"INVALID_ARG",
"NOT_FOUND",
"PARSE_ERROR",
"VERIFY_ERROR",
"INVALID_STATE",
"DESTROY_ME",
"NEED_MORE",
);
/**
* Described in header.
*/
void *clalloc(void * pointer, size_t size)
{
void *data;
data = malloc(size);
memcpy(data, pointer, size);
return (data);
}
/**
* Described in header.
*/
void memxor(u_int8_t dst[], u_int8_t src[], size_t n)
{
int m, i;
/* byte wise XOR until dst aligned */
for (i = 0; (uintptr_t)&dst[i] % sizeof(long) && i < n; i++)
{
dst[i] ^= src[i];
}
/* try to use words if src shares an aligment with dst */
switch (((uintptr_t)&src[i] % sizeof(long)))
{
case 0:
for (m = n - sizeof(long); i <= m; i += sizeof(long))
{
*(long*)&dst[i] ^= *(long*)&src[i];
}
break;
case sizeof(int):
for (m = n - sizeof(int); i <= m; i += sizeof(int))
{
*(int*)&dst[i] ^= *(int*)&src[i];
}
break;
case sizeof(short):
for (m = n - sizeof(short); i <= m; i += sizeof(short))
{
*(short*)&dst[i] ^= *(short*)&src[i];
}
break;
default:
break;
}
/* byte wise XOR of the rest */
for (; i < n; i++)
{
dst[i] ^= src[i];
}
}
/**
* Described in header.
*/
void memwipe_noinline(void *ptr, size_t n)
{
memwipe_inline(ptr, n);
}
/**
* Described in header.
*/
void *memstr(const void *haystack, const char *needle, size_t n)
{
unsigned const char *pos = haystack;
size_t l = strlen(needle);
for (; n >= l; ++pos, --n)
{
if (memeq(pos, needle, l))
{
return (void*)pos;
}
}
return NULL;
}
/**
* Described in header.
*/
char* translate(char *str, const char *from, const char *to)
{
char *pos = str;
if (strlen(from) != strlen(to))
{
return str;
}
while (pos && *pos)
{
char *match;
if ((match = strchr(from, *pos)) != NULL)
{
*pos = to[match - from];
}
pos++;
}
return str;
}
/**
* Described in header.
*/
bool mkdir_p(const char *path, mode_t mode)
{
int len;
char *pos, full[PATH_MAX];
pos = full;
if (!path || *path == '\0')
{
return TRUE;
}
len = snprintf(full, sizeof(full)-1, "%s", path);
if (len < 0 || len >= sizeof(full)-1)
{
DBG1(DBG_LIB, "path string %s too long", path);
return FALSE;
}
/* ensure that the path ends with a '/' */
if (full[len-1] != '/')
{
full[len++] = '/';
full[len] = '\0';
}
/* skip '/' at the beginning */
while (*pos == '/')
{
pos++;
}
while ((pos = strchr(pos, '/')))
{
*pos = '\0';
if (access(full, F_OK) < 0)
{
if (mkdir(full, mode) < 0)
{
DBG1(DBG_LIB, "failed to create directory %s", full);
return FALSE;
}
}
*pos = '/';
pos++;
}
return TRUE;
}
/**
* The size of the thread-specific error buffer
*/
#define STRERROR_BUF_LEN 256
/**
* Key to store thread-specific error buffer
*/
static pthread_key_t strerror_buf_key;
/**
* Only initialize the key above once
*/
static pthread_once_t strerror_buf_key_once = PTHREAD_ONCE_INIT;
/**
* Create the key used for the thread-specific error buffer
*/
static void create_strerror_buf_key()
{
pthread_key_create(&strerror_buf_key, free);
}
/**
* Retrieve the error buffer assigned to the current thread (or create it)
*/
static inline char *get_strerror_buf()
{
char *buf;
pthread_once(&strerror_buf_key_once, create_strerror_buf_key);
buf = pthread_getspecific(strerror_buf_key);
if (!buf)
{
buf = malloc(STRERROR_BUF_LEN);
pthread_setspecific(strerror_buf_key, buf);
}
return buf;
}
#ifdef HAVE_STRERROR_R
/*
* Described in header.
*/
const char *safe_strerror(int errnum)
{
char *buf = get_strerror_buf(), *msg;
#ifdef STRERROR_R_CHAR_P
/* char* version which may or may not return the original buffer */
msg = strerror_r(errnum, buf, STRERROR_BUF_LEN);
#else
/* int version returns 0 on success */
msg = strerror_r(errnum, buf, STRERROR_BUF_LEN) ? "Unknown error" : buf;
#endif
return msg;
}
#else /* HAVE_STRERROR_R */
/* we actually wan't to call strerror(3) below */
#undef strerror
/*
* Described in header.
*/
const char *safe_strerror(int errnum)
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
char *buf = get_strerror_buf();
/* use a mutex to ensure calling strerror(3) is thread-safe */
pthread_mutex_lock(&mutex);
strncpy(buf, strerror(errnum), STRERROR_BUF_LEN);
pthread_mutex_unlock(&mutex);
buf[STRERROR_BUF_LEN - 1] = '\0';
return buf;
}
#endif /* HAVE_STRERROR_R */
#ifndef HAVE_CLOSEFROM
/**
* Described in header.
*/
void closefrom(int lowfd)
{
char fd_dir[PATH_MAX];
int maxfd, fd, len;
/* try to close only open file descriptors on Linux... */
len = snprintf(fd_dir, sizeof(fd_dir), "/proc/%u/fd", getpid());
if (len > 0 && len < sizeof(fd_dir) && access(fd_dir, F_OK) == 0)
{
enumerator_t *enumerator = enumerator_create_directory(fd_dir);
if (enumerator)
{
char *rel;
while (enumerator->enumerate(enumerator, &rel, NULL, NULL))
{
fd = atoi(rel);
if (fd >= lowfd)
{
close(fd);
}
}
enumerator->destroy(enumerator);
return;
}
}
/* ...fall back to closing all fds otherwise */
maxfd = (int)sysconf(_SC_OPEN_MAX);
if (maxfd < 0)
{
maxfd = 256;
}
for (fd = lowfd; fd < maxfd; fd++)
{
close(fd);
}
}
#endif /* HAVE_CLOSEFROM */
/**
* Return monotonic time
*/
time_t time_monotonic(timeval_t *tv)
{
#if defined(HAVE_CLOCK_GETTIME) && \
(defined(HAVE_CONDATTR_CLOCK_MONOTONIC) || \
defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
/* as we use time_monotonic() for condvar operations, we use the
* monotonic time source only if it is also supported by pthread. */
timespec_t ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
{
if (tv)
{
tv->tv_sec = ts.tv_sec;
tv->tv_usec = ts.tv_nsec / 1000;
}
return ts.tv_sec;
}
#endif /* HAVE_CLOCK_GETTIME && (...) */
/* Fallback to non-monotonic timestamps:
* On MAC OS X, creating monotonic timestamps is rather difficult. We
* could use mach_absolute_time() and catch sleep/wakeup notifications.
* We stick to the simpler (non-monotonic) gettimeofday() for now.
* But keep in mind: we need the same time source here as in condvar! */
if (!tv)
{
return time(NULL);
}
if (gettimeofday(tv, NULL) != 0)
{ /* should actually never fail if passed pointers are valid */
return -1;
}
return tv->tv_sec;
}
/**
* return null
*/
void *return_null()
{
return NULL;
}
/**
* returns TRUE
*/
bool return_true()
{
return TRUE;
}
/**
* returns FALSE
*/
bool return_false()
{
return FALSE;
}
/**
* returns FAILED
*/
status_t return_failed()
{
return FAILED;
}
/**
* nop operation
*/
void nop()
{
}
#ifndef HAVE_GCC_ATOMIC_OPERATIONS
/**
* We use a single mutex for all refcount variables.
*/
static pthread_mutex_t ref_mutex = PTHREAD_MUTEX_INITIALIZER;
/**
* Increase refcount
*/
void ref_get(refcount_t *ref)
{
pthread_mutex_lock(&ref_mutex);
(*ref)++;
pthread_mutex_unlock(&ref_mutex);
}
/**
* Decrease refcount
*/
bool ref_put(refcount_t *ref)
{
bool more_refs;
pthread_mutex_lock(&ref_mutex);
more_refs = --(*ref) > 0;
pthread_mutex_unlock(&ref_mutex);
return !more_refs;
}
/**
* Single mutex for all compare and swap operations.
*/
static pthread_mutex_t cas_mutex = PTHREAD_MUTEX_INITIALIZER;
/**
* Compare and swap if equal to old value
*/
#define _cas_impl(name, type) \
bool cas_##name(type *ptr, type oldval, type newval) \
{ \
bool swapped; \
pthread_mutex_lock(&cas_mutex); \
if ((swapped = (*ptr == oldval))) { *ptr = newval; } \
pthread_mutex_unlock(&cas_mutex); \
return swapped; \
}
_cas_impl(bool, bool)
_cas_impl(ptr, void*)
#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
/**
* Described in header.
*/
int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args)
{
static const char* months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
time_t *time = *((time_t**)(args[0]));
bool utc = *((bool*)(args[1]));;
struct tm t;
if (time == UNDEFINED_TIME)
{
return print_in_hook(data, "--- -- --:--:--%s----",
utc ? " UTC " : " ");
}
if (utc)
{
gmtime_r(time, &t);
}
else
{
localtime_r(time, &t);
}
return print_in_hook(data, "%s %02d %02d:%02d:%02d%s%04d",
months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900);
}
/**
* Described in header.
*/
int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args)
{
char* unit = "second";
time_t *arg1 = *((time_t**)(args[0]));
time_t *arg2 = *((time_t**)(args[1]));
u_int64_t delta = llabs(*arg1 - *arg2);
if (delta > 2 * 60 * 60 * 24)
{
delta /= 60 * 60 * 24;
unit = "day";
}
else if (delta > 2 * 60 * 60)
{
delta /= 60 * 60;
unit = "hour";
}
else if (delta > 2 * 60)
{
delta /= 60;
unit = "minute";
}
return print_in_hook(data, "%" PRIu64 " %s%s", delta, unit,
(delta == 1) ? "" : "s");
}
/**
* Number of bytes per line to dump raw data
*/
#define BYTES_PER_LINE 16
static char hexdig_upper[] = "0123456789ABCDEF";
/**
* Described in header.
*/
int mem_printf_hook(printf_hook_data_t *data,
printf_hook_spec_t *spec, const void *const *args)
{
char *bytes = *((void**)(args[0]));
u_int len = *((int*)(args[1]));
char buffer[BYTES_PER_LINE * 3];
char ascii_buffer[BYTES_PER_LINE + 1];
char *buffer_pos = buffer;
char *bytes_pos = bytes;
char *bytes_roof = bytes + len;
int line_start = 0;
int i = 0;
int written = 0;
written += print_in_hook(data, "=> %u bytes @ %p", len, bytes);
while (bytes_pos < bytes_roof)
{
*buffer_pos++ = hexdig_upper[(*bytes_pos >> 4) & 0xF];
*buffer_pos++ = hexdig_upper[ *bytes_pos & 0xF];
ascii_buffer[i++] =
(*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
{
int padding = 3 * (BYTES_PER_LINE - i);
while (padding--)
{
*buffer_pos++ = ' ';
}
*buffer_pos++ = '\0';
ascii_buffer[i] = '\0';
written += print_in_hook(data, "\n%4d: %s %s",
line_start, buffer, ascii_buffer);
buffer_pos = buffer;
line_start += BYTES_PER_LINE;
i = 0;
}
else
{
*buffer_pos++ = ' ';
}
}
return written;
}
+699
View File
@@ -0,0 +1,699 @@
/*
* Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup utils_i utils
* @{ @ingroup utils
*/
#ifndef UTILS_H_
#define UTILS_H_
#include <sys/types.h>
#include <stdlib.h>
#include <stddef.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <string.h>
#include "enum.h"
/**
* strongSwan program return codes
*/
#define SS_RC_LIBSTRONGSWAN_INTEGRITY 64
#define SS_RC_DAEMON_INTEGRITY 65
#define SS_RC_INITIALIZATION_FAILED 66
#define SS_RC_FIRST SS_RC_LIBSTRONGSWAN_INTEGRITY
#define SS_RC_LAST SS_RC_INITIALIZATION_FAILED
/**
* Number of bits in a byte
*/
#define BITS_PER_BYTE 8
/**
* Default length for various auxiliary text buffers
*/
#define BUF_LEN 512
/**
* General purpose boolean type.
*/
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
# ifndef HAVE__BOOL
# define _Bool signed char
# endif /* HAVE__BOOL */
# define bool _Bool
# define false 0
# define true 1
# define __bool_true_false_are_defined 1
#endif /* HAVE_STDBOOL_H */
#ifndef FALSE
# define FALSE false
#endif /* FALSE */
#ifndef TRUE
# define TRUE true
#endif /* TRUE */
/**
* Helper function that compares two strings for equality
*/
static inline bool streq(const char *x, const char *y)
{
return strcmp(x, y) == 0;
}
/**
* Macro compares two strings for equality, length limited
*/
#define strneq(x,y,len) (strncmp(x, y, len) == 0)
/**
* Helper function that compares two strings for equality ignoring case
*/
static inline bool strcaseeq(const char *x, const char *y)
{
return strcasecmp(x, y) == 0;
}
/**
* Macro compares two strings for equality ignoring case, length limited
*/
#define strncaseeq(x,y,len) (strncasecmp(x, y, len) == 0)
/**
* NULL-safe strdup variant
*/
static inline char *strdupnull(const char *s)
{
return s ? strdup(s) : NULL;
}
/**
* Macro compares two binary blobs for equality
*/
#define memeq(x,y,len) (memcmp(x, y, len) == 0)
/**
* Macro gives back larger of two values.
*/
#define max(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
_x > _y ? _x : _y; })
/**
* Macro gives back smaller of two values.
*/
#define min(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
_x < _y ? _x : _y; })
/**
* Call destructor of an object, if object != NULL
*/
#define DESTROY_IF(obj) if (obj) (obj)->destroy(obj)
/**
* Call offset destructor of an object, if object != NULL
*/
#define DESTROY_OFFSET_IF(obj, offset) if (obj) obj->destroy_offset(obj, offset);
/**
* Call function destructor of an object, if object != NULL
*/
#define DESTROY_FUNCTION_IF(obj, fn) if (obj) obj->destroy_function(obj, fn);
/**
* Debug macro to follow control flow
*/
#define POS printf("%s, line %d\n", __FILE__, __LINE__)
/**
* Object allocation/initialization macro, using designated initializer.
*/
#define INIT(this, ...) { (this) = malloc(sizeof(*(this))); \
*(this) = (typeof(*(this))){ __VA_ARGS__ }; }
/**
* Method declaration/definition macro, providing private and public interface.
*
* Defines a method name with this as first parameter and a return value ret,
* and an alias for this method with a _ prefix, having the this argument
* safely casted to the public interface iface.
* _name is provided a function pointer, but will get optimized out by GCC.
*/
#define METHOD(iface, name, ret, this, ...) \
static ret name(union {iface *_public; this;} \
__attribute__((transparent_union)), ##__VA_ARGS__); \
static typeof(name) *_##name = (typeof(name)*)name; \
static ret name(this, ##__VA_ARGS__)
/**
* Same as METHOD(), but is defined for two public interfaces.
*/
#define METHOD2(iface1, iface2, name, ret, this, ...) \
static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
__attribute__((transparent_union)), ##__VA_ARGS__); \
static typeof(name) *_##name = (typeof(name)*)name; \
static ret name(this, ##__VA_ARGS__)
/**
* Architecture independent bitfield definition helpers (at least with GCC).
*
* Defines a bitfield with a type t and a fixed size of bitfield members, e.g.:
* BITFIELD2(u_int8_t,
* low: 4,
* high: 4,
* ) flags;
* The member defined first placed at bit 0.
*/
#if BYTE_ORDER == LITTLE_ENDIAN
#define BITFIELD2(t, a, b,...) struct { t a; t b; __VA_ARGS__}
#define BITFIELD3(t, a, b, c,...) struct { t a; t b; t c; __VA_ARGS__}
#define BITFIELD4(t, a, b, c, d,...) struct { t a; t b; t c; t d; __VA_ARGS__}
#define BITFIELD5(t, a, b, c, d, e,...) struct { t a; t b; t c; t d; t e; __VA_ARGS__}
#elif BYTE_ORDER == BIG_ENDIAN
#define BITFIELD2(t, a, b,...) struct { t b; t a; __VA_ARGS__}
#define BITFIELD3(t, a, b, c,...) struct { t c; t b; t a; __VA_ARGS__}
#define BITFIELD4(t, a, b, c, d,...) struct { t d; t c; t b; t a; __VA_ARGS__}
#define BITFIELD5(t, a, b, c, d, e,...) struct { t e; t d; t c; t b; t a; __VA_ARGS__}
#endif
/**
* Macro to allocate a sized type.
*/
#define malloc_thing(thing) ((thing*)malloc(sizeof(thing)))
/**
* Get the number of elements in an array
*/
#define countof(array) (sizeof(array)/sizeof(array[0]))
/**
* Ignore result of functions tagged with warn_unused_result attributes
*/
#define ignore_result(call) { if(call){}; }
/**
* Assign a function as a class method
*/
#define ASSIGN(method, function) (method = (typeof(method))function)
/**
* time_t not defined
*/
#define UNDEFINED_TIME 0
/**
* Maximum time since epoch causing wrap-around on Jan 19 03:14:07 UTC 2038
*/
#define TIME_32_BIT_SIGNED_MAX 0x7fffffff
/**
* define some missing fixed width int types on OpenSolaris.
* TODO: since the uintXX_t types are defined by the C99 standard we should
* probably use those anyway
*/
#ifdef __sun
#include <stdint.h>
typedef uint8_t u_int8_t;
typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t;
typedef uint64_t u_int64_t;
#endif
typedef enum status_t status_t;
/**
* Return values of function calls.
*/
enum status_t {
/**
* Call succeeded.
*/
SUCCESS,
/**
* Call failed.
*/
FAILED,
/**
* Out of resources.
*/
OUT_OF_RES,
/**
* The suggested operation is already done
*/
ALREADY_DONE,
/**
* Not supported.
*/
NOT_SUPPORTED,
/**
* One of the arguments is invalid.
*/
INVALID_ARG,
/**
* Something could not be found.
*/
NOT_FOUND,
/**
* Error while parsing.
*/
PARSE_ERROR,
/**
* Error while verifying.
*/
VERIFY_ERROR,
/**
* Object in invalid state.
*/
INVALID_STATE,
/**
* Destroy object which called method belongs to.
*/
DESTROY_ME,
/**
* Another call to the method is required.
*/
NEED_MORE,
};
/**
* enum_names for type status_t.
*/
extern enum_name_t *status_names;
/**
* deprecated pluto style return value:
* error message, NULL for success
*/
typedef const char *err_t;
/**
* Handle struct timeval like an own type.
*/
typedef struct timeval timeval_t;
/**
* Handle struct timespec like an own type.
*/
typedef struct timespec timespec_t;
/**
* Handle struct chunk_t like an own type.
*/
typedef struct sockaddr sockaddr_t;
/**
* Clone a data to a newly allocated buffer
*/
void *clalloc(void *pointer, size_t size);
/**
* Same as memcpy, but XORs src into dst instead of copy
*/
void memxor(u_int8_t dest[], u_int8_t src[], size_t n);
/**
* Safely overwrite n bytes of memory at ptr with zero, non-inlining variant.
*/
void memwipe_noinline(void *ptr, size_t n);
/**
* Safely overwrite n bytes of memory at ptr with zero, inlining variant.
*/
static inline void memwipe_inline(void *ptr, size_t n)
{
volatile char *c = (volatile char*)ptr;
size_t m, i;
/* byte wise until long aligned */
for (i = 0; (uintptr_t)&c[i] % sizeof(long) && i < n; i++)
{
c[i] = 0;
}
/* word wise */
if (n >= sizeof(long))
{
for (m = n - sizeof(long); i <= m; i += sizeof(long))
{
*(volatile long*)&c[i] = 0;
}
}
/* byte wise of the rest */
for (; i < n; i++)
{
c[i] = 0;
}
}
/**
* Safely overwrite n bytes of memory at ptr with zero, auto-inlining variant.
*/
static inline void memwipe(void *ptr, size_t n)
{
if (__builtin_constant_p(n))
{
memwipe_inline(ptr, n);
}
else
{
memwipe_noinline(ptr, n);
}
}
/**
* A variant of strstr with the characteristics of memchr, where haystack is not
* a null-terminated string but simply a memory area of length n.
*/
void *memstr(const void *haystack, const char *needle, size_t n);
/**
* Translates the characters in the given string, searching for characters
* in 'from' and mapping them to characters in 'to'.
* The two characters sets 'from' and 'to' must contain the same number of
* characters.
*/
char *translate(char *str, const char *from, const char *to);
/**
* Creates a directory and all required parent directories.
*
* @param path path to the new directory
* @param mode permissions of the new directory/directories
* @return TRUE on success
*/
bool mkdir_p(const char *path, mode_t mode);
/**
* Thread-safe wrapper around strerror and strerror_r.
*
* This is required because the first is not thread-safe (on some platforms)
* and the second uses two different signatures (POSIX/GNU) and is impractical
* to use anyway.
*
* @param errnum error code (i.e. errno)
* @return error message
*/
const char *safe_strerror(int errnum);
/**
* Replace usages of strerror(3) with thread-safe variant.
*/
#define strerror(errnum) safe_strerror(errnum)
#ifndef HAVE_CLOSEFROM
/**
* Close open file descriptors greater than or equal to lowfd.
*
* @param lowfd start closing file descriptoros from here
*/
void closefrom(int lowfd);
#endif
/**
* Get a timestamp from a monotonic time source.
*
* While the time()/gettimeofday() functions are affected by leap seconds
* and system time changes, this function returns ever increasing monotonic
* time stamps.
*
* @param tv timeval struct receiving monotonic timestamps, or NULL
* @return monotonic timestamp in seconds
*/
time_t time_monotonic(timeval_t *tv);
/**
* Add the given number of milliseconds to the given timeval struct
*
* @param tv timeval struct to modify
* @param ms number of milliseconds
*/
static inline void timeval_add_ms(timeval_t *tv, u_int ms)
{
tv->tv_usec += ms * 1000;
while (tv->tv_usec > 1000000 /* 1s */)
{
tv->tv_usec -= 1000000;
tv->tv_sec++;
}
}
/**
* returns null
*/
void *return_null();
/**
* No-Operation function
*/
void nop();
/**
* returns TRUE
*/
bool return_true();
/**
* returns FALSE
*/
bool return_false();
/**
* returns FAILED
*/
status_t return_failed();
/**
* Write a 16-bit host order value in network order to an unaligned address.
*
* @param host host order 16-bit value
* @param network unaligned address to write network order value to
*/
static inline void htoun16(void *network, u_int16_t host)
{
char *unaligned = (char*)network;
host = htons(host);
memcpy(unaligned, &host, sizeof(host));
}
/**
* Write a 32-bit host order value in network order to an unaligned address.
*
* @param host host order 32-bit value
* @param network unaligned address to write network order value to
*/
static inline void htoun32(void *network, u_int32_t host)
{
char *unaligned = (char*)network;
host = htonl(host);
memcpy((char*)unaligned, &host, sizeof(host));
}
/**
* Write a 64-bit host order value in network order to an unaligned address.
*
* @param host host order 64-bit value
* @param network unaligned address to write network order value to
*/
static inline void htoun64(void *network, u_int64_t host)
{
char *unaligned = (char*)network;
#ifdef be64toh
host = htobe64(host);
memcpy((char*)unaligned, &host, sizeof(host));
#else
u_int32_t high_part, low_part;
high_part = host >> 32;
high_part = htonl(high_part);
low_part = host & 0xFFFFFFFFLL;
low_part = htonl(low_part);
memcpy(unaligned, &high_part, sizeof(high_part));
unaligned += sizeof(high_part);
memcpy(unaligned, &low_part, sizeof(low_part));
#endif
}
/**
* Read a 16-bit value in network order from an unaligned address to host order.
*
* @param network unaligned address to read network order value from
* @return host order value
*/
static inline u_int16_t untoh16(void *network)
{
char *unaligned = (char*)network;
u_int16_t tmp;
memcpy(&tmp, unaligned, sizeof(tmp));
return ntohs(tmp);
}
/**
* Read a 32-bit value in network order from an unaligned address to host order.
*
* @param network unaligned address to read network order value from
* @return host order value
*/
static inline u_int32_t untoh32(void *network)
{
char *unaligned = (char*)network;
u_int32_t tmp;
memcpy(&tmp, unaligned, sizeof(tmp));
return ntohl(tmp);
}
/**
* Read a 64-bit value in network order from an unaligned address to host order.
*
* @param network unaligned address to read network order value from
* @return host order value
*/
static inline u_int64_t untoh64(void *network)
{
char *unaligned = (char*)network;
#ifdef be64toh
u_int64_t tmp;
memcpy(&tmp, unaligned, sizeof(tmp));
return be64toh(tmp);
#else
u_int32_t high_part, low_part;
memcpy(&high_part, unaligned, sizeof(high_part));
unaligned += sizeof(high_part);
memcpy(&low_part, unaligned, sizeof(low_part));
high_part = ntohl(high_part);
low_part = ntohl(low_part);
return (((u_int64_t)high_part) << 32) + low_part;
#endif
}
/**
* Special type to count references
*/
typedef volatile u_int refcount_t;
#ifdef HAVE_GCC_ATOMIC_OPERATIONS
#define ref_get(ref) {__sync_fetch_and_add(ref, 1); }
#define ref_put(ref) (!__sync_sub_and_fetch(ref, 1))
#define cas_bool(ptr, oldval, newval) \
(__sync_bool_compare_and_swap(ptr, oldval, newval))
#define cas_ptr(ptr, oldval, newval) \
(__sync_bool_compare_and_swap(ptr, oldval, newval))
#else /* !HAVE_GCC_ATOMIC_OPERATIONS */
/**
* Get a new reference.
*
* Increments the reference counter atomic.
*
* @param ref pointer to ref counter
*/
void ref_get(refcount_t *ref);
/**
* Put back a unused reference.
*
* Decrements the reference counter atomic and
* says if more references available.
*
* @param ref pointer to ref counter
* @return TRUE if no more references counted
*/
bool ref_put(refcount_t *ref);
/**
* Atomically replace value of ptr with newval if it currently equals oldval.
*
* @param ptr pointer to variable
* @param oldval old value of the variable
* @param newval new value set if possible
* @return TRUE if value equaled oldval and newval was written
*/
bool cas_bool(bool *ptr, bool oldval, bool newval);
/**
* Atomically replace value of ptr with newval if it currently equals oldval.
*
* @param ptr pointer to variable
* @param oldval old value of the variable
* @param newval new value set if possible
* @return TRUE if value equaled oldval and newval was written
*/
bool cas_ptr(void **ptr, void *oldval, void *newval);
#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
/**
* printf hook for time_t.
*
* Arguments are:
* time_t* time, bool utc
*/
int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args);
/**
* printf hook for time_t deltas.
*
* Arguments are:
* time_t* begin, time_t* end
*/
int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args);
/**
* printf hook for memory areas.
*
* Arguments are:
* u_char *ptr, u_int len
*/
int mem_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args);
#endif /** UTILS_H_ @}*/