224 lines
6.3 KiB
C
224 lines
6.3 KiB
C
/*
|
|
* netlink-private/utils.h Local Utility Functions
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation version 2.1
|
|
* of the License.
|
|
*
|
|
* Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
|
|
*/
|
|
|
|
#ifndef NETLINK_UTILS_PRIV_H_
|
|
#define NETLINK_UTILS_PRIV_H_
|
|
|
|
#include <byteswap.h>
|
|
|
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
#define ntohll(x) (x)
|
|
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
#define ntohll(x) bswap_64((x))
|
|
#endif
|
|
#define htonll(x) ntohll(x)
|
|
|
|
/*****************************************************************************/
|
|
|
|
#define _NL_STRINGIFY_ARG(contents) #contents
|
|
#define _NL_STRINGIFY(macro_or_string) _NL_STRINGIFY_ARG (macro_or_string)
|
|
|
|
/*****************************************************************************/
|
|
|
|
#if defined (__GNUC__)
|
|
#define _NL_PRAGMA_WARNING_DO(warning) _NL_STRINGIFY(GCC diagnostic ignored warning)
|
|
#elif defined (__clang__)
|
|
#define _NL_PRAGMA_WARNING_DO(warning) _NL_STRINGIFY(clang diagnostic ignored warning)
|
|
#endif
|
|
|
|
/* you can only suppress a specific warning that the compiler
|
|
* understands. Otherwise you will get another compiler warning
|
|
* about invalid pragma option.
|
|
* It's not that bad however, because gcc and clang often have the
|
|
* same name for the same warning. */
|
|
|
|
#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
|
#define _NL_PRAGMA_WARNING_DISABLE(warning) \
|
|
_Pragma("GCC diagnostic push") \
|
|
_Pragma(_NL_PRAGMA_WARNING_DO("-Wpragmas")) \
|
|
_Pragma(_NL_PRAGMA_WARNING_DO(warning))
|
|
#elif defined (__clang__)
|
|
#define _NL_PRAGMA_WARNING_DISABLE(warning) \
|
|
_Pragma("clang diagnostic push") \
|
|
_Pragma(_NL_PRAGMA_WARNING_DO("-Wunknown-warning-option")) \
|
|
_Pragma(_NL_PRAGMA_WARNING_DO(warning))
|
|
#else
|
|
#define _NL_PRAGMA_WARNING_DISABLE(warning)
|
|
#endif
|
|
|
|
#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
|
#define _NL_PRAGMA_WARNING_REENABLE \
|
|
_Pragma("GCC diagnostic pop")
|
|
#elif defined (__clang__)
|
|
#define _NL_PRAGMA_WARNING_REENABLE \
|
|
_Pragma("clang diagnostic pop")
|
|
#else
|
|
#define _NL_PRAGMA_WARNING_REENABLE
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
|
|
#define _nl_unused __attribute__ ((__unused__))
|
|
#define _nl_auto(fcn) __attribute__ ((__cleanup__(fcn)))
|
|
|
|
/*****************************************************************************/
|
|
|
|
#define _NL_STATIC_ASSERT(cond) ((void) sizeof (char[(cond) ? 1 : -1]))
|
|
|
|
/*****************************************************************************/
|
|
|
|
#if defined(NL_MORE_ASSERTS) && NL_MORE_ASSERTS > 0
|
|
#define _nl_assert(cond) assert(cond)
|
|
#else
|
|
#define _nl_assert(cond) do { if (0) { assert(cond); } } while (0)
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
|
|
#define _NL_AUTO_DEFINE_FCN_VOID0(CastType, name, func) \
|
|
static inline void name (void *v) \
|
|
{ \
|
|
if (*((CastType *) v)) \
|
|
func (*((CastType *) v)); \
|
|
}
|
|
|
|
#define _nl_auto_free _nl_auto(_nl_auto_free_fcn)
|
|
_NL_AUTO_DEFINE_FCN_VOID0 (void *, _nl_auto_free_fcn, free)
|
|
|
|
/*****************************************************************************/
|
|
|
|
extern const char *nl_strerror_l(int err);
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* internal macro to calculate the size of a struct @type up to (and including) @field.
|
|
* this will be used for .minlen policy fields, so that we require only a field of up
|
|
* to the given size. */
|
|
#define _nl_offsetofend(type, field) (offsetof (type, field) + sizeof (((type *) NULL)->field))
|
|
|
|
/*****************************************************************************/
|
|
|
|
#define _nl_clear_pointer(pp, destroy) \
|
|
({ \
|
|
__typeof__ (*(pp)) *_pp = (pp); \
|
|
__typeof__ (*_pp) _p; \
|
|
int _changed = 0; \
|
|
\
|
|
if ( _pp \
|
|
&& (_p = *_pp)) { \
|
|
_nl_unused const void *const _p_check_is_pointer = _p; \
|
|
\
|
|
*_pp = NULL; \
|
|
\
|
|
(destroy) (_p); \
|
|
\
|
|
_changed = 1; \
|
|
} \
|
|
_changed; \
|
|
})
|
|
|
|
#define _nl_clear_free(pp) _nl_clear_pointer (pp, free)
|
|
|
|
#define _nl_steal_pointer(pp) \
|
|
({ \
|
|
__typeof__ (*(pp)) *const _pp = (pp); \
|
|
__typeof__ (*_pp) _p = NULL; \
|
|
\
|
|
if ( _pp \
|
|
&& (_p = *_pp)) { \
|
|
*_pp = NULL; \
|
|
} \
|
|
\
|
|
_p; \
|
|
})
|
|
|
|
/*****************************************************************************/
|
|
|
|
#define _nl_malloc_maybe_a(alloca_maxlen, bytes, to_free) \
|
|
({ \
|
|
const size_t _bytes = (bytes); \
|
|
__typeof__ (to_free) _to_free = (to_free); \
|
|
__typeof__ (*_to_free) _ptr; \
|
|
\
|
|
_NL_STATIC_ASSERT ((alloca_maxlen) <= 500); \
|
|
_nl_assert (_to_free && !*_to_free); \
|
|
\
|
|
if (_bytes <= (alloca_maxlen)) { \
|
|
_ptr = alloca (_bytes); \
|
|
} else { \
|
|
_ptr = malloc (_bytes); \
|
|
*_to_free = _ptr; \
|
|
}; \
|
|
\
|
|
_ptr; \
|
|
})
|
|
|
|
/*****************************************************************************/
|
|
|
|
static inline char *
|
|
_nl_strncpy_trunc(char *dst, const char *src, size_t len)
|
|
{
|
|
/* we don't use/reimplement strlcpy(), because we want the fill-all-with-NUL
|
|
* behavior of strncpy(). This is just strncpy() with gracefully handling trunction
|
|
* (and disabling the "-Wstringop-truncation" warning).
|
|
*
|
|
* Note that truncation is silently accepted.
|
|
*/
|
|
|
|
_NL_PRAGMA_WARNING_DISABLE ("-Wstringop-truncation");
|
|
_NL_PRAGMA_WARNING_DISABLE ("-Wstringop-overflow");
|
|
|
|
if (len > 0) {
|
|
_nl_assert(dst);
|
|
_nl_assert(src);
|
|
|
|
strncpy(dst, src, len);
|
|
|
|
dst[len - 1] = '\0';
|
|
}
|
|
|
|
_NL_PRAGMA_WARNING_REENABLE;
|
|
_NL_PRAGMA_WARNING_REENABLE;
|
|
|
|
return dst;
|
|
}
|
|
|
|
static inline char *
|
|
_nl_strncpy(char *dst, const char *src, size_t len)
|
|
{
|
|
/* we don't use/reimplement strlcpy(), because we want the fill-all-with-NUL
|
|
* behavior of strncpy(). This is just strncpy() with gracefully handling trunction
|
|
* (and disabling the "-Wstringop-truncation" warning).
|
|
*
|
|
* Note that truncation is still a bug and there is an _nl_assert()
|
|
* against that.
|
|
*/
|
|
|
|
if (len > 0) {
|
|
_nl_assert(dst);
|
|
_nl_assert(src);
|
|
|
|
strncpy(dst, src, len);
|
|
|
|
/* Truncation is a bug and we assert against it. But note that this
|
|
* assertion is disabled by default because we cannot be sure that
|
|
* there are not wrong uses of _nl_strncpy() where truncation might
|
|
* happen (wrongly!!). */
|
|
_nl_assert (memchr(dst, '\0', len));
|
|
|
|
dst[len - 1] = '\0';
|
|
}
|
|
|
|
return dst;
|
|
}
|
|
|
|
#endif
|