diff --git a/configure.ac b/configure.ac index ffcb7a547..9ac51694a 100644 --- a/configure.ac +++ b/configure.ac @@ -489,6 +489,7 @@ AC_CHECK_FUNC( ) AC_CHECK_FUNCS(prctl mallinfo getpass closefrom getpwnam_r getgrnam_r getpwuid_r) +AC_CHECK_FUNCS(fmemopen funopen) AC_CHECK_HEADERS(sys/sockio.h glob.h net/if_tun.h linux/fib_rules.h) AC_CHECK_HEADERS(net/pfkeyv2.h netipsec/ipsec.h netinet6/ipsec.h linux/udp.h) diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c index 30084cd81..3a535c5a2 100644 --- a/src/libstrongswan/utils/utils.c +++ b/src/libstrongswan/utils/utils.c @@ -29,6 +29,7 @@ #include "collections/enumerator.h" #include "utils/debug.h" +#include "utils/chunk.h" ENUM(status_names, SUCCESS, NEED_MORE, "SUCCESS", @@ -513,6 +514,51 @@ _cas_impl(ptr, void*) #endif /* HAVE_GCC_ATOMIC_OPERATIONS */ + +#if HAVE_FMEMOPEN == fallback + +static int fmemread(chunk_t *cookie, char *buf, int size) +{ + int len; + + len = min(size, cookie->len); + memcpy(buf, cookie->ptr, len); + *cookie = chunk_skip(*cookie, len); + + return len; +} + +static int fmemwrite(chunk_t *cookie, const char *buf, int size) +{ + int len; + + len = min(size, cookie->len); + memcpy(cookie->ptr, buf, len); + *cookie = chunk_skip(*cookie, len); + + return len; +} + +static int fmemclose(void *cookie) +{ + free(cookie); + return 0; +} + +FILE *fmemopen(void *buf, size_t size, const char *mode) +{ + chunk_t *cookie; + + INIT(cookie, + .ptr = buf, + .len = size, + ); + + return funopen(cookie, (void*)fmemread, (void*)fmemwrite, NULL, fmemclose); +} + +#endif /* FMEMOPEN fallback*/ + /** * Described in header. */ diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h index 5c237a7f2..2cbab5b46 100644 --- a/src/libstrongswan/utils/utils.h +++ b/src/libstrongswan/utils/utils.h @@ -765,6 +765,21 @@ bool cas_ptr(void **ptr, void *oldval, void *newval); #endif /* HAVE_GCC_ATOMIC_OPERATIONS */ +#ifndef HAVE_FMEMOPEN +# ifdef HAVE_FUNOPEN +# define HAVE_FMEMOPEN fallback +/** + * fmemopen(3) fallback using BSD funopen. + * + * We could also provide one using fopencookie(), but should we have it we + * most likely have fmemopen(). + * + * fseek() is currently not supported. + */ +FILE *fmemopen(void *buf, size_t size, const char *mode); +# endif /* FUNOPEN */ +#endif /* FMEMOPEN */ + /** * printf hook for time_t. *