[network-manager-openvpn/th/cleanup: 2/11] shared: re-import shared files
- From: Thomas Haller <thaller src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-openvpn/th/cleanup: 2/11] shared: re-import shared files
- Date: Mon, 20 Nov 2017 11:40:09 +0000 (UTC)
commit ba1453a8766e89c58127352a27a3522de0b0bcbe
Author: Thomas Haller <thaller redhat com>
Date: Mon Nov 20 11:41:49 2017 +0100
shared: re-import shared files
shared/nm-utils/nm-macros-internal.h | 309 ++++++++++++++++++++++++++--------
shared/nm-utils/nm-shared-utils.c | 316 +++++++++++++++++++++++++++++++---
shared/nm-utils/nm-shared-utils.h | 136 ++++++++++++++-
shared/nm-utils/nm-test-utils.h | 57 ++++++
4 files changed, 718 insertions(+), 100 deletions(-)
---
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h
index b946a27..ce13d3a 100644
--- a/shared/nm-utils/nm-macros-internal.h
+++ b/shared/nm-utils/nm-macros-internal.h
@@ -26,11 +26,30 @@
#include <stdlib.h>
#include <errno.h>
-#define _nm_packed __attribute__ ((packed))
-#define _nm_unused __attribute__ ((unused))
-#define _nm_pure __attribute__ ((pure))
-#define _nm_const __attribute__ ((const))
-#define _nm_printf(a,b) __attribute__ ((__format__ (__printf__, a, b)))
+#define _nm_packed __attribute__ ((packed))
+#define _nm_unused __attribute__ ((unused))
+#define _nm_pure __attribute__ ((pure))
+#define _nm_const __attribute__ ((const))
+#define _nm_printf(a,b) __attribute__ ((__format__ (__printf__, a, b)))
+#define _nm_align(s) __attribute__ ((aligned (s)))
+#define _nm_alignof(type) __alignof (type)
+#define _nm_alignas(type) _nm_align (_nm_alignof (type))
+
+/*****************************************************************************/
+
+#ifdef thread_local
+#define _nm_thread_local thread_local
+/*
+ * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__
+ * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769
+ */
+#elif __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) &&
__GLIBC__ == 2 && __GLIBC_MINOR__ < 16))
+#define _nm_thread_local _Thread_local
+#else
+#define _nm_thread_local __thread
+#endif
+
+/*****************************************************************************/
#include "nm-glib.h"
@@ -40,6 +59,8 @@
#define nm_auto(fcn) __attribute__ ((cleanup(fcn)))
+static inline int nm_close (int fd);
+
/**
* nm_auto_free:
*
@@ -49,6 +70,30 @@
GS_DEFINE_CLEANUP_FUNCTION(void*, _nm_auto_free_impl, free)
static inline void
+nm_free_secret (char *secret)
+{
+ if (secret) {
+ memset (secret, 0, strlen (secret));
+ g_free (secret);
+ }
+}
+
+static inline void
+_nm_auto_free_secret_impl (char **v)
+{
+ nm_free_secret (*v);
+}
+
+/**
+ * nm_auto_free_secret:
+ *
+ * Call g_free() on a variable location when it goes out of scope.
+ * Also, previously, calls memset(loc, 0, strlen(loc)) to clear out
+ * the secret.
+ */
+#define nm_auto_free_secret nm_auto(_nm_auto_free_secret_impl)
+
+static inline void
_nm_auto_unset_gvalue_impl (GValue *v)
{
g_value_unset (v);
@@ -77,7 +122,7 @@ _nm_auto_close_impl (int *pfd)
if (*pfd >= 0) {
int errsv = errno;
- (void) close (*pfd);
+ (void) nm_close (*pfd);
errno = errsv;
}
}
@@ -242,31 +287,137 @@ NM_G_ERROR_MSG (GError *error)
/*****************************************************************************/
-#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 9 ))) || (defined
(__clang__))
+#ifndef _NM_CC_SUPPORT_AUTO_TYPE
+#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 )))
+#define _NM_CC_SUPPORT_AUTO_TYPE 1
+#else
+#define _NM_CC_SUPPORT_AUTO_TYPE 0
+#endif
+#endif
+
+#ifndef _NM_CC_SUPPORT_GENERIC
+#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 ))) || (defined
(__clang__))
#define _NM_CC_SUPPORT_GENERIC 1
#else
#define _NM_CC_SUPPORT_GENERIC 0
#endif
+#endif
+
+#if _NM_CC_SUPPORT_AUTO_TYPE
+#define _nm_auto_type __auto_type
+#endif
+
+#if _NM_CC_SUPPORT_GENERIC
+#define _NM_CONSTCAST_FULL_1(type, obj_expr, obj) \
+ (_Generic ((obj_expr), \
+ const void *const: ((const type *) (obj)), \
+ const void * : ((const type *) (obj)), \
+ void *const: (( type *) (obj)), \
+ void * : (( type *) (obj)), \
+ const type *const: ((const type *) (obj)), \
+ const type * : ((const type *) (obj)), \
+ type *const: (( type *) (obj)), \
+ type * : (( type *) (obj))))
+#define _NM_CONSTCAST_FULL_2(type, obj_expr, obj, alias_type2) \
+ (_Generic ((obj_expr), \
+ const void *const: ((const type *) (obj)), \
+ const void * : ((const type *) (obj)), \
+ void *const: (( type *) (obj)), \
+ void * : (( type *) (obj)), \
+ const alias_type2 *const: ((const type *) (obj)), \
+ const alias_type2 * : ((const type *) (obj)), \
+ alias_type2 *const: (( type *) (obj)), \
+ alias_type2 * : (( type *) (obj)), \
+ const type *const: ((const type *) (obj)), \
+ const type * : ((const type *) (obj)), \
+ type *const: (( type *) (obj)), \
+ type * : (( type *) (obj))))
+#define _NM_CONSTCAST_FULL_3(type, obj_expr, obj, alias_type2, alias_type3) \
+ (_Generic ((obj_expr), \
+ const void *const: ((const type *) (obj)), \
+ const void * : ((const type *) (obj)), \
+ void *const: (( type *) (obj)), \
+ void * : (( type *) (obj)), \
+ const alias_type2 *const: ((const type *) (obj)), \
+ const alias_type2 * : ((const type *) (obj)), \
+ alias_type2 *const: (( type *) (obj)), \
+ alias_type2 * : (( type *) (obj)), \
+ const alias_type3 *const: ((const type *) (obj)), \
+ const alias_type3 * : ((const type *) (obj)), \
+ alias_type3 *const: (( type *) (obj)), \
+ alias_type3 * : (( type *) (obj)), \
+ const type *const: ((const type *) (obj)), \
+ const type * : ((const type *) (obj)), \
+ type *const: (( type *) (obj)), \
+ type * : (( type *) (obj))))
+#define _NM_CONSTCAST_FULL_4(type, obj_expr, obj, alias_type2, alias_type3, alias_type4) \
+ (_Generic ((obj_expr), \
+ const void *const: ((const type *) (obj)), \
+ const void * : ((const type *) (obj)), \
+ void *const: (( type *) (obj)), \
+ void * : (( type *) (obj)), \
+ const alias_type2 *const: ((const type *) (obj)), \
+ const alias_type2 * : ((const type *) (obj)), \
+ alias_type2 *const: (( type *) (obj)), \
+ alias_type2 * : (( type *) (obj)), \
+ const alias_type3 *const: ((const type *) (obj)), \
+ const alias_type3 * : ((const type *) (obj)), \
+ alias_type3 *const: (( type *) (obj)), \
+ alias_type3 * : (( type *) (obj)), \
+ const alias_type4 *const: ((const type *) (obj)), \
+ const alias_type4 * : ((const type *) (obj)), \
+ alias_type4 *const: (( type *) (obj)), \
+ alias_type4 * : (( type *) (obj)), \
+ const type *const: ((const type *) (obj)), \
+ const type * : ((const type *) (obj)), \
+ type *const: (( type *) (obj)), \
+ type * : (( type *) (obj))))
+#define _NM_CONSTCAST_FULL_x(type, obj_expr, obj, n, ...) (_NM_CONSTCAST_FULL_##n (type, obj_expr, obj,
##__VA_ARGS__))
+#define _NM_CONSTCAST_FULL_y(type, obj_expr, obj, n, ...) (_NM_CONSTCAST_FULL_x (type, obj_expr, obj, n,
##__VA_ARGS__))
+#define NM_CONSTCAST_FULL( type, obj_expr, obj, ...) (_NM_CONSTCAST_FULL_y (type, obj_expr, obj,
NM_NARG (dummy, ##__VA_ARGS__), ##__VA_ARGS__))
+#else
+#define NM_CONSTCAST_FULL( type, obj_expr, obj, ...) ((type *) (obj))
+#endif
+
+#define NM_CONSTCAST(type, obj, ...) \
+ NM_CONSTCAST_FULL(type, (obj), (obj), ##__VA_ARGS__)
+
+#define NM_GOBJECT_CAST(type, obj, is_check, ...) \
+ ({ \
+ const void *_obj = (obj); \
+ \
+ nm_assert (_obj || (is_check (_obj))); \
+ NM_CONSTCAST_FULL (type, (obj), _obj, GObject, ##__VA_ARGS__); \
+ })
+
+#define NM_GOBJECT_CAST_NON_NULL(type, obj, is_check, ...) \
+ ({ \
+ const void *_obj = (obj); \
+ \
+ nm_assert (is_check (_obj)); \
+ NM_CONSTCAST_FULL (type, (obj), _obj, GObject, ##__VA_ARGS__); \
+ })
+
+#if _NM_CC_SUPPORT_GENERIC
+/* returns @value, if the type of @value matches @type.
+ * This requires support for C11 _Generic(). If no support is
+ * present, this returns @value directly.
+ *
+ * It's useful to check the let the compiler ensure that @value is
+ * of a certain type. */
+#define _NM_ENSURE_TYPE(type, value) (_Generic ((value), type: (value)))
+#else
+#define _NM_ENSURE_TYPE(type, value) (value)
+#endif
#if _NM_CC_SUPPORT_GENERIC
-#define _NM_CONSTCAST(type, obj) \
- (_Generic ((obj), \
- void * : ((type *) (obj)), \
- void *const : ((type *) (obj)), \
- const void * : ((const type *) (obj)), \
- const void *const: ((const type *) (obj)), \
- const type * : (obj), \
- const type *const: (obj), \
- type * : (obj), \
- type *const : (obj)))
+#define NM_PROPAGATE_CONST(test_expr, ptr) \
+ (_Generic ((test_expr), \
+ const typeof (*(test_expr)) *: ((const typeof (*(ptr)) *) (ptr)), \
+ default: (_Generic ((test_expr), \
+ typeof (*(test_expr)) *: (ptr)))))
#else
-/* _NM_CONSTCAST() is there to preserve constness of a pointer.
- * It uses C11's _Generic(). If that is not supported, we fall back
- * to casting away constness. So, with _Generic, we get some additional
- * static type checking by preserving constness, without, we cast it
- * to a non-const pointer. */
-#define _NM_CONSTCAST(type, obj) \
- ((type *) (obj))
+#define NM_PROPAGATE_CONST(test_expr, ptr) (ptr)
#endif
/*****************************************************************************/
@@ -410,21 +561,6 @@ _NM_IN_STRSET_streq (const char *x, const char *s)
/*****************************************************************************/
-static inline guint
-NM_HASH_COMBINE (guint h, guint val)
-{
- /* see g_str_hash() for reasons */
- return (h << 5) + h + val;
-}
-
-static inline guint
-NM_HASH_COMBINE_UINT64 (guint h, guint64 val)
-{
- return NM_HASH_COMBINE (h, (((guint) val) & 0xFFFFFFFFu) + ((guint) (val >> 32)));
-}
-
-/*****************************************************************************/
-
/* NM_CACHED_QUARK() returns the GQuark for @string, but caches
* it in a static variable to speed up future lookups.
*
@@ -563,39 +699,17 @@ _notify (obj_type *obj, _PropertyEnums prop) \
/*****************************************************************************/
-/* these are implemented as a macro, because they accept self
- * as both (type*) and (const type*), and return a const
- * private pointer accordingly. */
-#define __NM_GET_PRIVATE(self, type, is_check, addrop) \
- ({ \
- /* preserve the const-ness of self. Unfortunately, that
- * way, @self cannot be a void pointer */ \
- typeof (self) _self = (self); \
- \
- /* Get compiler error if variable is of wrong type */ \
- _nm_unused const type *const _self2 = (_self); \
- \
- nm_assert (is_check (_self)); \
- ( addrop ( _NM_CONSTCAST (type, _self)->_priv) ); \
- })
-
-#define _NM_GET_PRIVATE(self, type, is_check) __NM_GET_PRIVATE(self, type, is_check, &)
-#define _NM_GET_PRIVATE_PTR(self, type, is_check) __NM_GET_PRIVATE(self, type, is_check, )
-
-#define __NM_GET_PRIVATE_VOID(self, type, is_check, result_cmd) \
+#define _NM_GET_PRIVATE(self, type, is_check, ...) (&(NM_GOBJECT_CAST_NON_NULL (type, (self), is_check,
##__VA_ARGS__)->_priv))
+#if _NM_CC_SUPPORT_AUTO_TYPE
+#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) \
({ \
- /* (self) can be any non-const pointer. It will be cast to "type *".
- * We don't explicitly cast but assign first to (void *) which
- * will fail if @self is pointing to const. */ \
- void *const _self1 = (self); \
- type *const _self = _self1; \
+ _nm_auto_type _self = NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__); \
\
- nm_assert (is_check (_self)); \
- ( result_cmd ); \
+ NM_PROPAGATE_CONST (_self, _self->_priv); \
})
-
-#define _NM_GET_PRIVATE_VOID(self, type, is_check) __NM_GET_PRIVATE_VOID(self, type, is_check,
&_self->_priv)
-#define _NM_GET_PRIVATE_PTR_VOID(self, type, is_check) __NM_GET_PRIVATE_VOID(self, type, is_check,
_self->_priv)
+#else
+#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) (NM_GOBJECT_CAST_NON_NULL (type, (self), is_check,
##__VA_ARGS__)->_priv)
+#endif
/*****************************************************************************/
@@ -858,6 +972,33 @@ nm_strstrip (char *str)
return str ? g_strstrip (str) : NULL;
}
+static inline const char *
+nm_strstrip_avoid_copy (const char *str, char **str_free)
+{
+ gsize l;
+ char *s;
+
+ nm_assert (str_free && !*str_free);
+
+ if (!str)
+ return NULL;
+
+ str = nm_str_skip_leading_spaces (str);
+ l = strlen (str);
+ if ( l == 0
+ || !g_ascii_isspace (str[l - 1]))
+ return str;
+ while ( l > 0
+ && g_ascii_isspace (str[l - 1]))
+ l--;
+
+ s = g_new (char, l + 1);
+ memcpy (s, str, l);
+ s[l] = '\0';
+ *str_free = s;
+ return s;
+}
+
/* g_ptr_array_sort()'s compare function takes pointers to the
* value. Thus, you cannot use strcmp directly. You can use
* nm_strcmp_p().
@@ -1106,4 +1247,34 @@ nm_decode_version (guint version, guint *major, guint *minor, guint *micro)
/*****************************************************************************/
+static inline int
+nm_steal_fd (int *p_fd)
+{
+ int fd;
+
+ if ( p_fd
+ && ((fd = *p_fd) >= 0)) {
+ *p_fd = -1;
+ return fd;
+ }
+ return -1;
+}
+
+/**
+ * nm_close:
+ *
+ * Like close() but throws an assertion if the input fd is
+ * invalid. Closing an invalid fd is a programming error, so
+ * it's better to catch it early.
+ */
+static inline int
+nm_close (int fd)
+{
+ int r;
+
+ r = close (fd);
+ nm_assert (r != -1 || fd < 0 || errno != EBADF);
+ return r;
+}
+
#endif /* __NM_MACROS_INTERNAL_H__ */
diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c
index 0810d7b..79d1e6a 100644
--- a/shared/nm-utils/nm-shared-utils.c
+++ b/shared/nm-utils/nm-shared-utils.c
@@ -25,6 +25,8 @@
#include <errno.h>
#include <arpa/inet.h>
+#include <poll.h>
+#include <fcntl.h>
/*****************************************************************************/
@@ -116,6 +118,162 @@ nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...)
/*****************************************************************************/
/**
+ * nm_strquote:
+ * @buf: the output buffer of where to write the quoted @str argument.
+ * @buf_len: the size of @buf.
+ * @str: (allow-none): the string to quote.
+ *
+ * Writes @str to @buf with quoting. The resulting buffer
+ * is always NUL terminated, unless @buf_len is zero.
+ * If @str is %NULL, it writes "(null)".
+ *
+ * If @str needs to be truncated, the closing quote is '^' instead
+ * of '"'.
+ *
+ * This is similar to nm_strquote_a(), which however uses alloca()
+ * to allocate a new buffer. Also, here @buf_len is the size of @buf,
+ * while nm_strquote_a() has the number of characters to print. The latter
+ * doesn't include the quoting.
+ *
+ * Returns: the input buffer with the quoted string.
+ */
+const char *
+nm_strquote (char *buf, gsize buf_len, const char *str)
+{
+ const char *const buf0 = buf;
+
+ if (!str) {
+ nm_utils_strbuf_append_str (&buf, &buf_len, "(null)");
+ goto out;
+ }
+
+ if (G_UNLIKELY (buf_len <= 2)) {
+ switch (buf_len) {
+ case 2:
+ *(buf++) = '^';
+ /* fall-through */
+ case 1:
+ *(buf++) = '\0';
+ break;
+ }
+ goto out;
+ }
+
+ *(buf++) = '"';
+ buf_len--;
+
+ nm_utils_strbuf_append_str (&buf, &buf_len, str);
+
+ /* if the string was too long we indicate truncation with a
+ * '^' instead of a closing quote. */
+ if (G_UNLIKELY (buf_len <= 1)) {
+ switch (buf_len) {
+ case 1:
+ buf[-1] = '^';
+ break;
+ case 0:
+ buf[-2] = '^';
+ break;
+ default:
+ nm_assert_not_reached ();
+ break;
+ }
+ } else {
+ nm_assert (buf_len >= 2);
+ *(buf++) = '"';
+ *(buf++) = '\0';
+ }
+
+out:
+ return buf0;
+}
+
+/*****************************************************************************/
+
+char _nm_utils_to_string_buffer[];
+
+void
+nm_utils_to_string_buffer_init (char **buf, gsize *len)
+{
+ if (!*buf) {
+ *buf = _nm_utils_to_string_buffer;
+ *len = sizeof (_nm_utils_to_string_buffer);
+ }
+}
+
+gboolean
+nm_utils_to_string_buffer_init_null (gconstpointer obj, char **buf, gsize *len)
+{
+ nm_utils_to_string_buffer_init (buf, len);
+ if (!obj) {
+ g_strlcpy (*buf, "(null)", *len);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*****************************************************************************/
+
+const char *
+nm_utils_flags2str (const NMUtilsFlags2StrDesc *descs,
+ gsize n_descs,
+ unsigned flags,
+ char *buf,
+ gsize len)
+{
+ gsize i;
+ char *p;
+
+#if NM_MORE_ASSERTS > 10
+ nm_assert (descs);
+ nm_assert (n_descs > 0);
+ for (i = 0; i < n_descs; i++) {
+ gsize j;
+
+ nm_assert (descs[i].name && descs[i].name[0]);
+ for (j = 0; j < i; j++)
+ nm_assert (descs[j].flag != descs[i].flag);
+ }
+#endif
+
+ nm_utils_to_string_buffer_init (&buf, &len);
+
+ if (!len)
+ return buf;
+
+ buf[0] = '\0';
+ p = buf;
+ if (!flags) {
+ for (i = 0; i < n_descs; i++) {
+ if (!descs[i].flag) {
+ nm_utils_strbuf_append_str (&p, &len, descs[i].name);
+ break;
+ }
+ }
+ return buf;
+ }
+
+ for (i = 0; flags && i < n_descs; i++) {
+ if ( descs[i].flag
+ && NM_FLAGS_ALL (flags, descs[i].flag)) {
+ flags &= ~descs[i].flag;
+
+ if (buf[0] != '\0')
+ nm_utils_strbuf_append_c (&p, &len, ',');
+ nm_utils_strbuf_append_str (&p, &len, descs[i].name);
+ }
+ }
+ if (flags) {
+ if (buf[0] != '\0')
+ nm_utils_strbuf_append_c (&p, &len, ',');
+ nm_utils_strbuf_append (&p, &len, "0x%x", flags);
+ }
+ return buf;
+};
+
+/*****************************************************************************/
+
+/**
* _nm_utils_ip4_prefix_to_netmask:
* @prefix: a CIDR prefix
*
@@ -174,41 +332,58 @@ nm_utils_ip_is_site_local (int addr_family,
/*****************************************************************************/
gboolean
-nm_utils_parse_inaddr_bin (const char *text,
- int family,
- gpointer out_addr)
+nm_utils_parse_inaddr_bin (int addr_family,
+ const char *text,
+ gpointer out_addr)
{
NMIPAddr addrbin;
g_return_val_if_fail (text, FALSE);
- if (family == AF_UNSPEC)
- family = strchr (text, ':') ? AF_INET6 : AF_INET;
+ if (addr_family == AF_UNSPEC)
+ addr_family = strchr (text, ':') ? AF_INET6 : AF_INET;
else
- g_return_val_if_fail (NM_IN_SET (family, AF_INET, AF_INET6), FALSE);
+ g_return_val_if_fail (NM_IN_SET (addr_family, AF_INET, AF_INET6), FALSE);
- if (inet_pton (family, text, out_addr ?: &addrbin) != 1)
+ /* use a temporary variable @addrbin, to guarantee that @out_addr
+ * is only modified on success. */
+ if (inet_pton (addr_family, text, &addrbin) != 1)
return FALSE;
+
+ if (out_addr) {
+ switch (addr_family) {
+ case AF_INET:
+ *((in_addr_t *) out_addr) = addrbin.addr4;
+ break;
+ case AF_INET6:
+ *((struct in6_addr *) out_addr) = addrbin.addr6;
+ break;
+ default:
+ nm_assert_not_reached ();
+ }
+ }
return TRUE;
}
gboolean
-nm_utils_parse_inaddr (const char *text,
- int family,
+nm_utils_parse_inaddr (int addr_family,
+ const char *text,
char **out_addr)
{
NMIPAddr addrbin;
char addrstr_buf[MAX (INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
- if (!nm_utils_parse_inaddr_bin (text, family, &addrbin))
+ nm_assert (!out_addr || !*out_addr);
+
+ if (!nm_utils_parse_inaddr_bin (addr_family, text, &addrbin))
return FALSE;
- NM_SET_OUT (out_addr, g_strdup (inet_ntop (family, &addrbin, addrstr_buf, sizeof (addrstr_buf))));
+ NM_SET_OUT (out_addr, g_strdup (inet_ntop (addr_family, &addrbin, addrstr_buf, sizeof
(addrstr_buf))));
return TRUE;
}
gboolean
-nm_utils_parse_inaddr_prefix_bin (const char *text,
- int family,
+nm_utils_parse_inaddr_prefix_bin (int addr_family,
+ const char *text,
gpointer out_addr,
int *out_prefix)
{
@@ -221,12 +396,12 @@ nm_utils_parse_inaddr_prefix_bin (const char *text,
g_return_val_if_fail (text, FALSE);
- if (family == AF_UNSPEC)
- family = strchr (text, ':') ? AF_INET6 : AF_INET;
+ if (addr_family == AF_UNSPEC)
+ addr_family = strchr (text, ':') ? AF_INET6 : AF_INET;
- if (family == AF_INET)
+ if (addr_family == AF_INET)
addr_len = sizeof (in_addr_t);
- else if (family == AF_INET6)
+ else if (addr_family == AF_INET6)
addr_len = sizeof (struct in6_addr);
else
g_return_val_if_reached (FALSE);
@@ -237,13 +412,13 @@ nm_utils_parse_inaddr_prefix_bin (const char *text,
else
addrstr = text;
- if (inet_pton (family, addrstr, &addrbin) != 1)
+ if (inet_pton (addr_family, addrstr, &addrbin) != 1)
return FALSE;
if (slash) {
prefix = _nm_utils_ascii_str_to_int64 (slash + 1, 10,
0,
- family == AF_INET ? 32 : 128,
+ addr_family == AF_INET ? 32 : 128,
-1);
if (prefix == -1)
return FALSE;
@@ -256,17 +431,17 @@ nm_utils_parse_inaddr_prefix_bin (const char *text,
}
gboolean
-nm_utils_parse_inaddr_prefix (const char *text,
- int family,
+nm_utils_parse_inaddr_prefix (int addr_family,
+ const char *text,
char **out_addr,
int *out_prefix)
{
NMIPAddr addrbin;
char addrstr_buf[MAX (INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
- if (!nm_utils_parse_inaddr_prefix_bin (text, family, &addrbin, out_prefix))
+ if (!nm_utils_parse_inaddr_prefix_bin (addr_family, text, &addrbin, out_prefix))
return FALSE;
- NM_SET_OUT (out_addr, g_strdup (inet_ntop (family, &addrbin, addrstr_buf, sizeof (addrstr_buf))));
+ NM_SET_OUT (out_addr, g_strdup (inet_ntop (addr_family, &addrbin, addrstr_buf, sizeof
(addrstr_buf))));
return TRUE;
}
@@ -819,3 +994,98 @@ nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flags)
}
return str;
}
+
+/*****************************************************************************/
+
+/* taken from systemd's fd_wait_for_event(). Note that the timeout
+ * is here in nano-seconds, not micro-seconds. */
+int
+nm_utils_fd_wait_for_event (int fd, int event, gint64 timeout_ns)
+{
+ struct pollfd pollfd = {
+ .fd = fd,
+ .events = event,
+ };
+ struct timespec ts, *pts;
+ int r;
+
+ if (timeout_ns < 0)
+ pts = NULL;
+ else {
+ ts.tv_sec = (time_t) (timeout_ns / NM_UTILS_NS_PER_SECOND);
+ ts.tv_nsec = (long int) (timeout_ns % NM_UTILS_NS_PER_SECOND);
+ pts = &ts;
+ }
+
+ r = ppoll (&pollfd, 1, pts, NULL);
+ if (r < 0)
+ return -errno;
+ if (r == 0)
+ return 0;
+ return pollfd.revents;
+}
+
+/* taken from systemd's loop_read() */
+ssize_t
+nm_utils_fd_read_loop (int fd, void *buf, size_t nbytes, bool do_poll)
+{
+ uint8_t *p = buf;
+ ssize_t n = 0;
+
+ g_return_val_if_fail (fd >= 0, -EINVAL);
+ g_return_val_if_fail (buf, -EINVAL);
+
+ /* If called with nbytes == 0, let's call read() at least
+ * once, to validate the operation */
+
+ if (nbytes > (size_t) SSIZE_MAX)
+ return -EINVAL;
+
+ do {
+ ssize_t k;
+
+ k = read (fd, p, nbytes);
+ if (k < 0) {
+ if (errno == EINTR)
+ continue;
+
+ if (errno == EAGAIN && do_poll) {
+
+ /* We knowingly ignore any return value here,
+ * and expect that any error/EOF is reported
+ * via read() */
+
+ (void) nm_utils_fd_wait_for_event (fd, POLLIN, -1);
+ continue;
+ }
+
+ return n > 0 ? n : -errno;
+ }
+
+ if (k == 0)
+ return n;
+
+ g_assert ((size_t) k <= nbytes);
+
+ p += k;
+ nbytes -= k;
+ n += k;
+ } while (nbytes > 0);
+
+ return n;
+}
+
+/* taken from systemd's loop_read_exact() */
+int
+nm_utils_fd_read_loop_exact (int fd, void *buf, size_t nbytes, bool do_poll)
+{
+ ssize_t n;
+
+ n = nm_utils_fd_read_loop (fd, buf, nbytes, do_poll);
+ if (n < 0)
+ return (int) n;
+ if ((size_t) n != nbytes)
+ return -EIO;
+
+ return 0;
+}
diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h
index 4a93016..a092a6b 100644
--- a/shared/nm-utils/nm-shared-utils.h
+++ b/shared/nm-utils/nm-shared-utils.h
@@ -26,6 +26,31 @@
/*****************************************************************************/
+static inline char
+nm_utils_addr_family_to_char (int addr_family)
+{
+ switch (addr_family) {
+ case AF_INET: return '4';
+ case AF_INET6: return '6';
+ }
+ g_return_val_if_reached ('?');
+}
+
+static inline gsize
+nm_utils_addr_family_to_size (int addr_family)
+{
+ switch (addr_family) {
+ case AF_INET: return sizeof (in_addr_t);
+ case AF_INET6: return sizeof (struct in6_addr);
+ }
+ g_return_val_if_reached (0);
+}
+
+#define nm_assert_addr_family(addr_family) \
+ nm_assert (NM_IN_SET ((addr_family), AF_INET, AF_INET6))
+
+/*****************************************************************************/
+
typedef struct {
union {
guint8 addr_ptr[1];
@@ -41,6 +66,19 @@ typedef struct {
extern const NMIPAddr nm_ip_addr_zero;
+static inline void
+nm_ip_addr_set (int addr_family, gpointer dst, const NMIPAddr *src)
+{
+ nm_assert_addr_family (addr_family);
+ nm_assert (dst);
+ nm_assert (src);
+
+ if (addr_family != AF_INET6)
+ *((in_addr_t *) dst) = src->addr4;
+ else
+ *((struct in6_addr *) dst) = src->addr6;
+}
+
/*****************************************************************************/
#define NM_CMP_RETURN(c) \
@@ -151,6 +189,8 @@ void nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...) _n
void nm_utils_strbuf_append_c (char **buf, gsize *len, char c);
void nm_utils_strbuf_append_str (char **buf, gsize *len, const char *str);
+const char *nm_strquote (char *buf, gsize buf_len, const char *str);
+
/*****************************************************************************/
const char **nm_utils_strsplit_set (const char *str, const char *delimiters);
@@ -172,21 +212,21 @@ gboolean nm_utils_ip_is_site_local (int addr_family,
/*****************************************************************************/
-gboolean nm_utils_parse_inaddr_bin (const char *text,
- int family,
+gboolean nm_utils_parse_inaddr_bin (int addr_family,
+ const char *text,
gpointer out_addr);
-gboolean nm_utils_parse_inaddr (const char *text,
- int family,
+gboolean nm_utils_parse_inaddr (int addr_family,
+ const char *text,
char **out_addr);
-gboolean nm_utils_parse_inaddr_prefix_bin (const char *text,
- int family,
+gboolean nm_utils_parse_inaddr_prefix_bin (int addr_family,
+ const char *text,
gpointer out_addr,
int *out_prefix);
-gboolean nm_utils_parse_inaddr_prefix (const char *text,
- int family,
+gboolean nm_utils_parse_inaddr_prefix (int addr_family,
+ const char *text,
char **out_addr,
int *out_prefix);
@@ -197,6 +237,74 @@ gint _nm_utils_ascii_str_to_bool (const char *str,
/*****************************************************************************/
+extern char _nm_utils_to_string_buffer[2096];
+
+void nm_utils_to_string_buffer_init (char **buf, gsize *len);
+gboolean nm_utils_to_string_buffer_init_null (gconstpointer obj, char **buf, gsize *len);
+
+/*****************************************************************************/
+
+typedef struct {
+ unsigned flag;
+ const char *name;
+} NMUtilsFlags2StrDesc;
+
+#define NM_UTILS_FLAGS2STR(f, n) { .flag = f, .name = ""n, }
+
+#define _NM_UTILS_FLAGS2STR_DEFINE(scope, fcn_name, flags_type, ...) \
+scope const char * \
+fcn_name (flags_type flags, char *buf, gsize len) \
+{ \
+ static const NMUtilsFlags2StrDesc descs[] = { \
+ __VA_ARGS__ \
+ }; \
+ G_STATIC_ASSERT (sizeof (flags_type) <= sizeof (unsigned)); \
+ return nm_utils_flags2str (descs, G_N_ELEMENTS (descs), flags, buf, len); \
+};
+
+#define NM_UTILS_FLAGS2STR_DEFINE(fcn_name, flags_type, ...) \
+ _NM_UTILS_FLAGS2STR_DEFINE (, fcn_name, flags_type, __VA_ARGS__)
+#define NM_UTILS_FLAGS2STR_DEFINE_STATIC(fcn_name, flags_type, ...) \
+ _NM_UTILS_FLAGS2STR_DEFINE (static, fcn_name, flags_type, __VA_ARGS__)
+
+const char *nm_utils_flags2str (const NMUtilsFlags2StrDesc *descs,
+ gsize n_descs,
+ unsigned flags,
+ char *buf,
+ gsize len);
+
+/*****************************************************************************/
+
+#define NM_UTILS_ENUM2STR(v, n) (void) 0; case v: s = ""n""; break; (void) 0
+#define NM_UTILS_ENUM2STR_IGNORE(v) (void) 0; case v: break; (void) 0
+
+#define _NM_UTILS_ENUM2STR_DEFINE(scope, fcn_name, lookup_type, int_fmt, ...) \
+scope const char * \
+fcn_name (lookup_type val, char *buf, gsize len) \
+{ \
+ nm_utils_to_string_buffer_init (&buf, &len); \
+ if (len) { \
+ const char *s = NULL; \
+ switch (val) { \
+ (void) 0, \
+ __VA_ARGS__ \
+ (void) 0; \
+ }; \
+ if (s) \
+ g_strlcpy (buf, s, len); \
+ else \
+ g_snprintf (buf, len, "(%"int_fmt")", val); \
+ } \
+ return buf; \
+}
+
+#define NM_UTILS_ENUM2STR_DEFINE(fcn_name, lookup_type, ...) \
+ _NM_UTILS_ENUM2STR_DEFINE (, fcn_name, lookup_type, "d", __VA_ARGS__)
+#define NM_UTILS_ENUM2STR_DEFINE_STATIC(fcn_name, lookup_type, ...) \
+ _NM_UTILS_ENUM2STR_DEFINE (static, fcn_name, lookup_type, "d", __VA_ARGS__)
+
+/*****************************************************************************/
+
#define _nm_g_slice_free_fcn_define(mem_size) \
static inline void \
_nm_g_slice_free_fcn_##mem_size (gpointer mem_block) \
@@ -299,4 +407,16 @@ char *nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flag
/*****************************************************************************/
+#define NM_UTILS_NS_PER_SECOND ((gint64) 1000000000)
+#define NM_UTILS_NS_PER_MSEC ((gint64) 1000000)
+#define NM_UTILS_NS_TO_MSEC_CEIL(nsec) (((nsec) + (NM_UTILS_NS_PER_MSEC - 1)) / NM_UTILS_NS_PER_MSEC)
+
+/*****************************************************************************/
+
+int nm_utils_fd_wait_for_event (int fd, int event, gint64 timeout_ns);
+ssize_t nm_utils_fd_read_loop (int fd, void *buf, size_t nbytes, bool do_poll);
+int nm_utils_fd_read_loop_exact (int fd, void *buf, size_t nbytes, bool do_poll);
+
+/*****************************************************************************/
+
#endif /* __NM_SHARED_UTILS_H__ */
diff --git a/shared/nm-utils/nm-test-utils.h b/shared/nm-utils/nm-test-utils.h
index f7a87aa..126546e 100644
--- a/shared/nm-utils/nm-test-utils.h
+++ b/shared/nm-utils/nm-test-utils.h
@@ -1697,6 +1697,63 @@ nmtst_assert_setting_verifies (NMSetting *setting)
g_assert (success);
}
+#if defined(__NM_SIMPLE_CONNECTION_H__)
+static inline void
+_nmtst_assert_connection_has_settings (NMConnection *connection, gboolean has_at_least, gboolean
has_at_most, ...)
+{
+ gs_unref_hashtable GHashTable *names = NULL;
+ gs_free NMSetting **settings = NULL;
+ va_list ap;
+ const char *name;
+ guint i, len;
+ gs_unref_ptrarray GPtrArray *names_arr = NULL;
+
+ g_assert (NM_IS_CONNECTION (connection));
+
+ names = g_hash_table_new (g_str_hash, g_str_equal);
+ names_arr = g_ptr_array_new ();
+
+ va_start (ap, has_at_most);
+ while ((name = va_arg (ap, const char *))) {
+ if (!nm_g_hash_table_add (names, (gpointer) name))
+ g_assert_not_reached ();
+ g_ptr_array_add (names_arr, (gpointer) name);
+ }
+ va_end (ap);
+
+ g_ptr_array_add (names_arr, NULL);
+
+ settings = nm_connection_get_settings (connection, &len);
+ for (i = 0; i < len; i++) {
+ if ( !g_hash_table_remove (names, nm_setting_get_name (settings[i]))
+ && has_at_most) {
+ g_error ("nmtst_assert_connection_has_settings(): has setting \"%s\" which is not
expected",
+ nm_setting_get_name (settings[i]));
+ }
+ }
+ if ( g_hash_table_size (names) > 0
+ && has_at_least) {
+ gs_free char *expected_str = g_strjoinv (" ", (char **) names_arr->pdata);
+ gs_free const char **settings_names = NULL;
+ gs_free char *has_str = NULL;
+
+ settings_names = g_new0 (const char *, len + 1);
+ for (i = 0; i < len; i++)
+ settings_names[i] = nm_setting_get_name (settings[i]);
+ has_str = g_strjoinv (" ", (char **) settings_names);
+
+ g_error ("nmtst_assert_connection_has_settings(): the setting lacks %u expected settings
(expected: [%s] vs. has: [%s])",
+ g_hash_table_size (names),
+ expected_str,
+ has_str);
+ }
+}
+#define nmtst_assert_connection_has_settings(connection, ...) _nmtst_assert_connection_has_settings
((connection), TRUE, TRUE, __VA_ARGS__, NULL)
+#define nmtst_assert_connection_has_settings_at_least(connection, ...) _nmtst_assert_connection_has_settings
((connection), TRUE, FALSE, __VA_ARGS__, NULL)
+#define nmtst_assert_connection_has_settings_at_most(connection, ...) _nmtst_assert_connection_has_settings
((connection), FALSE, TRUE, __VA_ARGS__, NULL)
+
+#endif /* __NM_SIMPLE_CONNECTION_H__ */
+
static inline void
nmtst_assert_setting_verify_fails (NMSetting *setting,
GQuark expect_error_domain,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]