From 2aa1fdd2bf71663ee0b56fc309c7d2a4c78a5190 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 27 Oct 2021 20:24:17 +0200 Subject: [PATCH] libnm: add direct property type "bytes" --- src/libnm-core-impl/nm-setting-private.h | 38 ++++++++++++ src/libnm-core-impl/nm-setting.c | 77 ++++++++++++++++++++++++ src/libnm-core-impl/tests/test-setting.c | 6 ++ src/libnm-glib-aux/nm-json-aux.h | 2 + src/libnm-glib-aux/nm-value-type.h | 33 ++++++++-- 5 files changed, 150 insertions(+), 6 deletions(-) diff --git a/src/libnm-core-impl/nm-setting-private.h b/src/libnm-core-impl/nm-setting-private.h index 78f6e136e8..05ea3a70ff 100644 --- a/src/libnm-core-impl/nm-setting-private.h +++ b/src/libnm-core-impl/nm-setting-private.h @@ -293,6 +293,7 @@ extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_int32; extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_uint32; extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_uint64; extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_string; +extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_bytes; extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_enum; extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_flags; extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_mac_address; @@ -707,6 +708,43 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p /*****************************************************************************/ +#define _nm_setting_property_define_direct_bytes(properties_override, \ + obj_properties, \ + prop_name, \ + prop_id, \ + param_flags, \ + private_struct_type, \ + private_struct_field, \ + ... /* extra NMSettInfoProperty fields */) \ + G_STMT_START \ + { \ + GParamSpec *_param_spec; \ + \ + G_STATIC_ASSERT(!NM_FLAGS_ANY((param_flags), \ + ~(NM_SETTING_PARAM_SECRET | NM_SETTING_PARAM_INFERRABLE \ + | NM_SETTING_PARAM_FUZZY_IGNORE))); \ + \ + _param_spec = \ + g_param_spec_boxed("" prop_name "", \ + "", \ + "", \ + G_TYPE_BYTES, \ + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | (param_flags)); \ + \ + (obj_properties)[(prop_id)] = _param_spec; \ + \ + _nm_properties_override_gobj( \ + (properties_override), \ + _param_spec, \ + &nm_sett_info_propert_type_direct_bytes, \ + .direct_offset = \ + NM_STRUCT_OFFSET_ENSURE_TYPE(GBytes *, private_struct_type, private_struct_field), \ + __VA_ARGS__); \ + } \ + G_STMT_END + +/*****************************************************************************/ + #define _nm_setting_property_define_direct_enum(properties_override, \ obj_properties, \ prop_name, \ diff --git a/src/libnm-core-impl/nm-setting.c b/src/libnm-core-impl/nm-setting.c index 2bf98186da..1f6992a72f 100644 --- a/src/libnm-core-impl/nm-setting.c +++ b/src/libnm-core-impl/nm-setting.c @@ -776,6 +776,14 @@ _nm_setting_property_get_property_direct(GObject * object, g_value_set_string(value, *p_val); return; } + case NM_VALUE_TYPE_BYTES: + { + const GBytes *const *p_val = + _nm_setting_get_private(setting, sett_info, property_info->direct_offset); + + g_value_set_boxed(value, *p_val); + return; + } default: goto out_fail; } @@ -887,6 +895,19 @@ _nm_setting_property_set_property_direct(GObject * object, g_value_get_string(value))) return; goto out_notify; + case NM_VALUE_TYPE_BYTES: + { + GBytes **p_val = _nm_setting_get_private(setting, sett_info, property_info->direct_offset); + GBytes * v; + _nm_unused gs_unref_bytes GBytes *old = NULL; + + v = g_value_get_boxed(value); + if (nm_g_bytes_equal0(*p_val, v)) + return; + old = *p_val; + *p_val = v ? g_bytes_ref(v) : NULL; + goto out_notify; + } default: goto out_fail; } @@ -995,6 +1016,11 @@ _init_direct(NMSetting *setting) *((const char *const *) _nm_setting_get_private(setting, sett_info, property_info->direct_offset)))); break; + case NM_VALUE_TYPE_BYTES: + nm_assert(!( + *((const GBytes *const *) + _nm_setting_get_private(setting, sett_info, property_info->direct_offset)))); + break; default: nm_assert_not_reached(); break; @@ -1038,6 +1064,14 @@ _finalize_direct(NMSetting *setting) nm_clear_g_free(p_val); break; } + case NM_VALUE_TYPE_BYTES: + { + GBytes **p_val = + _nm_setting_get_private(setting, sett_info, property_info->direct_offset); + + nm_clear_pointer(p_val, g_bytes_unref); + break; + } default: nm_assert_not_reached(); break; @@ -1136,6 +1170,21 @@ _nm_setting_property_to_dbus_fcn_direct(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_ return g_variant_ref(nm_g_variant_singleton_s_empty()); return g_variant_new_string(val); } + case NM_VALUE_TYPE_BYTES: + { + const GBytes *val; + + /* Bytes have always NULL as default. Setting "including_default" has no defined meaning + * (but it could have). */ + nm_assert(!property_info->to_dbus_including_default); + + val = *((const GBytes *const *) _nm_setting_get_private(setting, + sett_info, + property_info->direct_offset)); + if (!val) + return NULL; + return nm_g_bytes_to_variant_ay(val); + } default: return nm_assert_unreachable_val(NULL); } @@ -1457,6 +1506,23 @@ _nm_setting_property_from_dbus_fcn_direct(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS goto out_notify; } + case NM_VALUE_TYPE_BYTES: + { + gs_unref_bytes GBytes *v = NULL; + GBytes ** p_val; + + if (!g_variant_is_of_type(value, G_VARIANT_TYPE_BYTESTRING)) + goto out_error_wrong_dbus_type; + + v = nm_g_bytes_new_from_variant_ay(value); + + p_val = _nm_setting_get_private(setting, sett_info, property_info->direct_offset); + if (nm_g_bytes_equal0(*p_val, v)) + goto out_unchanged; + + NM_SWAP(p_val, &v); + goto out_notify; + } default: break; } @@ -2361,6 +2427,8 @@ _nm_setting_property_compare_fcn_direct(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_ return *((const guint *) p_a) == *((const guint *) p_b); case NM_VALUE_TYPE_STRING: return nm_streq0(*((const char *const *) p_a), *((const char *const *) p_b)); + case NM_VALUE_TYPE_BYTES: + return nm_g_bytes_equal0(*((const GBytes *const *) p_a), *((const GBytes *const *) p_b)); default: return nm_assert_unreachable_val(TRUE); } @@ -3422,6 +3490,15 @@ const NMSettInfoPropertType nm_sett_info_propert_type_direct_string = .from_dbus_is_full = TRUE, .from_dbus_direct_allow_transform = TRUE); +const NMSettInfoPropertType nm_sett_info_propert_type_direct_bytes = + NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_BYTESTRING, + .direct_type = NM_VALUE_TYPE_BYTES, + .compare_fcn = _nm_setting_property_compare_fcn_direct, + .to_dbus_fcn = _nm_setting_property_to_dbus_fcn_direct, + .from_dbus_fcn = _nm_setting_property_from_dbus_fcn_direct, + .from_dbus_is_full = TRUE, + .from_dbus_direct_allow_transform = TRUE); + const NMSettInfoPropertType nm_sett_info_propert_type_direct_enum = NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_INT32, .direct_type = NM_VALUE_TYPE_ENUM, diff --git a/src/libnm-core-impl/tests/test-setting.c b/src/libnm-core-impl/tests/test-setting.c index 45d72cbdef..4187077172 100644 --- a/src/libnm-core-impl/tests/test-setting.c +++ b/src/libnm-core-impl/tests/test-setting.c @@ -4558,6 +4558,12 @@ test_setting_metadata(void) } g_assert(sip->param_spec); g_assert(sip->param_spec->value_type == G_TYPE_STRING); + } else if (sip->property_type->direct_type == NM_VALUE_TYPE_BYTES) { + g_assert(g_variant_type_equal(sip->property_type->dbus_type, "ay")); + g_assert(sip->property_type->to_dbus_fcn + == _nm_setting_property_to_dbus_fcn_direct); + g_assert(sip->param_spec); + g_assert(sip->param_spec->value_type == G_TYPE_BYTES); } else g_assert_not_reached(); diff --git a/src/libnm-glib-aux/nm-json-aux.h b/src/libnm-glib-aux/nm-json-aux.h index 5ed756ae65..088d67a9c3 100644 --- a/src/libnm-glib-aux/nm-json-aux.h +++ b/src/libnm-glib-aux/nm-json-aux.h @@ -390,6 +390,7 @@ nm_value_type_to_json(NMValueType value_type, GString *gstr, gconstpointer p_fie case NM_VALUE_TYPE_STRING: nm_json_gstr_append_string(gstr, *((const char *const *) p_field)); return; + case NM_VALUE_TYPE_BYTES: case NM_VALUE_TYPE_NONE: case NM_VALUE_TYPE_UNSPEC: break; @@ -426,6 +427,7 @@ nm_value_type_from_json(const NMJsonVt * vt, case NM_VALUE_TYPE_STRING: return (nm_jansson_json_as_string(vt, elem, out_val) > 0); + case NM_VALUE_TYPE_BYTES: case NM_VALUE_TYPE_NONE: case NM_VALUE_TYPE_UNSPEC: break; diff --git a/src/libnm-glib-aux/nm-value-type.h b/src/libnm-glib-aux/nm-value-type.h index 502d9fd7c1..0addeec699 100644 --- a/src/libnm-glib-aux/nm-value-type.h +++ b/src/libnm-glib-aux/nm-value-type.h @@ -26,6 +26,8 @@ typedef enum _nm_packed { NM_VALUE_TYPE_ENUM = 10, NM_VALUE_TYPE_STRING = 11, + + NM_VALUE_TYPE_BYTES = 12, } NMValueType; /*****************************************************************************/ @@ -110,6 +112,8 @@ nm_value_type_cmp(NMValueType value_type, gconstpointer p_a, gconstpointer p_b) return 0; case NM_VALUE_TYPE_STRING: return nm_strcmp0(*((const char *const *) p_a), *((const char *const *) p_b)); + case NM_VALUE_TYPE_BYTES: + return nm_g_bytes_equal0(*((const GBytes *const *) p_a), *((const GBytes *const *) p_b)); case NM_VALUE_TYPE_NONE: case NM_VALUE_TYPE_UNSPEC: break; @@ -154,10 +158,19 @@ nm_value_type_copy(NMValueType value_type, gpointer dst, gconstpointer src) case NM_VALUE_TYPE_STRING: /* self assignment safe! */ if (*((char **) dst) != *((const char *const *) src)) { - g_free(*((char **) dst)); + _nm_unused char *old = *((char **) dst); + *((char **) dst) = g_strdup(*((const char *const *) src)); } return; + case NM_VALUE_TYPE_BYTES: + /* self assignment safe! */ + if (*((GBytes **) dst) != *((const GBytes *const *) src)) { + _nm_unused gs_unref_bytes GBytes *old = *((GBytes **) dst); + + *((GBytes **) dst) = g_bytes_ref(*((GBytes *const *) src)); + } + return; case NM_VALUE_TYPE_NONE: case NM_VALUE_TYPE_UNSPEC: break; @@ -189,7 +202,8 @@ nm_value_type_get_from_variant(NMValueType value_type, return; case NM_VALUE_TYPE_STRING: if (clone) { - g_free(*((char **) dst)); + _nm_unused gs_free char *old = *((char **) dst); + *((char **) dst) = g_variant_dup_string(variant, NULL); } else { /* we don't clone the string, nor free the previous value. */ @@ -197,12 +211,13 @@ nm_value_type_get_from_variant(NMValueType value_type, } return; + case NM_VALUE_TYPE_BYTES: case NM_VALUE_TYPE_INT: case NM_VALUE_TYPE_UINT: case NM_VALUE_TYPE_ENUM: case NM_VALUE_TYPE_FLAGS: /* These types don't have a defined variant type, because it's not - * clear how many bits we would need. */ + * clear how many bits we would need or how to handle the type. */ /* fall-through */ case NM_VALUE_TYPE_NONE: @@ -215,7 +230,8 @@ nm_value_type_get_from_variant(NMValueType value_type, static inline GVariant * nm_value_type_to_variant(NMValueType value_type, gconstpointer src) { - const char *v_string; + const char * v_string; + const GBytes *v_bytes; switch (value_type) { case NM_VALUE_TYPE_BOOL: @@ -231,13 +247,16 @@ nm_value_type_to_variant(NMValueType value_type, gconstpointer src) case NM_VALUE_TYPE_STRING: v_string = *((const char *const *) src); return v_string ? g_variant_new_string(v_string) : NULL; + case NM_VALUE_TYPE_BYTES: + v_bytes = *((const GBytes *const *) src); + return v_bytes ? nm_g_bytes_to_variant_ay(v_bytes) : NULL; case NM_VALUE_TYPE_INT: case NM_VALUE_TYPE_UINT: case NM_VALUE_TYPE_ENUM: case NM_VALUE_TYPE_FLAGS: /* These types don't have a defined variant type, because it's not - * clear how many bits we would need. */ + * clear how many bits we would need or how to handle the type. */ /* fall-through */ case NM_VALUE_TYPE_NONE: @@ -264,13 +283,15 @@ nm_value_type_get_variant_type(NMValueType value_type) return G_VARIANT_TYPE_UINT64; case NM_VALUE_TYPE_STRING: return G_VARIANT_TYPE_STRING; + case NM_VALUE_TYPE_BYTES: + return G_VARIANT_TYPE_BYTESTRING; case NM_VALUE_TYPE_INT: case NM_VALUE_TYPE_UINT: case NM_VALUE_TYPE_ENUM: case NM_VALUE_TYPE_FLAGS: /* These types don't have a defined variant type, because it's not - * clear how many bits we would need. */ + * clear how many bits we would need or how to handle the type. */ /* fall-through */ case NM_VALUE_TYPE_NONE: