summaryrefslogtreecommitdiff
path: root/src/libstrongswan/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/utils.c')
-rw-r--r--src/libstrongswan/utils.c78
1 files changed, 73 insertions, 5 deletions
diff --git a/src/libstrongswan/utils.c b/src/libstrongswan/utils.c
index 6ffb62aaf..f76245a19 100644
--- a/src/libstrongswan/utils.c
+++ b/src/libstrongswan/utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2010 Tobias Brunner
+ * Copyright (C) 2008-2011 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -20,6 +20,7 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
+#include <inttypes.h>
#include <stdint.h>
#include <limits.h>
#include <dirent.h>
@@ -27,6 +28,7 @@
#include "enum.h"
#include "debug.h"
+#include "utils/enumerator.h"
ENUM(status_names, SUCCESS, NEED_MORE,
"SUCCESS",
@@ -192,6 +194,49 @@ bool mkdir_p(const char *path, mode_t mode)
return TRUE;
}
+#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
*/
@@ -299,6 +344,28 @@ bool ref_put(refcount_t *ref)
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 */
/**
@@ -342,7 +409,7 @@ int time_delta_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
char* unit = "second";
time_t *arg1 = *((time_t**)(args[0]));
time_t *arg2 = *((time_t**)(args[1]));
- time_t delta = abs(*arg1 - *arg2);
+ u_int64_t delta = llabs(*arg1 - *arg2);
if (delta > 2 * 60 * 60 * 24)
{
@@ -359,7 +426,8 @@ int time_delta_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
delta /= 60;
unit = "minute";
}
- return print_in_hook(dst, len, "%d %s%s", delta, unit, (delta == 1)? "":"s");
+ return print_in_hook(dst, len, "%" PRIu64 " %s%s", delta, unit,
+ (delta == 1) ? "" : "s");
}
/**
@@ -376,7 +444,7 @@ int mem_printf_hook(char *dst, size_t dstlen,
printf_hook_spec_t *spec, const void *const *args)
{
char *bytes = *((void**)(args[0]));
- int len = *((size_t*)(args[1]));
+ u_int len = *((int*)(args[1]));
char buffer[BYTES_PER_LINE * 3];
char ascii_buffer[BYTES_PER_LINE + 1];
@@ -387,7 +455,7 @@ int mem_printf_hook(char *dst, size_t dstlen,
int i = 0;
int written = 0;
- written += print_in_hook(dst, dstlen, "=> %d bytes @ %p", len, bytes);
+ written += print_in_hook(dst, dstlen, "=> %u bytes @ %p", len, bytes);
while (bytes_pos < bytes_roof)
{