[network-manager-openvpn/th/cleanup: 2/11] shared: re-import shared files



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]