diff options
| author | Michael Biebl <biebl@debian.org> | 2018-02-07 02:39:23 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-02-07 02:39:23 +0100 |
| commit | 50f6b47074e01dffb8dc536c0a20961dcf28ae9b (patch) | |
| tree | b4bd771d78ebe38661b8c4ec8b9a8e0eb8261eb5 /libnm-core | |
| parent | afcd268ea7b1149fbfb66bce4eca659b675da0a2 (diff) | |
New upstream version 1.10.4 upstream/1.10.4
Diffstat (limited to 'libnm-core')
| -rw-r--r-- | libnm-core/nm-core-internal.h | 8 | ||||
| -rw-r--r-- | libnm-core/nm-dbus-interface.h | 4 | ||||
| -rw-r--r-- | libnm-core/nm-dbus-types.xml | 10 | ||||
| -rw-r--r-- | libnm-core/nm-json.c | 118 | ||||
| -rw-r--r-- | libnm-core/nm-json.h | 50 | ||||
| -rw-r--r-- | libnm-core/nm-setting-ip4-config.c | 2 | ||||
| -rw-r--r-- | libnm-core/nm-setting-tc-config.h | 3 | ||||
| -rw-r--r-- | libnm-core/nm-setting-team.c | 10 | ||||
| -rw-r--r-- | libnm-core/nm-setting-team.h | 2 | ||||
| -rw-r--r-- | libnm-core/nm-setting-vpn.c | 23 | ||||
| -rw-r--r-- | libnm-core/nm-utils.c | 177 | ||||
| -rw-r--r-- | libnm-core/tests/test-general.c | 99 |
12 files changed, 433 insertions, 73 deletions
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 5a27d438..15e5dc2a 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -241,7 +241,13 @@ GPtrArray *_nm_utils_copy_object_array (const GPtrArray *array); gssize _nm_utils_ptrarray_find_first (gconstpointer *list, gssize len, gconstpointer needle); -gssize _nm_utils_ptrarray_find_binary_search (gconstpointer *list, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data); +gssize _nm_utils_ptrarray_find_binary_search (gconstpointer *list, + gsize len, + gconstpointer needle, + GCompareDataFunc cmpfcn, + gpointer user_data, + gssize *out_idx_first, + gssize *out_idx_last); gssize _nm_utils_array_find_binary_search (gconstpointer list, gsize elem_size, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data); GSList * _nm_utils_strv_to_slist (char **strv, gboolean deep_copy); diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index 98c94154..33e4850c 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -551,6 +551,8 @@ typedef enum { * @NM_DEVICE_STATE_REASON_PARENT_CHANGED: the device's parent changed * @NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED: the device parent's management changed * @NM_DEVICE_STATE_REASON_OVSDB_FAILED: problem communicating with OpenVSwitch database + * @NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE: a duplicate IP address was detected + * @NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED: The selected IP method is not supported * * Device state change reason codes */ @@ -619,6 +621,8 @@ typedef enum { NM_DEVICE_STATE_REASON_PARENT_CHANGED = 61, NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED = 62, NM_DEVICE_STATE_REASON_OVSDB_FAILED = 63, + NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE = 64, + NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED = 65, } NMDeviceStateReason; /** diff --git a/libnm-core/nm-dbus-types.xml b/libnm-core/nm-dbus-types.xml index bc0c023b..b8c5d84f 100644 --- a/libnm-core/nm-dbus-types.xml +++ b/libnm-core/nm-dbus-types.xml @@ -1122,6 +1122,16 @@ <entry role="enum_member_value"><para>= <literal>63</literal></para><para></para></entry> <entry role="enum_member_description"><para>problem communicating with OpenVSwitch database</para><para></para></entry> </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>64</literal></para><para></para></entry> + <entry role="enum_member_description"><para>a duplicate IP address was detected</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>65</literal></para><para></para></entry> + <entry role="enum_member_description"><para>The selected IP method is not supported</para><para></para></entry> + </row> </tbody> </tgroup> </informaltable> diff --git a/libnm-core/nm-json.c b/libnm-core/nm-json.c new file mode 100644 index 00000000..f9042b1f --- /dev/null +++ b/libnm-core/nm-json.c @@ -0,0 +1,118 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2017, 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#define NM_JANSSON_C +#include "nm-json.h" + +#include <dlfcn.h> + +void *_nm_jansson_json_object_iter_value; +void *_nm_jansson_json_object_key_to_iter; +void *_nm_jansson_json_integer; +void *_nm_jansson_json_object_del; +void *_nm_jansson_json_array_get; +void *_nm_jansson_json_array_size; +void *_nm_jansson_json_array_append_new; +void *_nm_jansson_json_string; +void *_nm_jansson_json_object_iter_next; +void *_nm_jansson_json_loads; +void *_nm_jansson_json_dumps; +void *_nm_jansson_json_object_iter_key; +void *_nm_jansson_json_object; +void *_nm_jansson_json_object_get; +void *_nm_jansson_json_array; +void *_nm_jansson_json_false; +void *_nm_jansson_json_delete; +void *_nm_jansson_json_true; +void *_nm_jansson_json_object_size; +void *_nm_jansson_json_object_set_new; +void *_nm_jansson_json_object_iter; +void *_nm_jansson_json_object_iter_at; +void *_nm_jansson_json_integer_value; +void *_nm_jansson_json_string_value; + +#define TRY_BIND_SYMBOL(symbol) \ + G_STMT_START { \ + void *sym = dlsym (handle, #symbol); \ + if (_nm_jansson_ ## symbol && sym != _nm_jansson_ ## symbol) \ + return FALSE; \ + _nm_jansson_ ## symbol = sym; \ + } G_STMT_END + +static gboolean +bind_symbols (void *handle) +{ + TRY_BIND_SYMBOL (json_object_iter_value); + TRY_BIND_SYMBOL (json_object_key_to_iter); + TRY_BIND_SYMBOL (json_integer); + TRY_BIND_SYMBOL (json_object_del); + TRY_BIND_SYMBOL (json_array_get); + TRY_BIND_SYMBOL (json_array_size); + TRY_BIND_SYMBOL (json_array_append_new); + TRY_BIND_SYMBOL (json_string); + TRY_BIND_SYMBOL (json_object_iter_next); + TRY_BIND_SYMBOL (json_loads); + TRY_BIND_SYMBOL (json_dumps); + TRY_BIND_SYMBOL (json_object_iter_key); + TRY_BIND_SYMBOL (json_object); + TRY_BIND_SYMBOL (json_object_get); + TRY_BIND_SYMBOL (json_array); + TRY_BIND_SYMBOL (json_false); + TRY_BIND_SYMBOL (json_delete); + TRY_BIND_SYMBOL (json_true); + TRY_BIND_SYMBOL (json_object_size); + TRY_BIND_SYMBOL (json_object_set_new); + TRY_BIND_SYMBOL (json_object_iter); + TRY_BIND_SYMBOL (json_object_iter_at); + TRY_BIND_SYMBOL (json_integer_value); + TRY_BIND_SYMBOL (json_string_value); + + return TRUE; +} + +gboolean +nm_jansson_load (void) +{ + static enum { + UNKNOWN, + AVAILABLE, + MISSING, + } state = UNKNOWN; + void *handle; + + if (G_LIKELY (state != UNKNOWN)) + goto out; + + /* First just resolve the symbols to see if there's a conflict already. */ + if (!bind_symbols (RTLD_DEFAULT)) + goto out; + + handle = dlopen (JANSSON_SONAME, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND); + if (!handle) + goto out; + + /* Now do the actual binding. */ + if (!bind_symbols (handle)) + goto out; + + state = AVAILABLE; +out: + return state == AVAILABLE; +} diff --git a/libnm-core/nm-json.h b/libnm-core/nm-json.h new file mode 100644 index 00000000..513b8d36 --- /dev/null +++ b/libnm-core/nm-json.h @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2017, 2018 Red Hat, Inc. + */ +#ifndef __NM_JSON_H__ +#define __NM_JSON_H__ + +gboolean nm_jansson_load (void); + +#ifndef NM_JANSSON_C +#define json_object_iter_value (*_nm_jansson_json_object_iter_value) +#define json_object_key_to_iter (*_nm_jansson_json_object_key_to_iter) +#define json_integer (*_nm_jansson_json_integer) +#define json_object_del (*_nm_jansson_json_object_del) +#define json_array_get (*_nm_jansson_json_array_get) +#define json_array_size (*_nm_jansson_json_array_size) +#define json_array_append_new (*_nm_jansson_json_array_append_new) +#define json_string (*_nm_jansson_json_string) +#define json_object_iter_next (*_nm_jansson_json_object_iter_next) +#define json_loads (*_nm_jansson_json_loads) +#define json_dumps (*_nm_jansson_json_dumps) +#define json_object_iter_key (*_nm_jansson_json_object_iter_key) +#define json_object (*_nm_jansson_json_object) +#define json_object_get (*_nm_jansson_json_object_get) +#define json_array (*_nm_jansson_json_array) +#define json_false (*_nm_jansson_json_false) +#define json_delete (*_nm_jansson_json_delete) +#define json_true (*_nm_jansson_json_true) +#define json_object_size (*_nm_jansson_json_object_size) +#define json_object_set_new (*_nm_jansson_json_object_set_new) +#define json_object_iter (*_nm_jansson_json_object_iter) +#define json_object_iter_at (*_nm_jansson_json_object_iter_at) +#define json_integer_value (*_nm_jansson_json_integer_value) +#define json_string_value (*_nm_jansson_json_string_value) +#endif + +#endif /* __NM_JSON_H__ */ diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c index 26e7f505..d9c0cbb1 100644 --- a/libnm-core/nm-setting-ip4-config.c +++ b/libnm-core/nm-setting-ip4-config.c @@ -191,7 +191,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (priv->dhcp_client_id && !strlen (priv->dhcp_client_id)) { + if (priv->dhcp_client_id && !priv->dhcp_client_id[0]) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, diff --git a/libnm-core/nm-setting-tc-config.h b/libnm-core/nm-setting-tc-config.h index 736d5ad1..8117d5ea 100644 --- a/libnm-core/nm-setting-tc-config.h +++ b/libnm-core/nm-setting-tc-config.h @@ -28,7 +28,6 @@ G_BEGIN_DECLS -NM_AVAILABLE_IN_1_10_2 typedef struct NMTCQdisc NMTCQdisc; NM_AVAILABLE_IN_1_10_2 @@ -61,7 +60,6 @@ void nm_tc_qdisc_set_handle (NMTCQdisc *qdisc, NM_AVAILABLE_IN_1_10_2 guint32 nm_tc_qdisc_get_parent (NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_10_2 typedef struct NMTCAction NMTCAction; NM_AVAILABLE_IN_1_10_2 @@ -96,7 +94,6 @@ void nm_tc_action_set_attribute (NMTCAction *action, const char *name, GVariant *value); -NM_AVAILABLE_IN_1_10_2 typedef struct NMTCTfilter NMTCTfilter; NM_AVAILABLE_IN_1_10_2 diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c index d3688278..60bdf5f6 100644 --- a/libnm-core/nm-setting-team.c +++ b/libnm-core/nm-setting-team.c @@ -249,7 +249,7 @@ nm_team_link_watcher_new_arp_ping (gint init_wait, return NULL; } - if (strpbrk (target_host, " \\/\t=\"\'")) { + if (strpbrk (source_host, " \\/\t=\"\'")) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, _("source-host '%s' contains invalid characters"), source_host); return NULL; @@ -1485,8 +1485,10 @@ set_property (GObject *object, guint prop_id, break; } - if (align_config) + if (align_config) { _nm_utils_json_append_gvalue (&priv->config, _prop_to_keys[prop_id], align_value); + _align_team_properties (setting); + } } static void @@ -1654,6 +1656,10 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * Corresponds to the teamd runner.name. * Permitted values are: "roundrobin", "broadcast", "activebackup", * "loadbalance", "lacp". + * When setting the runner, all the properties specific to the runner + * will be reset to the default value; all the properties specific to + * other runners will be set to an empty value (or if not possible to + * a default value). * * Since: 1.10.2 **/ diff --git a/libnm-core/nm-setting-team.h b/libnm-core/nm-setting-team.h index 45207836..d423901f 100644 --- a/libnm-core/nm-setting-team.h +++ b/libnm-core/nm-setting-team.h @@ -150,7 +150,7 @@ NMTeamLinkWatcherArpPingFlags nm_team_link_watcher_get_flags (NMTeamLinkWatcher #define NM_SETTING_TEAM_RUNNER_DEFAULT NM_SETTING_TEAM_RUNNER_ROUNDROBIN #define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_DEFAULT NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL #define NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT 50 -#define NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT 255 +#define NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT 65535 #define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_DEFAULT NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c index 6b42e0c7..34607252 100644 --- a/libnm-core/nm-setting-vpn.c +++ b/libnm-core/nm-setting-vpn.c @@ -614,17 +614,15 @@ need_secrets (NMSetting *setting) } static gboolean -compare_one_secret (NMSettingVpn *a, - NMSettingVpn *b, - NMSettingCompareFlags flags) +_compare_secrets (NMSettingVpn *a, + NMSettingVpn *b, + NMSettingCompareFlags flags) { - GHashTable *a_secrets, *b_secrets; + GHashTable *a_secrets; GHashTableIter iter; const char *key, *val; a_secrets = NM_SETTING_VPN_GET_PRIVATE (a)->secrets; - b_secrets = NM_SETTING_VPN_GET_PRIVATE (b)->secrets; - g_hash_table_iter_init (&iter, a_secrets); while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &val)) { NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE; @@ -654,6 +652,19 @@ compare_one_secret (NMSettingVpn *a, } static gboolean +compare_one_secret (NMSettingVpn *a, + NMSettingVpn *b, + NMSettingCompareFlags flags) +{ + if (!_compare_secrets (a, b, flags)) + return FALSE; + if (!_compare_secrets (b, a, flags)) + return FALSE; + + return TRUE; +} + +static gboolean compare_property (NMSetting *setting, NMSetting *other, const GParamSpec *prop_spec, diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 6cc92ec8..ebbbfd3a 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -36,6 +36,7 @@ #include <linux/pkt_sched.h> #if WITH_JANSSON +#include "nm-json.h" #include <jansson.h> #endif @@ -650,36 +651,82 @@ _nm_utils_ptrarray_find_first (gconstpointer *list, gssize len, gconstpointer ne } gssize -_nm_utils_ptrarray_find_binary_search (gconstpointer *list, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data) -{ - gssize imin, imax, imid; +_nm_utils_ptrarray_find_binary_search (gconstpointer *list, + gsize len, + gconstpointer needle, + GCompareDataFunc cmpfcn, + gpointer user_data, + gssize *out_idx_first, + gssize *out_idx_last) +{ + gssize imin, imax, imid, i2min, i2max, i2mid; int cmp; g_return_val_if_fail (list || !len, ~((gssize) 0)); g_return_val_if_fail (cmpfcn, ~((gssize) 0)); imin = 0; - if (len == 0) - return ~imin; - - imax = len - 1; - - while (imin <= imax) { - imid = imin + (imax - imin) / 2; - - cmp = cmpfcn (list[imid], needle, user_data); - if (cmp == 0) - return imid; + if (len > 0) { + imax = len - 1; + + while (imin <= imax) { + imid = imin + (imax - imin) / 2; + + cmp = cmpfcn (list[imid], needle, user_data); + if (cmp == 0) { + /* we found a matching entry at index imid. + * + * Does the caller request the first/last index as well (in case that + * there are multiple entries which compare equal). */ + + if (out_idx_first) { + i2min = imin; + i2max = imid + 1; + while (i2min <= i2max) { + i2mid = i2min + (i2max - i2min) / 2; + + cmp = cmpfcn (list[i2mid], needle, user_data); + if (cmp == 0) + i2max = i2mid -1; + else { + nm_assert (cmp < 0); + i2min = i2mid + 1; + } + } + *out_idx_first = i2min; + } + if (out_idx_last) { + i2min = imid + 1; + i2max = imax; + while (i2min <= i2max) { + i2mid = i2min + (i2max - i2min) / 2; + + cmp = cmpfcn (list[i2mid], needle, user_data); + if (cmp == 0) + i2min = i2mid + 1; + else { + nm_assert (cmp > 0); + i2max = i2mid - 1; + } + } + *out_idx_last = i2min - 1; + } + return imid; + } - if (cmp < 0) - imin = imid + 1; - else - imax = imid - 1; + if (cmp < 0) + imin = imid + 1; + else + imax = imid - 1; + } } /* return the inverse of @imin. This is a negative number, but * also is ~imin the position where the value should be inserted. */ - return ~imin; + imin = ~imin; + NM_SET_OUT (out_idx_first, imin); + NM_SET_OUT (out_idx_last, imin); + return imin; } gssize @@ -4845,6 +4892,41 @@ const char **nm_utils_enum_get_values (GType type, gint from, gint to) /*****************************************************************************/ +static gboolean +_nm_utils_is_json_object_no_validation (const char *str, GError **error) +{ + if (str) { + /* libjansson also requires only utf-8 encoding. */ + if (!g_utf8_validate (str, -1, NULL)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("not valid utf-8")); + return FALSE; + } + while (g_ascii_isspace (str[0])) + str++; + } + + /* do some very basic validation to see if this might be a JSON object. */ + if (str[0] == '{') { + gsize l; + + l = strlen (str) - 1; + while (l > 0 && g_ascii_isspace (str[l])) + l--; + + if (str[l] == '}') + return TRUE; + } + + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a JSON object")); + return FALSE; +} + #if WITH_JANSSON /* Added in Jansson v2.3 (released Jan 27 2012) */ @@ -5151,9 +5233,9 @@ _json_team_normalize_defaults (json_t *json, gboolean reset) _json_delete_object_on_string_match (json, "runner", "hwaddr_policy", NULL, NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_DEFAULT); } else if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_LACP)) { - runner_tx_balancer_interval = 50; + runner_tx_balancer_interval = NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT; runner_active = TRUE; - runner_sys_prio = 255; + runner_sys_prio = NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT; runner_min_ports = 0; _json_delete_object_on_string_match (json, "runner", "agg_select_policy", NULL, NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_DEFAULT); @@ -5185,13 +5267,16 @@ _nm_utils_team_link_watcher_from_json (json_t *json_element) g_return_val_if_fail (json_element, NULL); json_object_foreach (json_element, j_key, j_val) { - if (nm_streq (j_key, "name")) + if (nm_streq (j_key, "name")) { + g_free (name); name = strdup (json_string_value (j_val)); - else if (nm_streq (j_key, "target_host")) + } else if (nm_streq (j_key, "target_host")) { + g_free (target_host); target_host = strdup (json_string_value (j_val)); - else if (nm_streq (j_key, "source_host")) + } else if (nm_streq (j_key, "source_host")) { + g_free (source_host); source_host = strdup (json_string_value (j_val)); - else if (NM_IN_STRSET (j_key, "delay_up", "init_wait")) + } else if (NM_IN_STRSET (j_key, "delay_up", "init_wait")) val1 = json_integer_value (j_val); else if (NM_IN_STRSET (j_key, "delay_down", "interval")) val2 = json_integer_value (j_val); @@ -5314,6 +5399,9 @@ nm_utils_is_json_object (const char *str, GError **error) return FALSE; } + if (!nm_jansson_load ()) + return _nm_utils_is_json_object_no_validation (str, error); + json = json_loads (str, JSON_REJECT_DUPLICATES, &jerror); if (!json) { g_set_error (error, @@ -5364,6 +5452,8 @@ _nm_utils_team_config_equal (const char *conf1, if (nm_streq0 (conf1, conf2)) return TRUE; + else if (!nm_jansson_load ()) + return FALSE; /* A NULL configuration is equivalent to default value '{}' */ json1 = json_loads (conf1 ?: "{}", JSON_REJECT_DUPLICATES, &jerror); @@ -5421,6 +5511,9 @@ _nm_utils_team_config_get (const char *conf, if (!key) return NULL; + if (!nm_jansson_load ()) + return NULL; + json = json_loads (conf ?: "{}", JSON_REJECT_DUPLICATES, &jerror); /* Invalid json in conf */ @@ -5528,6 +5621,9 @@ _nm_utils_team_config_set (char **conf, g_return_val_if_fail (key, FALSE); + if (!nm_jansson_load ()) + return FALSE; + json = json_loads (*conf?: "{}", JSON_REJECT_DUPLICATES, &jerror); if (!json) return FALSE; @@ -5645,19 +5741,6 @@ nm_utils_is_json_object (const char *str, GError **error) { g_return_val_if_fail (!error || !*error, FALSE); - if (str) { - /* libjansson also requires only utf-8 encoding. */ - if (!g_utf8_validate (str, -1, NULL)) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("not valid utf-8")); - return FALSE; - } - while (g_ascii_isspace (str[0])) - str++; - } - if (!str || !str[0]) { g_set_error_literal (error, NM_CONNECTION_ERROR, @@ -5666,23 +5749,7 @@ nm_utils_is_json_object (const char *str, GError **error) return FALSE; } - /* do some very basic validation to see if this might be a JSON object. */ - if (str[0] == '{') { - gsize l; - - l = strlen (str) - 1; - while (l > 0 && g_ascii_isspace (str[l])) - l--; - - if (str[l] == '}') - return TRUE; - } - - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("is not a JSON object")); - return FALSE; + return _nm_utils_is_json_object_no_validation (str, error); } gboolean diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index d743fd22..520ed581 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -6139,7 +6139,7 @@ static void _test_find_binary_search_do (const int *array, gsize len) { gsize i; - gssize idx; + gssize idx, idx_first, idx_last; gs_free gconstpointer *parray = g_new (gconstpointer, len); const int NEEDLE = 0; gconstpointer pneedle = GINT_TO_POINTER (NEEDLE); @@ -6150,10 +6150,10 @@ _test_find_binary_search_do (const int *array, gsize len) expected_result = _nm_utils_ptrarray_find_first (parray, len, pneedle); - idx = _nm_utils_ptrarray_find_binary_search (parray, len, pneedle, _test_find_binary_search_cmp, NULL); - if (expected_result >= 0) + idx = _nm_utils_ptrarray_find_binary_search (parray, len, pneedle, _test_find_binary_search_cmp, NULL, &idx_first, &idx_last); + if (expected_result >= 0) { g_assert_cmpint (expected_result, ==, idx); - else { + } else { gssize idx2 = ~idx; g_assert_cmpint (idx, <, 0); @@ -6162,6 +6162,8 @@ _test_find_binary_search_do (const int *array, gsize len) g_assert (idx2 - 1 < 0 || _test_find_binary_search_cmp (parray[idx2 - 1], pneedle, NULL) < 0); g_assert (idx2 >= len || _test_find_binary_search_cmp (parray[idx2], pneedle, NULL) > 0); } + g_assert_cmpint (idx, ==, idx_first); + g_assert_cmpint (idx, ==, idx_last); for (i = 0; i < len; i++) { int cmp; @@ -6263,6 +6265,94 @@ test_nm_utils_ptrarray_find_binary_search (void) } /*****************************************************************************/ + +#define BIN_SEARCH_W_DUPS_LEN 100 +#define BIN_SEARCH_W_DUPS_JITTER 10 + +static int +_test_bin_search2_cmp (gconstpointer pa, + gconstpointer pb, + gpointer user_data) +{ + int a = GPOINTER_TO_INT (pa); + int b = GPOINTER_TO_INT (pb); + + g_assert (a >= 0 && a <= BIN_SEARCH_W_DUPS_LEN + BIN_SEARCH_W_DUPS_JITTER); + g_assert (b >= 0 && b <= BIN_SEARCH_W_DUPS_LEN + BIN_SEARCH_W_DUPS_JITTER); + NM_CMP_DIRECT (a, b); + return 0; +} + +static int +_test_bin_search2_cmp_p (gconstpointer pa, + gconstpointer pb, + gpointer user_data) +{ + return _test_bin_search2_cmp (*((gpointer *) pa), *((gpointer *) pb), NULL); +} + +static void +test_nm_utils_ptrarray_find_binary_search_with_duplicates (void) +{ + gssize idx, idx2, idx_first2, idx_first, idx_last; + int i_test, i_len, i; + gssize j; + gconstpointer arr[BIN_SEARCH_W_DUPS_LEN]; + const int N_TEST = 10; + + for (i_test = 0; i_test < N_TEST; i_test++) { + for (i_len = 0; i_len < BIN_SEARCH_W_DUPS_LEN; i_len++) { + + /* fill with random numbers... surely there are some duplicates + * there... or maybe even there are none... */ + for (i = 0; i < i_len; i++) + arr[i] = GINT_TO_POINTER (nmtst_get_rand_int () % (i_len + BIN_SEARCH_W_DUPS_JITTER)); + g_qsort_with_data (arr, + i_len, + sizeof (gpointer), + _test_bin_search2_cmp_p, + NULL); + for (i = 0; i < i_len + BIN_SEARCH_W_DUPS_JITTER; i++) { + gconstpointer p = GINT_TO_POINTER (i); + + idx = _nm_utils_ptrarray_find_binary_search (arr, i_len, p, _test_bin_search2_cmp, NULL, &idx_first, &idx_last); + + idx_first2 = _nm_utils_ptrarray_find_first (arr, i_len, p); + + idx2 = _nm_utils_array_find_binary_search (arr, sizeof (gpointer), i_len, &p, _test_bin_search2_cmp_p, NULL); + g_assert_cmpint (idx, ==, idx2); + + if (idx_first2 < 0) { + g_assert_cmpint (idx, <, 0); + g_assert_cmpint (idx, ==, idx_first); + g_assert_cmpint (idx, ==, idx_last); + idx = ~idx; + g_assert_cmpint (idx, >=, 0); + g_assert_cmpint (idx, <=, i_len); + if (i_len == 0) + g_assert_cmpint (idx, ==, 0); + else { + g_assert (idx == i_len || GPOINTER_TO_INT (arr[idx]) > i); + g_assert (idx == 0 || GPOINTER_TO_INT (arr[idx - 1]) < i); + } + } else { + g_assert_cmpint (idx_first, ==, idx_first2); + g_assert_cmpint (idx_first, >=, 0); + g_assert_cmpint (idx_last, <, i_len); + g_assert_cmpint (idx_first, <=, idx_last); + g_assert_cmpint (idx, >=, idx_first); + g_assert_cmpint (idx, <=, idx_last); + for (j = idx_first; j < idx_last; j++) + g_assert (GPOINTER_TO_INT (arr[j]) == i); + g_assert (idx_first == 0 || GPOINTER_TO_INT (arr[idx_first - 1]) < i); + g_assert (idx_last == i_len - 1 || GPOINTER_TO_INT (arr[idx_last + 1]) > i); + } + } + } + } +} + +/*****************************************************************************/ static void test_nm_utils_enum_from_str_do (GType type, const char *str, gboolean exp_result, int exp_flags, @@ -6952,6 +7042,7 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/_glib_compat_g_ptr_array_insert", test_g_ptr_array_insert); g_test_add_func ("/core/general/_glib_compat_g_hash_table_get_keys_as_array", test_g_hash_table_get_keys_as_array); g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search); + g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search_with_duplicates", test_nm_utils_ptrarray_find_binary_search_with_duplicates); g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey); g_test_add_func ("/core/general/nm_ptrarray_len", test_nm_ptrarray_len); |