diff --git a/0001-gdbus-Avoid-printing-null-strings.patch b/0001-gdbus-Avoid-printing-null-strings.patch deleted file mode 100644 index 8d7b19a0cbc9f86a4fd36d087ec88dda693064bd..0000000000000000000000000000000000000000 --- a/0001-gdbus-Avoid-printing-null-strings.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 566e1d61a500267c7849ad0b2552feec9c9a29a6 Mon Sep 17 00:00:00 2001 -From: Ernestas Kulik -Date: Tue, 29 Jan 2019 09:50:46 +0100 -Subject: [PATCH] gdbus: Avoid printing null strings -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This mostly affects the 2.56 branch, but, given that GCC 9 is being -stricter about passing null string pointers to printf-like functions, it -might make sense to proactively fix such calls. - -gdbusauth.c: In function '_g_dbus_auth_run_server': -gdbusauth.c:1302:11: error: '%s' directive argument is null -[-Werror=format-overflow=] - 1302 | debug_print ("SERVER: WaitingForBegin, read '%s'", - line); - | - -gdbusmessage.c: In function ‘g_dbus_message_to_blob’: -gdbusmessage.c:2730:30: error: ‘%s’ directive argument is null [-Werror=format-overflow=] - 2730 | tupled_signature_str = g_strdup_printf ("(%s)", signature_str); - | ---- - gio/gdbusauth.c | 2 +- - gio/gdbusmessage.c | 5 ++--- - 2 files changed, 3 insertions(+), 4 deletions(-) - -diff --git a/gio/gdbusauth.c b/gio/gdbusauth.c -index 1f8ea80..752ec23 100644 ---- a/gio/gdbusauth.c -+++ b/gio/gdbusauth.c -@@ -1272,9 +1272,9 @@ _g_dbus_auth_run_server (GDBusAuth *auth, - &line_length, - cancellable, - error); -- debug_print ("SERVER: WaitingForBegin, read '%s'", line); - if (line == NULL) - goto out; -+ debug_print ("SERVER: WaitingForBegin, read '%s'", line); - if (g_strcmp0 (line, "BEGIN") == 0) - { - /* YAY, done! */ -diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c -index 3221b92..3a1a1f9 100644 ---- a/gio/gdbusmessage.c -+++ b/gio/gdbusmessage.c -@@ -2731,7 +2731,6 @@ g_dbus_message_to_blob (GDBusMessage *message, - if (message->body != NULL) - { - gchar *tupled_signature_str; -- tupled_signature_str = g_strdup_printf ("(%s)", signature_str); - if (signature == NULL) - { - g_set_error (error, -@@ -2739,10 +2738,10 @@ g_dbus_message_to_blob (GDBusMessage *message, - G_IO_ERROR_INVALID_ARGUMENT, - _("Message body has signature “%s” but there is no signature header"), - signature_str); -- g_free (tupled_signature_str); - goto out; - } -- else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0) -+ tupled_signature_str = g_strdup_printf ("(%s)", signature_str); -+ if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0) - { - g_set_error (error, - G_IO_ERROR, --- -1.8.3.1 - diff --git a/105.patch b/105.patch deleted file mode 100644 index fa4572e04c699c3c3a7cb348fbe0ee1db26f6213..0000000000000000000000000000000000000000 --- a/105.patch +++ /dev/null @@ -1,658 +0,0 @@ -From 5634fd61f17d28dfc05cd47cfbd2bd2f21e6d2b1 Mon Sep 17 00:00:00 2001 -From: Allison Lortie -Date: Wed, 2 Aug 2017 11:06:03 +0100 -Subject: [PATCH 1/4] gsettings: cleanup default value lookup - -There are a couple of different ways (and soon one more) to access the -default value of a key. Clean up the various places that access this to -avoid duplication. - -https://bugzilla.gnome.org/show_bug.cgi?id=746592 ---- - gio/gsettings.c | 20 ++++---------------- - 1 file changed, 4 insertions(+), 16 deletions(-) - -diff --git a/gio/gsettings.c b/gio/gsettings.c -index 10d394d69..5e5816d57 100644 ---- a/gio/gsettings.c -+++ b/gio/gsettings.c -@@ -1204,10 +1204,7 @@ g_settings_get_value (GSettings *settings, - value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE); - - if (value == NULL) -- value = g_settings_schema_key_get_translated_default (&skey); -- -- if (value == NULL) -- value = g_variant_ref (skey.default_value); -+ value = g_settings_schema_key_get_default_value (&skey); - - g_settings_schema_key_clear (&skey); - -@@ -1304,10 +1301,7 @@ g_settings_get_default_value (GSettings *settings, - value = g_settings_read_from_backend (settings, &skey, FALSE, TRUE); - - if (value == NULL) -- value = g_settings_schema_key_get_translated_default (&skey); -- -- if (value == NULL) -- value = g_variant_ref (skey.default_value); -+ value = g_settings_schema_key_get_default_value (&skey); - - g_settings_schema_key_clear (&skey); - -@@ -1360,10 +1354,7 @@ g_settings_get_enum (GSettings *settings, - value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE); - - if (value == NULL) -- value = g_settings_schema_key_get_translated_default (&skey); -- -- if (value == NULL) -- value = g_variant_ref (skey.default_value); -+ value = g_settings_schema_key_get_default_value (&skey); - - result = g_settings_schema_key_to_enum (&skey, value); - g_settings_schema_key_clear (&skey); -@@ -1473,10 +1464,7 @@ g_settings_get_flags (GSettings *settings, - value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE); - - if (value == NULL) -- value = g_settings_schema_key_get_translated_default (&skey); -- -- if (value == NULL) -- value = g_variant_ref (skey.default_value); -+ value = g_settings_schema_key_get_default_value (&skey); - - result = g_settings_schema_key_to_flags (&skey, value); - g_settings_schema_key_clear (&skey); --- -2.21.0 - - -From 89c6e8f4a0bcda4b58dbaea713e62be01cfc2087 Mon Sep 17 00:00:00 2001 -From: Allison Lortie -Date: Wed, 2 Aug 2017 11:08:17 +0100 -Subject: [PATCH 2/4] gsettingsschema: Allow per-desktop overrides -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Recognise a new 'd' option in schema keys which gives a dictionary of -per-desktop default values. This dictionary is searched for the items -found in XDG_CURRENT_DESKTOP, in the order. If nothing matches (or if -the option is missing) then the default value is used as before. - -This feature was requested by Alberts Muktupāvels and this patch is -based on an approach devised by them. - -https://bugzilla.gnome.org/show_bug.cgi?id=746592 ---- - gio/gsettings.c | 21 +++++++++++++++++ - gio/gsettingsschema-internal.h | 2 ++ - gio/gsettingsschema.c | 41 ++++++++++++++++++++++++++++++++++ - 3 files changed, 64 insertions(+) - -diff --git a/gio/gsettings.c b/gio/gsettings.c -index 5e5816d57..f1130c095 100644 ---- a/gio/gsettings.c -+++ b/gio/gsettings.c -@@ -1739,6 +1739,13 @@ g_settings_get_mapped (GSettings *settings, - if (okay) goto okay; - } - -+ if ((value = g_settings_schema_key_get_per_desktop_default (&skey))) -+ { -+ okay = mapping (value, &result, user_data); -+ g_variant_unref (value); -+ if (okay) goto okay; -+ } -+ - if (mapping (skey.default_value, &result, user_data)) - goto okay; - -@@ -2647,6 +2654,20 @@ g_settings_binding_key_changed (GSettings *settings, - } - } - -+ if (variant == NULL) -+ { -+ variant = g_settings_schema_key_get_per_desktop_default (&binding->key); -+ if (variant && -+ !binding->get_mapping (&value, variant, binding->user_data)) -+ { -+ g_error ("Per-desktop default value for key '%s' in schema '%s' " -+ "was rejected by the binding mapping function.", -+ binding->key.name, g_settings_schema_get_id (binding->key.schema)); -+ g_variant_unref (variant); -+ variant = NULL; -+ } -+ } -+ - if (variant == NULL) - { - variant = g_variant_ref (binding->key.default_value); -diff --git a/gio/gsettingsschema-internal.h b/gio/gsettingsschema-internal.h -index f54de3b34..5f996b4bc 100644 ---- a/gio/gsettingsschema-internal.h -+++ b/gio/gsettingsschema-internal.h -@@ -37,6 +37,7 @@ struct _GSettingsSchemaKey - const GVariantType *type; - GVariant *minimum, *maximum; - GVariant *default_value; -+ GVariant *desktop_overrides; - - gint ref_count; - }; -@@ -58,6 +59,7 @@ gboolean g_settings_schema_key_type_check (GSettin - GVariant * g_settings_schema_key_range_fixup (GSettingsSchemaKey *key, - GVariant *value); - GVariant * g_settings_schema_key_get_translated_default (GSettingsSchemaKey *key); -+GVariant * g_settings_schema_key_get_per_desktop_default (GSettingsSchemaKey *key); - - gint g_settings_schema_key_to_enum (GSettingsSchemaKey *key, - GVariant *value); -diff --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c -index f1274a369..17b7e3b01 100644 ---- a/gio/gsettingsschema.c -+++ b/gio/gsettingsschema.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - /** - * SECTION:gsettingsschema -@@ -1283,6 +1284,11 @@ g_settings_schema_key_init (GSettingsSchemaKey *key, - endian_fixup (&key->maximum); - break; - -+ case 'd': -+ g_variant_get (data, "@a{sv}", &key->desktop_overrides); -+ endian_fixup (&key->desktop_overrides); -+ break; -+ - default: - g_warning ("unknown schema extension '%c'", code); - break; -@@ -1303,6 +1309,9 @@ g_settings_schema_key_clear (GSettingsSchemaKey *key) - if (key->maximum) - g_variant_unref (key->maximum); - -+ if (key->desktop_overrides) -+ g_variant_unref (key->desktop_overrides); -+ - g_variant_unref (key->default_value); - - g_settings_schema_unref (key->schema); -@@ -1410,6 +1419,35 @@ g_settings_schema_key_get_translated_default (GSettingsSchemaKey *key) - return value; - } - -+GVariant * -+g_settings_schema_key_get_per_desktop_default (GSettingsSchemaKey *key) -+{ -+ static const gchar * const *current_desktops; -+ GVariant *value = NULL; -+ gint i; -+ -+ if (!key->desktop_overrides) -+ return NULL; -+ -+ if (g_once_init_enter (¤t_desktops)) -+ { -+ const gchar *xdg_current_desktop = g_getenv ("XDG_CURRENT_DESKTOP"); -+ gchar **tmp; -+ -+ if (xdg_current_desktop != NULL && xdg_current_desktop[0] != '\0') -+ tmp = g_strsplit (xdg_current_desktop, G_SEARCHPATH_SEPARATOR_S, -1); -+ else -+ tmp = g_new0 (gchar *, 0 + 1); -+ -+ g_once_init_leave (¤t_desktops, (const gchar **) tmp); -+ } -+ -+ for (i = 0; value == NULL && current_desktops[i] != NULL; i++) -+ value = g_variant_lookup_value (key->desktop_overrides, current_desktops[i], NULL); -+ -+ return value; -+} -+ - gint - g_settings_schema_key_to_enum (GSettingsSchemaKey *key, - GVariant *value) -@@ -1698,6 +1736,9 @@ g_settings_schema_key_get_default_value (GSettingsSchemaKey *key) - - value = g_settings_schema_key_get_translated_default (key); - -+ if (!value) -+ value = g_settings_schema_key_get_per_desktop_default (key); -+ - if (!value) - value = g_variant_ref (key->default_value); - --- -2.21.0 - - -From 3710e830de015829c086c69181a8703645d577ec Mon Sep 17 00:00:00 2001 -From: Allison Lortie -Date: Wed, 2 Aug 2017 11:10:18 +0100 -Subject: [PATCH 3/4] glib-compile-schemas: Handle per-desktop overrides - -Add a new syntax to override files: if the group name has a ':' in it, -it indicates that we want to override the default values of keys for -only one desktop. For example: - -[org.gnome.desktop.interface:Unity] -font-name='Ubuntu 12' - -Will override the settings, only if "Unity" is found in -XDG_CURRENT_DESKTOP. Multiple per-desktop overrides can be specified -for a given key: the one which comes first in XDG_CURRENT_DESKTOP will -be used. - -https://bugzilla.gnome.org/show_bug.cgi?id=746592 ---- - gio/glib-compile-schemas.c | 83 ++++++++++++++++++++++++++++++++++---- - 1 file changed, 75 insertions(+), 8 deletions(-) - -diff --git a/gio/glib-compile-schemas.c b/gio/glib-compile-schemas.c -index 2dc8c7171..59fb68ee7 100644 ---- a/gio/glib-compile-schemas.c -+++ b/gio/glib-compile-schemas.c -@@ -179,6 +179,8 @@ typedef struct - GString *unparsed_default_value; - GVariant *default_value; - -+ GVariantDict *desktop_overrides; -+ - GString *strinfo; - gboolean is_enum; - gboolean is_flags; -@@ -731,6 +733,11 @@ key_state_serialise (KeyState *state) - g_variant_builder_add (&builder, "(y(**))", 'r', - state->minimum, state->maximum); - -+ /* per-desktop overrides */ -+ if (state->desktop_overrides) -+ g_variant_builder_add (&builder, "(y@a{sv})", 'd', -+ g_variant_dict_end (state->desktop_overrides)); -+ - state->serialised = g_variant_builder_end (&builder); - } - -@@ -768,6 +775,9 @@ key_state_free (gpointer data) - if (state->serialised) - g_variant_unref (state->serialised); - -+ if (state->desktop_overrides) -+ g_variant_dict_unref (state->desktop_overrides); -+ - g_slice_free (KeyState, state); - } - -@@ -1878,6 +1888,8 @@ set_overrides (GHashTable *schema_table, - gchar **groups; - gint i; - -+ g_debug ("Processing override file '%s'", filename); -+ - key_file = g_key_file_new (); - if (!g_key_file_load_from_file (key_file, filename, 0, &error)) - { -@@ -1900,18 +1912,31 @@ set_overrides (GHashTable *schema_table, - for (i = 0; groups[i]; i++) - { - const gchar *group = groups[i]; -+ const gchar *schema_name; -+ const gchar *desktop_id; - SchemaState *schema; -+ gchar **pieces; - gchar **keys; - gint j; - -- schema = g_hash_table_lookup (schema_table, group); -+ pieces = g_strsplit (group, ":", 2); -+ schema_name = pieces[0]; -+ desktop_id = pieces[1]; -+ -+ g_debug ("Processing group '%s' (schema '%s', %s)", -+ group, schema_name, desktop_id ? desktop_id : "all desktops"); -+ -+ schema = g_hash_table_lookup (schema_table, schema_name); - - if (schema == NULL) -- /* Having the schema not be installed is expected to be a -- * common case. Don't even emit an error message about -- * that. -- */ -- continue; -+ { -+ /* Having the schema not be installed is expected to be a -+ * common case. Don't even emit an error message about -+ * that. -+ */ -+ g_strfreev (pieces); -+ continue; -+ } - - keys = g_key_file_get_keys (key_file, group, NULL, NULL); - g_assert (keys != NULL); -@@ -1939,6 +1964,32 @@ set_overrides (GHashTable *schema_table, - - fprintf (stderr, _(" and --strict was specified; exiting.\n")); - g_key_file_free (key_file); -+ g_strfreev (pieces); -+ g_strfreev (groups); -+ g_strfreev (keys); -+ -+ return FALSE; -+ } -+ -+ if (desktop_id != NULL && state->l10n) -+ { -+ /* Let's avoid the n*m case of per-desktop localised -+ * default values, and just forbid it. -+ */ -+ fprintf (stderr, -+ _("cannot provide per-desktop overrides for localised " -+ "key '%s' in schema '%s' (override file '%s')"), -+ key, group, filename); -+ -+ if (!strict) -+ { -+ fprintf (stderr, _("; ignoring override for this key.\n")); -+ continue; -+ } -+ -+ fprintf (stderr, _(" and --strict was specified; exiting.\n")); -+ g_key_file_free (key_file); -+ g_strfreev (pieces); - g_strfreev (groups); - g_strfreev (keys); - -@@ -1969,6 +2020,7 @@ set_overrides (GHashTable *schema_table, - - fprintf (stderr, _("--strict was specified; exiting.\n")); - g_key_file_free (key_file); -+ g_strfreev (pieces); - g_strfreev (groups); - g_strfreev (keys); - -@@ -1997,6 +2049,7 @@ set_overrides (GHashTable *schema_table, - - fprintf (stderr, _(" and --strict was specified; exiting.\n")); - g_key_file_free (key_file); -+ g_strfreev (pieces); - g_strfreev (groups); - g_strfreev (keys); - -@@ -2025,6 +2078,7 @@ set_overrides (GHashTable *schema_table, - - fprintf (stderr, _(" and --strict was specified; exiting.\n")); - g_key_file_free (key_file); -+ g_strfreev (pieces); - g_strfreev (groups); - g_strfreev (keys); - -@@ -2032,11 +2086,24 @@ set_overrides (GHashTable *schema_table, - } - } - -- g_variant_unref (state->default_value); -- state->default_value = value; -+ if (desktop_id != NULL) -+ { -+ if (state->desktop_overrides == NULL) -+ state->desktop_overrides = g_variant_dict_new (NULL); -+ -+ g_variant_dict_insert_value (state->desktop_overrides, desktop_id, value); -+ g_variant_unref (value); -+ } -+ else -+ { -+ g_variant_unref (state->default_value); -+ state->default_value = value; -+ } -+ - g_free (string); - } - -+ g_strfreev (pieces); - g_strfreev (keys); - } - --- -2.21.0 - - -From 2ca9218fb46f32fa02bed43c6e60243c8c5d656f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alberts=20Muktup=C4=81vels?= -Date: Tue, 19 Jun 2018 23:39:24 +0300 -Subject: [PATCH 4/4] Add a test for per-desktop overrides - ---- - gio/glib-compile-schemas.c | 1 + - gio/tests/Makefile.am | 2 + - gio/tests/gsettings.c | 106 ++++++++++++++++++- - gio/tests/org.gtk.test.gschema.override.orig | 2 + - gio/tests/org.gtk.test.gschema.xml.orig | 6 ++ - 5 files changed, 116 insertions(+), 1 deletion(-) - create mode 100644 gio/tests/org.gtk.test.gschema.override.orig - -diff --git a/gio/glib-compile-schemas.c b/gio/glib-compile-schemas.c -index 59fb68ee7..00dd64146 100644 ---- a/gio/glib-compile-schemas.c -+++ b/gio/glib-compile-schemas.c -@@ -2139,6 +2139,7 @@ main (int argc, char **argv) - - /* These options are only for use in the gschema-compile tests */ - { "schema-file", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME_ARRAY, &schema_files, NULL, NULL }, -+ { "override-file", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME_ARRAY, &override_files, NULL, NULL }, - { NULL } - }; - -diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am -index 49a19bf4a..b41317ad9 100644 ---- a/gio/tests/Makefile.am -+++ b/gio/tests/Makefile.am -@@ -367,12 +367,14 @@ test.mo: de.po - EXTRA_DIST += de.po - dist_uninstalled_test_data += \ - org.gtk.test.gschema.xml.orig \ -+ org.gtk.test.gschema.override.orig \ - org.gtk.schemasourcecheck.gschema.xml \ - testenum.h \ - enums.xml.template - # Generated while running the testcase itself... - CLEANFILES += \ - org.gtk.test.gschema.xml \ -+ org.gtk.test.gschema.override \ - org.gtk.test.enums.xml \ - gsettings.store \ - gschemas.compiled \ -diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c -index 2be4122fe..acdeead4c 100644 ---- a/gio/tests/gsettings.c -+++ b/gio/tests/gsettings.c -@@ -2192,6 +2192,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS - "org.gtk.test.range.direct", - "org.gtk.test.mapped", - "org.gtk.test.descriptions", -+ "org.gtk.test.per-desktop", - NULL)); - } - -@@ -2583,6 +2584,100 @@ test_default_value (void) - g_object_unref (settings); - } - -+static gboolean -+string_map_func (GVariant *value, -+ gpointer *result, -+ gpointer user_data) -+{ -+ const gchar *str; -+ -+ str = g_variant_get_string (value, NULL); -+ *result = g_variant_new_string (str); -+ -+ return TRUE; -+} -+ -+/* Test that per-desktop values from org.gtk.test.gschema.override -+ * does not change default value if current desktop is not listed in -+ * $XDG_CURRENT_DESKTOP. -+ */ -+static void -+test_per_desktop (void) -+{ -+ GSettings *settings; -+ TestObject *obj; -+ gpointer p; -+ gchar *str; -+ -+ settings = g_settings_new ("org.gtk.test.per-desktop"); -+ obj = test_object_new (); -+ -+ if (!g_test_subprocess ()) -+ { -+ g_test_trap_subprocess ("/gsettings/per-desktop/subprocess", 0, 0); -+ g_test_trap_assert_passed (); -+ } -+ -+ str = g_settings_get_string (settings, "desktop"); -+ g_assert_cmpstr (str, ==, "GNOME"); -+ g_free (str); -+ -+ p = g_settings_get_mapped (settings, "desktop", string_map_func, NULL); -+ -+ str = g_variant_dup_string (p, NULL); -+ g_assert_cmpstr (str, ==, "GNOME"); -+ g_free (str); -+ -+ g_variant_unref (p); -+ -+ g_settings_bind (settings, "desktop", obj, "string", G_SETTINGS_BIND_DEFAULT); -+ -+ g_object_get (obj, "string", &str, NULL); -+ g_assert_cmpstr (str, ==, "GNOME"); -+ g_free (str); -+ -+ g_object_unref (settings); -+ g_object_unref (obj); -+} -+ -+/* Test that per-desktop values from org.gtk.test.gschema.override -+ * are successfully loaded based on the value of $XDG_CURRENT_DESKTOP. -+ */ -+static void -+test_per_desktop_subprocess (void) -+{ -+ GSettings *settings; -+ TestObject *obj; -+ gpointer p; -+ gchar *str; -+ -+ g_setenv ("XDG_CURRENT_DESKTOP", "GNOME-Classic:GNOME", TRUE); -+ -+ settings = g_settings_new ("org.gtk.test.per-desktop"); -+ obj = test_object_new (); -+ -+ str = g_settings_get_string (settings, "desktop"); -+ g_assert_cmpstr (str, ==, "GNOME Classic"); -+ g_free (str); -+ -+ p = g_settings_get_mapped (settings, "desktop", string_map_func, NULL); -+ -+ str = g_variant_dup_string (p, NULL); -+ g_assert_cmpstr (str, ==, "GNOME Classic"); -+ g_free (str); -+ -+ g_variant_unref (p); -+ -+ g_settings_bind (settings, "desktop", obj, "string", G_SETTINGS_BIND_DEFAULT); -+ -+ g_object_get (obj, "string", &str, NULL); -+ g_assert_cmpstr (str, ==, "GNOME Classic"); -+ g_free (str); -+ -+ g_object_unref (settings); -+ g_object_unref (obj); -+} -+ - static void - test_extended_schema (void) - { -@@ -2603,6 +2698,7 @@ int - main (int argc, char *argv[]) - { - gchar *schema_text; -+ gchar *override_text; - gchar *enums; - gint result; - -@@ -2625,6 +2721,7 @@ main (int argc, char *argv[]) - g_setenv ("XDG_DATA_DIRS", ".", TRUE); - g_setenv ("XDG_DATA_HOME", ".", TRUE); - g_setenv ("GSETTINGS_SCHEMA_DIR", ".", TRUE); -+ g_setenv ("XDG_CURRENT_DESKTOP", "", TRUE); - - if (!backend_set) - g_setenv ("GSETTINGS_BACKEND", "memory", TRUE); -@@ -2647,6 +2744,10 @@ main (int argc, char *argv[]) - g_assert (g_file_set_contents ("org.gtk.test.gschema.xml", schema_text, -1, NULL)); - g_free (schema_text); - -+ g_assert (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.override.orig", &override_text, NULL, NULL)); -+ g_assert (g_file_set_contents ("org.gtk.test.gschema.override", override_text, -1, NULL)); -+ g_free (override_text); -+ - /* Meson build defines this, autotools build does not */ - #ifndef GLIB_COMPILE_SCHEMAS - #define GLIB_COMPILE_SCHEMAS "../glib-compile-schemas" -@@ -2655,7 +2756,8 @@ main (int argc, char *argv[]) - g_remove ("gschemas.compiled"); - g_assert (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=. " - "--schema-file=org.gtk.test.enums.xml " -- "--schema-file=org.gtk.test.gschema.xml", -+ "--schema-file=org.gtk.test.gschema.xml " -+ "--override-file=org.gtk.test.gschema.override", - NULL, NULL, &result, NULL)); - g_assert (result == 0); - -@@ -2736,6 +2838,8 @@ main (int argc, char *argv[]) - g_test_add_func ("/gsettings/read-descriptions", test_read_descriptions); - g_test_add_func ("/gsettings/test-extended-schema", test_extended_schema); - g_test_add_func ("/gsettings/default-value", test_default_value); -+ g_test_add_func ("/gsettings/per-desktop", test_per_desktop); -+ g_test_add_func ("/gsettings/per-desktop/subprocess", test_per_desktop_subprocess); - - result = g_test_run (); - -diff --git a/gio/tests/org.gtk.test.gschema.override.orig b/gio/tests/org.gtk.test.gschema.override.orig -new file mode 100644 -index 000000000..6694baace ---- /dev/null -+++ b/gio/tests/org.gtk.test.gschema.override.orig -@@ -0,0 +1,2 @@ -+[org.gtk.test.per-desktop:GNOME-Classic] -+desktop = "GNOME Classic" -diff --git a/gio/tests/org.gtk.test.gschema.xml.orig b/gio/tests/org.gtk.test.gschema.xml.orig -index c07558335..fbcdce683 100644 ---- a/gio/tests/org.gtk.test.gschema.xml.orig -+++ b/gio/tests/org.gtk.test.gschema.xml.orig -@@ -209,4 +209,10 @@ - - - -+ -+ -+ "GNOME" -+ -+ -+ - --- -2.21.0 - diff --git a/1176.patch b/1176.patch deleted file mode 100644 index 7322a122caf8c71dc6dcd70dd8dee6b8c5d4b68d..0000000000000000000000000000000000000000 --- a/1176.patch +++ /dev/null @@ -1,371 +0,0 @@ -From ef1035d9d86464ea0b5dde60a7a0e190895fdf5b Mon Sep 17 00:00:00 2001 -From: Simon McVittie -Date: Mon, 14 Oct 2019 08:22:24 +0100 -Subject: [PATCH] gcredentialsprivate: Document the various private macros - -Signed-off-by: Simon McVittie ---- - gio/gcredentialsprivate.h | 59 +++++++++++++++++++++++++++++++++++++++ - 1 file changed, 59 insertions(+) - -diff --git a/gio/gcredentialsprivate.h b/gio/gcredentialsprivate.h -index 4d1c420a8..06f0aed19 100644 ---- a/gio/gcredentialsprivate.h -+++ b/gio/gcredentialsprivate.h -@@ -22,6 +22,65 @@ - #include "gio/gcredentials.h" - #include "gio/gnetworking.h" - -+/* -+ * G_CREDENTIALS_SUPPORTED: -+ * -+ * Defined to 1 if GCredentials works. -+ */ -+#undef G_CREDENTIALS_SUPPORTED -+ -+/* -+ * G_CREDENTIALS_USE_LINUX_UCRED, etc.: -+ * -+ * Defined to 1 if GCredentials uses Linux `struct ucred`, etc. -+ */ -+#undef G_CREDENTIALS_USE_LINUX_UCRED -+#undef G_CREDENTIALS_USE_FREEBSD_CMSGCRED -+#undef G_CREDENTIALS_USE_NETBSD_UNPCBID -+#undef G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED -+#undef G_CREDENTIALS_USE_SOLARIS_UCRED -+ -+/* -+ * G_CREDENTIALS_NATIVE_TYPE: -+ * -+ * Defined to one of G_CREDENTIALS_TYPE_LINUX_UCRED, etc. -+ */ -+#undef G_CREDENTIALS_NATIVE_TYPE -+ -+/* -+ * G_CREDENTIALS_NATIVE_SIZE: -+ * -+ * Defined to the size of the %G_CREDENTIALS_NATIVE_TYPE -+ */ -+#undef G_CREDENTIALS_NATIVE_SIZE -+ -+/* -+ * G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED: -+ * -+ * Defined to 1 if we have a message-passing API in which credentials -+ * are attached to a particular message, such as `SCM_CREDENTIALS` on Linux -+ * or `SCM_CREDS` on FreeBSD. -+ */ -+#undef G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED -+ -+/* -+ * G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED: -+ * -+ * Defined to 1 if we have a `getsockopt()`-style API in which one end of -+ * a socket connection can directly query the credentials of the process -+ * that initiated the other end, such as `getsockopt SO_PEERCRED` on Linux -+ * or `getpeereid()` on multiple operating systems. -+ */ -+#undef G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED -+ -+/* -+ * G_CREDENTIALS_SPOOFING_SUPPORTED: -+ * -+ * Defined to 1 if privileged processes can spoof their credentials when -+ * using the message-passing API. -+ */ -+#undef G_CREDENTIALS_SPOOFING_SUPPORTED -+ - #ifdef __linux__ - #define G_CREDENTIALS_SUPPORTED 1 - #define G_CREDENTIALS_USE_LINUX_UCRED 1 --- -2.23.0 - -From ee502dbbe89a5976c32eb8863c9a9d274ddb60e1 Mon Sep 17 00:00:00 2001 -From: Simon McVittie -Date: Mon, 14 Oct 2019 08:47:39 +0100 -Subject: [PATCH] GDBus: prefer getsockopt()-style credentials-passing APIs - -Conceptually, a D-Bus server is really trying to determine the credentials -of (the process that initiated) a connection, not the credentials that -the process had when it sent a particular message. Ideally, it does -this with a getsockopt()-style API that queries the credentials of the -connection's initiator without requiring any particular cooperation from -that process, avoiding a class of possible failures. - -The leading '\0' in the D-Bus protocol is primarily a workaround -for platforms where the message-based credentials-passing API is -strictly better than the getsockopt()-style API (for example, on -FreeBSD, SCM_CREDS includes a process ID but getpeereid() does not), -or where the getsockopt()-style API does not exist at all. As a result -libdbus, the reference implementation of D-Bus, does not implement -Linux SCM_CREDENTIALS at all - it has no reason to do so, because the -SO_PEERCRED socket option is equally informative. - -This change makes GDBusServer on Linux more closely match the behaviour -of libdbus. - -In particular, GNOME/glib#1831 indicates that when a libdbus client -connects to a GDBus server, recvmsg() sometimes yields a SCM_CREDENTIALS -message with cmsg_data={pid=0, uid=65534, gid=65534}. I think this is -most likely a race condition in the early steps to connect: - - client server - connect - accept - send '\0' <- race -> set SO_PASSCRED = 1 - receive '\0' - -If the server wins the race: - - client server - connect - accept - set SO_PASSCRED = 1 - send '\0' - receive '\0' - -then everything is fine. However, if the client wins the race: - - client server - connect - accept - send '\0' - set SO_PASSCRED = 1 - receive '\0' - -then the kernel does not record credentials for the message containing -'\0' (because SO_PASSCRED was 0 at the time). However, by the time the -server receives the message, the kernel knows that credentials are -desired. I would have expected the kernel to omit the credentials header -in this case, but it seems that instead, it synthesizes a credentials -structure with a dummy process ID 0, a dummy uid derived from -/proc/sys/kernel/overflowuid and a dummy gid derived from -/proc/sys/kernel/overflowgid. - -In an unconfigured GDBusServer, hitting this race condition results in -falling back to DBUS_COOKIE_SHA1 authentication, which in practice usually -succeeds in authenticating the peer's uid. However, we encourage AF_UNIX -servers on Unix platforms to allow only EXTERNAL authentication as a -security-hardening measure, because DBUS_COOKIE_SHA1 relies on a series -of assumptions including a cryptographically strong PRNG and a shared -home directory with no write access by others, which are not necessarily -true for all operating systems and users. EXTERNAL authentication will -fail if the server cannot determine the client's credentials. - -In particular, this caused a regression when CVE-2019-14822 was fixed -in ibus, which appears to be resolved by this commit. Qt clients -(which use libdbus) intermittently fail to connect to an ibus server -(which uses GDBusServer), because ibus no longer allows DBUS_COOKIE_SHA1 -authentication or non-matching uids. - -Signed-off-by: Simon McVittie -Closes: https://gitlab.gnome.org/GNOME/glib/issues/1831 ---- - gio/gcredentialsprivate.h | 18 ++++++++++++++++++ - gio/gdbusauth.c | 27 +++++++++++++++++++++++++-- - 2 files changed, 43 insertions(+), 2 deletions(-) - -diff --git a/gio/gcredentialsprivate.h b/gio/gcredentialsprivate.h -index 06f0aed19..e9ec09b9f 100644 ---- a/gio/gcredentialsprivate.h -+++ b/gio/gcredentialsprivate.h -@@ -81,6 +81,18 @@ - */ - #undef G_CREDENTIALS_SPOOFING_SUPPORTED - -+/* -+ * G_CREDENTIALS_PREFER_MESSAGE_PASSING: -+ * -+ * Defined to 1 if the data structure transferred by the message-passing -+ * API is strictly more informative than the one transferred by the -+ * `getsockopt()`-style API, and hence should be preferred, even for -+ * protocols like D-Bus that are defined in terms of the credentials of -+ * the (process that opened the) socket, as opposed to the credentials -+ * of an individual message. -+ */ -+#undef G_CREDENTIALS_PREFER_MESSAGE_PASSING -+ - #ifdef __linux__ - #define G_CREDENTIALS_SUPPORTED 1 - #define G_CREDENTIALS_USE_LINUX_UCRED 1 -@@ -100,6 +112,12 @@ - #define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct cmsgcred)) - #define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1 - #define G_CREDENTIALS_SPOOFING_SUPPORTED 1 -+/* GLib doesn't implement it yet, but FreeBSD's getsockopt()-style API -+ * is getpeereid(), which is not as informative as struct cmsgcred - -+ * it does not tell us the PID. As a result, libdbus prefers to use -+ * SCM_CREDS, and if we implement getpeereid() in future, we should -+ * do the same. */ -+#define G_CREDENTIALS_PREFER_MESSAGE_PASSING 1 - - #elif defined(__NetBSD__) - #define G_CREDENTIALS_SUPPORTED 1 -diff --git a/gio/gdbusauth.c b/gio/gdbusauth.c -index 752ec23fc..14cc5d70e 100644 ---- a/gio/gdbusauth.c -+++ b/gio/gdbusauth.c -@@ -31,6 +31,7 @@ - #include "gdbusutils.h" - #include "gioenumtypes.h" - #include "gcredentials.h" -+#include "gcredentialsprivate.h" - #include "gdbusprivate.h" - #include "giostream.h" - #include "gdatainputstream.h" -@@ -969,9 +970,31 @@ _g_dbus_auth_run_server (GDBusAuth *auth, - - g_data_input_stream_set_newline_type (dis, G_DATA_STREAM_NEWLINE_TYPE_CR_LF); - -- /* first read the NUL-byte */ -+ /* read the NUL-byte, possibly with credentials attached */ - #ifdef G_OS_UNIX -- if (G_IS_UNIX_CONNECTION (auth->priv->stream)) -+#ifndef G_CREDENTIALS_PREFER_MESSAGE_PASSING -+ if (G_IS_SOCKET_CONNECTION (auth->priv->stream)) -+ { -+ GSocket *sock = g_socket_connection_get_socket (G_SOCKET_CONNECTION (auth->priv->stream)); -+ -+ local_error = NULL; -+ credentials = g_socket_get_credentials (sock, &local_error); -+ -+ if (credentials == NULL && !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) -+ { -+ g_propagate_error (error, local_error); -+ goto out; -+ } -+ else -+ { -+ /* Clear the error indicator, so we can retry with -+ * g_unix_connection_receive_credentials() if necessary */ -+ g_clear_error (&local_error); -+ } -+ } -+#endif -+ -+ if (credentials == NULL && G_IS_UNIX_CONNECTION (auth->priv->stream)) - { - local_error = NULL; - credentials = g_unix_connection_receive_credentials (G_UNIX_CONNECTION (auth->priv->stream), --- -2.23.0 - -From 1485a97d8051b0aa047987f7b0c0bfe4ba4ce55b Mon Sep 17 00:00:00 2001 -From: Simon McVittie -Date: Fri, 18 Oct 2019 10:55:09 +0100 -Subject: [PATCH] credentials: Invalid Linux struct ucred means "no - information" - -On Linux, if getsockopt SO_PEERCRED is used on a TCP socket, one -might expect it to fail with an appropriate error like ENOTSUP or -EPROTONOSUPPORT. However, it appears that in fact it succeeds, but -yields a credentials structure with pid 0, uid -1 and gid -1. These -are not real process, user and group IDs that can be allocated to a -real process (pid 0 needs to be reserved to give kill(0) its documented -special semantics, and similarly uid and gid -1 need to be reserved for -setresuid() and setresgid()) so it is not meaningful to signal them to -high-level API users. - -An API user with Linux-specific knowledge can still inspect these fields -via g_credentials_get_native() if desired. - -Similarly, if SO_PASSCRED is used to receive a SCM_CREDENTIALS message -on a receiving Unix socket, but the sending socket had not enabled -SO_PASSCRED at the time that the message was sent, it is possible -for it to succeed but yield a credentials structure with pid 0, uid -/proc/sys/kernel/overflowuid and gid /proc/sys/kernel/overflowgid. Even -if we were to read those pseudo-files, we cannot distinguish between -the overflow IDs and a real process that legitimately has the same IDs -(typically they are set to 'nobody' and 'nogroup', which can be used -by a real process), so we detect this situation by noticing that -pid == 0, and to save syscalls we do not read the overflow IDs from -/proc at all. - -This results in a small API change: g_credentials_is_same_user() now -returns FALSE if we compare two credentials structures that are both -invalid. This seems like reasonable, conservative behaviour: if we cannot -prove that they are the same user, we should assume they are not. - -Signed-off-by: Simon McVittie ---- - gio/gcredentials.c | 42 +++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 39 insertions(+), 3 deletions(-) - -diff --git a/gio/gcredentials.c b/gio/gcredentials.c -index c350e3c88..c4794ded7 100644 ---- a/gio/gcredentials.c -+++ b/gio/gcredentials.c -@@ -265,6 +265,35 @@ g_credentials_to_string (GCredentials *credentials) - - /* ---------------------------------------------------------------------------------------------------- */ - -+#if G_CREDENTIALS_USE_LINUX_UCRED -+/* -+ * Check whether @native contains invalid data. If getsockopt SO_PEERCRED -+ * is used on a TCP socket, it succeeds but yields a credentials structure -+ * with pid 0, uid -1 and gid -1. Similarly, if SO_PASSCRED is used on a -+ * receiving Unix socket when the sending socket did not also enable -+ * SO_PASSCRED, it can succeed but yield a credentials structure with -+ * pid 0, uid /proc/sys/kernel/overflowuid and gid -+ * /proc/sys/kernel/overflowgid. -+ */ -+static gboolean -+linux_ucred_check_valid (struct ucred *native, -+ GError **error) -+{ -+ if (native->pid == 0 -+ || native->uid == -1 -+ || native->gid == -1) -+ { -+ g_set_error_literal (error, -+ G_IO_ERROR, -+ G_IO_ERROR_INVALID_DATA, -+ _("GCredentials contains invalid data")); -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+#endif -+ - /** - * g_credentials_is_same_user: - * @credentials: A #GCredentials. -@@ -294,7 +323,8 @@ g_credentials_is_same_user (GCredentials *credentials, - - ret = FALSE; - #if G_CREDENTIALS_USE_LINUX_UCRED -- if (credentials->native.uid == other_credentials->native.uid) -+ if (linux_ucred_check_valid (&credentials->native, NULL) -+ && credentials->native.uid == other_credentials->native.uid) - ret = TRUE; - #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED - if (credentials->native.cmcred_euid == other_credentials->native.cmcred_euid) -@@ -453,7 +483,10 @@ g_credentials_get_unix_user (GCredentials *credentials, - g_return_val_if_fail (error == NULL || *error == NULL, -1); - - #if G_CREDENTIALS_USE_LINUX_UCRED -- ret = credentials->native.uid; -+ if (linux_ucred_check_valid (&credentials->native, error)) -+ ret = credentials->native.uid; -+ else -+ ret = -1; - #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED - ret = credentials->native.cmcred_euid; - #elif G_CREDENTIALS_USE_NETBSD_UNPCBID -@@ -499,7 +532,10 @@ g_credentials_get_unix_pid (GCredentials *credentials, - g_return_val_if_fail (error == NULL || *error == NULL, -1); - - #if G_CREDENTIALS_USE_LINUX_UCRED -- ret = credentials->native.pid; -+ if (linux_ucred_check_valid (&credentials->native, error)) -+ ret = credentials->native.pid; -+ else -+ ret = -1; - #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED - ret = credentials->native.cmcred_pid; - #elif G_CREDENTIALS_USE_NETBSD_UNPCBID --- -2.23.0 - diff --git a/13.patch b/13.patch deleted file mode 100644 index 6c6163d4968a18bd7d13f74299fae33f6b853ad9..0000000000000000000000000000000000000000 --- a/13.patch +++ /dev/null @@ -1,654 +0,0 @@ -From fe823e3cfe25c96de5e453d1acbdc036892a9c36 Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Tue, 17 Apr 2018 14:07:50 +0100 -Subject: [PATCH 1/4] codegen: Support Since and name changing annotations on - annotations - -Recursive annotations do seem to be supported, so we should support them -properly in the type system representation. This currently introduces no -behavioural changes, but will be used in upcoming commits. - -Signed-off-by: Philip Withnall - -https://bugzilla.gnome.org/show_bug.cgi?id=795304 ---- - gio/gdbus-2.0/codegen/dbustypes.py | 33 ++++++++++++++++++++++++++++++ - 1 file changed, 33 insertions(+) - -diff --git a/gio/gdbus-2.0/codegen/dbustypes.py b/gio/gdbus-2.0/codegen/dbustypes.py -index 359880ff7..29222f987 100644 ---- a/gio/gdbus-2.0/codegen/dbustypes.py -+++ b/gio/gdbus-2.0/codegen/dbustypes.py -@@ -27,6 +27,25 @@ class Annotation: - self.key = key - self.value = value - self.annotations = [] -+ self.since = '' -+ -+ def post_process(self, interface_prefix, cns, cns_upper, cns_lower, container): -+ key = self.key -+ overridden_key = utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.Name') -+ if utils.is_ugly_case(overridden_key): -+ self.key_lower = overridden_key.lower() -+ else: -+ if overridden_key: -+ key = overridden_key -+ self.key_lower = utils.camel_case_to_uscore(key).lower().replace('-', '_').replace('.', '_') -+ -+ if len(self.since) == 0: -+ self.since = utils.lookup_since(self.annotations) -+ if len(self.since) == 0: -+ self.since = container.since -+ -+ for a in self.annotations: -+ a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) - - class Arg: - def __init__(self, name, signature): -@@ -229,6 +248,8 @@ class Arg: - self.gvalue_get = 'g_value_get_boxed' - self.array_annotation = '(array zero-terminated=1)' - -+ for a in self.annotations: -+ a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) - - class Method: - def __init__(self, name): -@@ -270,6 +291,9 @@ class Method: - if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true': - self.deprecated = True - -+ for a in self.annotations: -+ a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) -+ - class Signal: - def __init__(self, name): - self.name = name -@@ -305,6 +329,9 @@ class Signal: - if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true': - self.deprecated = True - -+ for a in self.annotations: -+ a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) -+ - class Property: - def __init__(self, name, signature, access): - self.name = name -@@ -357,6 +384,9 @@ class Property: - if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true': - self.deprecated = True - -+ for a in self.annotations: -+ a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) -+ - # FIXME: for now we only support 'false' and 'const' on the signal itself, see #674913 and - # http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format - # for details -@@ -436,3 +466,6 @@ class Interface: - - for p in self.properties: - p.post_process(interface_prefix, cns, cns_upper, cns_lower, self) -+ -+ for a in self.annotations: -+ a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) --- -2.35.1 - -From dcb1c3fbd588dcf5cdcaeb65547fdbe176312e10 Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Tue, 17 Apr 2018 14:10:07 +0100 -Subject: [PATCH 2/4] codegen: Add --interface-info-[body|header] modes - -These generate basic .c and .h files containing the GDBusInterfaceInfo -for a D-Bus introspection XML file, but no other code (no skeletons, -proxies, GObjects, etc.). - -This is useful for projects who want to describe their D-Bus interfaces -using introspection XML, but who wish to implement the interfaces -manually (for various reasons, typically because the skeletons generated -by gdbus-codegen are too simplistic and limiting). Previously, these -projects would have had to write the GDBusInterfaceInfo manually, which -is painstaking and error-prone. - -The new --interface-info-[body|header] options are very similar to ---[body|header], but mutually exclusive with them. - -Signed-off-by: Philip Withnall - -https://bugzilla.gnome.org/show_bug.cgi?id=795304 ---- - docs/reference/gio/gdbus-codegen.xml | 65 +++++- - gio/gdbus-2.0/codegen/codegen.py | 280 ++++++++++++++++++++++++++ - gio/gdbus-2.0/codegen/codegen_main.py | 39 ++++ - 3 files changed, 377 insertions(+), 7 deletions(-) - -diff --git a/docs/reference/gio/gdbus-codegen.xml b/docs/reference/gio/gdbus-codegen.xml -index b1145e5ef..3e1a9d668 100644 ---- a/docs/reference/gio/gdbus-codegen.xml -+++ b/docs/reference/gio/gdbus-codegen.xml -@@ -39,6 +39,8 @@ - FILE - - -+ -+ - OUTFILE - - -@@ -69,7 +71,11 @@ - arguments on the command line and generates output files. - It currently supports generating C source code (via - ) or header (via ) -- and Docbook XML (via ). -+ and Docbook XML (via ). Alternatively, -+ more restricted C source code and headers can be generated, which just -+ contain the interface information (as GDBusInterfaceInfo -+ structures) using and -+ . - - - -@@ -90,8 +96,11 @@ - - - For C code generation either that -- generates source code, or that -- generates headers, can be used. These options must be used along with -+ generates source code, that -+ generates headers, that generates -+ interface information source code, or -+ that generates interface information -+ headers, can be used. These options must be used along with - , which is used to specify the file to output to. - - -@@ -282,8 +291,10 @@ - Directory to output generated source to. Equivalent to changing directory before generation. - - -- This option cannot be used with neither nor -- , and must be used. -+ This option cannot be used with , -+ , or -+ ; and -+ must be used. - - - -@@ -321,12 +332,52 @@ - - - -+ -+ -+ -+ -+ If this option is passed, it will generate the header code for the -+ GDBusInterfaceInfo structures only and will write it to -+ the disk by using the path and file name provided by -+ . -+ -+ -+ Using , or -+ are not allowed to be used along with -+ the and -+ options, because these options -+ are used to generate only one file. -+ -+ -+ -+ -+ -+ -+ -+ -+ If this option is passed, it will generate the source code for the -+ GDBusInterfaceInfo structures only and will write it to -+ the disk by using the path and file name provided by -+ . -+ -+ -+ Using , or -+ are not allowed to be used along with -+ the and -+ options, because these options -+ are used to generate only one file. -+ -+ -+ -+ - - OUTFILE - - -- The full path where the header () or the source code -- () will be written, using the path and filename provided by -+ The full path where the header (, -+ ) or the source code -+ (, ) will -+ be written, using the path and filename provided by - . The full path could be something like - $($OUTFILE).{c,h}. - -diff --git a/gio/gdbus-2.0/codegen/codegen.py b/gio/gdbus-2.0/codegen/codegen.py -index 442bd3f5d..4e258332d 100644 ---- a/gio/gdbus-2.0/codegen/codegen.py -+++ b/gio/gdbus-2.0/codegen/codegen.py -@@ -610,6 +610,286 @@ class HeaderCodeGenerator: - - # ---------------------------------------------------------------------------------------------------- - -+class InterfaceInfoHeaderCodeGenerator: -+ def __init__(self, ifaces, namespace, header_name, use_pragma, outfile): -+ self.ifaces = ifaces -+ self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) -+ self.header_guard = header_name.upper().replace('.', '_').replace('-', '_').replace('/', '_').replace(':', '_') -+ self.use_pragma = use_pragma -+ self.outfile = outfile -+ -+ # ---------------------------------------------------------------------------------------------------- -+ -+ def generate_header_preamble(self): -+ self.outfile.write(LICENSE_STR.format(config.VERSION)) -+ self.outfile.write('\n') -+ -+ if self.use_pragma: -+ self.outfile.write('#pragma once\n') -+ else: -+ self.outfile.write('#ifndef __{!s}__\n'.format(self.header_guard)) -+ self.outfile.write('#define __{!s}__\n'.format(self.header_guard)) -+ -+ self.outfile.write('\n') -+ self.outfile.write('#include \n') -+ self.outfile.write('\n') -+ self.outfile.write('G_BEGIN_DECLS\n') -+ self.outfile.write('\n') -+ -+ # ---------------------------------------------------------------------------------------------------- -+ -+ def declare_infos(self): -+ for i in self.ifaces: -+ self.outfile.write('extern const GDBusInterfaceInfo %s_interface;\n' % i.name_lower) -+ -+ # ---------------------------------------------------------------------------------------------------- -+ -+ def generate_header_postamble(self): -+ self.outfile.write('\n') -+ self.outfile.write('G_END_DECLS\n') -+ -+ if not self.use_pragma: -+ self.outfile.write('\n') -+ self.outfile.write('#endif /* __{!s}__ */\n'.format(self.header_guard)) -+ -+ # ---------------------------------------------------------------------------------------------------- -+ -+ def generate(self): -+ self.generate_header_preamble() -+ self.declare_infos() -+ self.generate_header_postamble() -+ -+# ---------------------------------------------------------------------------------------------------- -+ -+class InterfaceInfoBodyCodeGenerator: -+ def __init__(self, ifaces, namespace, header_name, outfile): -+ self.ifaces = ifaces -+ self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) -+ self.header_name = header_name -+ self.outfile = outfile -+ -+ # ---------------------------------------------------------------------------------------------------- -+ -+ def generate_body_preamble(self): -+ self.outfile.write(LICENSE_STR.format(config.VERSION)) -+ self.outfile.write('\n') -+ self.outfile.write('#ifdef HAVE_CONFIG_H\n' -+ '# include "config.h"\n' -+ '#endif\n' -+ '\n' -+ '#include "%s"\n' -+ '\n' -+ '#include \n' -+ % (self.header_name)) -+ self.outfile.write('\n') -+ -+ # ---------------------------------------------------------------------------------------------------- -+ -+ def generate_array(self, array_name_lower, element_type, elements): -+ self.outfile.write('const %s * const %s[] =\n' % (element_type, array_name_lower)) -+ self.outfile.write('{\n') -+ for (_, name) in sorted(elements, key=utils.version_cmp_key): -+ self.outfile.write(' &%s,\n' % name) -+ self.outfile.write(' NULL,\n') -+ self.outfile.write('};\n') -+ self.outfile.write('\n') -+ -+ def define_annotations(self, array_name_lower, annotations): -+ if len(annotations) == 0: -+ return -+ -+ annotation_pointers = [] -+ -+ for a in annotations: -+ # Skip internal annotations. -+ if a.key.startswith('org.gtk.GDBus'): -+ continue -+ -+ self.define_annotations('%s__%s_annotations' % (array_name_lower, a.key_lower), a.annotations) -+ -+ self.outfile.write('const GDBusAnnotationInfo %s__%s_annotation =\n' % (array_name_lower, a.key_lower)) -+ self.outfile.write('{\n') -+ self.outfile.write(' -1, /* ref count */\n') -+ self.outfile.write(' (gchar *) "%s",\n' % a.key) -+ self.outfile.write(' (gchar *) "%s",\n' % a.value) -+ if len(a.annotations) > 0: -+ self.outfile.write(' (GDBusAnnotationInfo **) %s__%s_annotations,\n' % (array_name_lower, a.key_lower)) -+ else: -+ self.outfile.write(' NULL, /* no annotations */\n') -+ self.outfile.write('};\n') -+ self.outfile.write('\n') -+ -+ key = (a.since, '%s__%s_annotation' % (array_name_lower, a.key_lower)) -+ annotation_pointers.append(key) -+ -+ self.generate_array(array_name_lower, 'GDBusAnnotationInfo', -+ annotation_pointers) -+ -+ def define_args(self, array_name_lower, args): -+ if len(args) == 0: -+ return -+ -+ arg_pointers = [] -+ -+ for a in args: -+ self.define_annotations('%s__%s_arg_annotations' % (array_name_lower, a.name), a.annotations) -+ -+ self.outfile.write('const GDBusArgInfo %s__%s_arg =\n' % (array_name_lower, a.name)) -+ self.outfile.write('{\n') -+ self.outfile.write(' -1, /* ref count */\n') -+ self.outfile.write(' (gchar *) "%s",\n' % a.name) -+ self.outfile.write(' (gchar *) "%s",\n' % a.signature) -+ if len(a.annotations) > 0: -+ self.outfile.write(' (GDBusAnnotationInfo **) %s__%s_arg_annotations,\n' % (array_name_lower, a.name)) -+ else: -+ self.outfile.write(' NULL, /* no annotations */\n') -+ self.outfile.write('};\n') -+ self.outfile.write('\n') -+ -+ key = (a.since, '%s__%s_arg' % (array_name_lower, a.name)) -+ arg_pointers.append(key) -+ -+ self.generate_array(array_name_lower, 'GDBusArgInfo', arg_pointers) -+ -+ def define_infos(self): -+ for i in self.ifaces: -+ self.outfile.write('/* ------------------------------------------------------------------------ */\n') -+ self.outfile.write('/* Definitions for %s */\n' % i.name) -+ self.outfile.write('\n') -+ -+ # GDBusMethodInfos. -+ if len(i.methods) > 0: -+ method_pointers = [] -+ -+ for m in i.methods: -+ self.define_args('%s_interface__%s_method_in_args' % (i.name_lower, m.name_lower), m.in_args) -+ self.define_args('%s_interface__%s_method_out_args' % (i.name_lower, m.name_lower), m.out_args) -+ self.define_annotations('%s_interface__%s_method_annotations' % (i.name_lower, m.name_lower), m.annotations) -+ -+ self.outfile.write('const GDBusMethodInfo %s_interface__%s_method =\n' % (i.name_lower, m.name_lower)) -+ self.outfile.write('{\n') -+ self.outfile.write(' -1, /* ref count */\n') -+ self.outfile.write(' (gchar *) "%s",\n' % m.name) -+ if len(m.in_args) > 0: -+ self.outfile.write(' (GDBusArgInfo **) %s_interface__%s_method_in_args,\n' % (i.name_lower, m.name_lower)) -+ else: -+ self.outfile.write(' NULL, /* no in args */\n') -+ if len(m.out_args) > 0: -+ self.outfile.write(' (GDBusArgInfo **) %s_interface__%s_method_out_args,\n' % (i.name_lower, m.name_lower)) -+ else: -+ self.outfile.write(' NULL, /* no out args */\n') -+ if len(m.annotations) > 0: -+ self.outfile.write(' (GDBusAnnotationInfo **) %s_interface__%s_method_annotations,\n' % (i.name_lower, m.name_lower)) -+ else: -+ self.outfile.write(' NULL, /* no annotations */\n') -+ self.outfile.write('};\n') -+ self.outfile.write('\n') -+ -+ key = (m.since, '%s_interface__%s_method' % (i.name_lower, m.name_lower)) -+ method_pointers.append(key) -+ -+ self.generate_array('%s_interface_methods' % i.name_lower, -+ 'GDBusMethodInfo', method_pointers) -+ -+ # GDBusSignalInfos. -+ if len(i.signals) > 0: -+ signal_pointers = [] -+ -+ for s in i.signals: -+ self.define_args('%s_interface__%s_signal_args' % (i.name_lower, s.name_lower), s.args) -+ self.define_annotations('%s_interface__%s_signal_annotations' % (i.name_lower, s.name_lower), s.annotations) -+ -+ self.outfile.write('const GDBusSignalInfo %s_interface__%s_signal =\n' % (i.name_lower, s.name_lower)) -+ self.outfile.write('{\n') -+ self.outfile.write(' -1, /* ref count */\n') -+ self.outfile.write(' (gchar *) "%s",\n' % s.name) -+ if len(s.args) > 0: -+ self.outfile.write(' (GDBusArgInfo **) %s_interface__%s_signal_args,\n' % (i.name_lower, s.name_lower)) -+ else: -+ self.outfile.write(' NULL, /* no args */\n') -+ if len(s.annotations) > 0: -+ self.outfile.write(' (GDBusAnnotationInfo **) %s_interface__%s_signal_annotations,\n' % (i.name_lower, s.name_lower)) -+ else: -+ self.outfile.write(' NULL, /* no annotations */\n') -+ self.outfile.write('};\n') -+ self.outfile.write('\n') -+ -+ key = (m.since, '%s_interface__%s_signal' % (i.name_lower, s.name_lower)) -+ signal_pointers.append(key) -+ -+ self.generate_array('%s_interface_signals' % i.name_lower, -+ 'GDBusSignalInfo', signal_pointers) -+ -+ # GDBusPropertyInfos. -+ if len(i.properties) > 0: -+ property_pointers = [] -+ -+ for p in i.properties: -+ if p.readable and p.writable: -+ flags = 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE' -+ elif p.readable: -+ flags = 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE' -+ elif p.writable: -+ flags = 'G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE' -+ else: -+ flags = 'G_DBUS_PROPERTY_INFO_FLAGS_NONE' -+ -+ self.define_annotations('%s_interface__%s_property_annotations' % (i.name_lower, p.name_lower), p.annotations) -+ -+ self.outfile.write('const GDBusPropertyInfo %s_interface__%s_property =\n' % (i.name_lower, p.name_lower)) -+ self.outfile.write('{\n') -+ self.outfile.write(' -1, /* ref count */\n') -+ self.outfile.write(' (gchar *) "%s",\n' % p.name) -+ self.outfile.write(' (gchar *) "%s",\n' % p.signature) -+ self.outfile.write(' %s,\n' % flags) -+ if len(p.annotations) > 0: -+ self.outfile.write(' (GDBusAnnotationInfo **) %s_interface__%s_property_annotations,\n' % (i.name_lower, p.name_lower)) -+ else: -+ self.outfile.write(' NULL, /* no annotations */\n') -+ self.outfile.write('};\n') -+ self.outfile.write('\n') -+ -+ key = (m.since, '%s_interface__%s_property' % (i.name_lower, p.name_lower)) -+ property_pointers.append(key) -+ -+ self.generate_array('%s_interface_properties' % i.name_lower, -+ 'GDBusPropertyInfo', property_pointers) -+ -+ # Finally the GDBusInterfaceInfo. -+ self.define_annotations('%s_interface_annotations' % i.name_lower, -+ i.annotations) -+ -+ self.outfile.write('const GDBusInterfaceInfo %s_interface =\n' % i.name_lower) -+ self.outfile.write('{\n') -+ self.outfile.write(' -1, /* ref count */\n') -+ self.outfile.write(' (gchar *) "%s",\n' % i.name) -+ if len(i.methods) > 0: -+ self.outfile.write(' (GDBusMethodInfo **) %s_interface_methods,\n' % i.name_lower) -+ else: -+ self.outfile.write(' NULL, /* no methods */\n') -+ if len(i.signals) > 0: -+ self.outfile.write(' (GDBusSignalInfo **) %s_interface_signals,\n' % i.name_lower) -+ else: -+ self.outfile.write(' NULL, /* no signals */\n') -+ if len(i.properties) > 0: -+ self.outfile.write(' (GDBusPropertyInfo **) %s_interface_properties,\n' % i.name_lower) -+ else: -+ self.outfile.write( 'NULL, /* no properties */\n') -+ if len(i.annotations) > 0: -+ self.outfile.write(' (GDBusAnnotationInfo **) %s_interface_annotations,\n' % i.name_lower) -+ else: -+ self.outfile.write(' NULL, /* no annotations */\n') -+ self.outfile.write('};\n') -+ self.outfile.write('\n') -+ -+ # ---------------------------------------------------------------------------------------------------- -+ -+ def generate(self): -+ self.generate_body_preamble() -+ self.define_infos() -+ -+# ---------------------------------------------------------------------------------------------------- -+ - class CodeGenerator: - def __init__(self, ifaces, namespace, generate_objmanager, header_name, - docbook_gen, outfile): -diff --git a/gio/gdbus-2.0/codegen/codegen_main.py b/gio/gdbus-2.0/codegen/codegen_main.py -index 1cfe7c1bb..37efb3bcf 100755 ---- a/gio/gdbus-2.0/codegen/codegen_main.py -+++ b/gio/gdbus-2.0/codegen/codegen_main.py -@@ -175,6 +175,10 @@ def codegen_main(): - help='Generate C headers') - group.add_argument('--body', action='store_true', - help='Generate C code') -+ group.add_argument('--interface-info-header', action='store_true', -+ help='Generate GDBusInterfaceInfo C header') -+ group.add_argument('--interface-info-body', action='store_true', -+ help='Generate GDBusInterfaceInfo C code') - - group = arg_parser.add_mutually_exclusive_group() - group.add_argument('--output', metavar='FILE', -@@ -210,6 +214,24 @@ def codegen_main(): - - c_file = args.output - header_name = os.path.splitext(os.path.basename(c_file))[0] + '.h' -+ elif args.interface_info_header: -+ if args.output is None: -+ print_error('Using --interface-info-header requires --output') -+ if args.c_generate_object_manager: -+ print_error('--c-generate-object-manager is incompatible with ' -+ '--interface-info-header') -+ -+ h_file = args.output -+ header_name = os.path.basename(h_file) -+ elif args.interface_info_body: -+ if args.output is None: -+ print_error('Using --interface-info-body requires --output') -+ if args.c_generate_object_manager: -+ print_error('--c-generate-object-manager is incompatible with ' -+ '--interface-info-body') -+ -+ c_file = args.output -+ header_name = os.path.splitext(os.path.basename(c_file))[0] + '.h' - - all_ifaces = [] - for fname in args.files + args.xml_files: -@@ -250,6 +272,23 @@ def codegen_main(): - outfile) - gen.generate() - -+ if args.interface_info_header: -+ with open(h_file, 'w') as outfile: -+ gen = codegen.InterfaceInfoHeaderCodeGenerator(all_ifaces, -+ args.c_namespace, -+ header_name, -+ args.pragma_once, -+ outfile) -+ gen.generate() -+ -+ if args.interface_info_body: -+ with open(c_file, 'w') as outfile: -+ gen = codegen.InterfaceInfoBodyCodeGenerator(all_ifaces, -+ args.c_namespace, -+ header_name, -+ outfile) -+ gen.generate() -+ - sys.exit(0) - - if __name__ == "__main__": --- -2.35.1 - -From 11de9adfe6f57521ea5ed881b6862480c742414c Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Tue, 17 Apr 2018 14:12:18 +0100 -Subject: [PATCH 3/4] codegen: Suppress the old --xml-files option in the - --help output -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Since it’s deprecated in favour of positional arguments, including it in -the help output is confusing. - -Signed-off-by: Philip Withnall - -https://bugzilla.gnome.org/show_bug.cgi?id=795304 ---- - gio/gdbus-2.0/codegen/codegen_main.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/gio/gdbus-2.0/codegen/codegen_main.py b/gio/gdbus-2.0/codegen/codegen_main.py -index 37efb3bcf..d3763eb0f 100755 ---- a/gio/gdbus-2.0/codegen/codegen_main.py -+++ b/gio/gdbus-2.0/codegen/codegen_main.py -@@ -152,7 +152,7 @@ def codegen_main(): - arg_parser.add_argument('files', metavar='FILE', nargs='*', - help='D-Bus introspection XML file') - arg_parser.add_argument('--xml-files', metavar='FILE', action='append', default=[], -- help='D-Bus introspection XML file') -+ help=argparse.SUPPRESS) - arg_parser.add_argument('--interface-prefix', metavar='PREFIX', default='', - help='String to strip from D-Bus interface names for code and docs') - arg_parser.add_argument('--c-namespace', metavar='NAMESPACE', default='', --- -2.35.1 - -From b2b72837b0545e297db7ded8773377b4b6473a55 Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Tue, 17 Apr 2018 14:13:05 +0100 -Subject: [PATCH 4/4] codegen: Fix a minor Python linting warning - -This introduces no functional changes. - -Signed-off-by: Philip Withnall - -https://bugzilla.gnome.org/show_bug.cgi?id=795304 ---- - gio/gdbus-2.0/codegen/codegen_main.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/gio/gdbus-2.0/codegen/codegen_main.py b/gio/gdbus-2.0/codegen/codegen_main.py -index d3763eb0f..fa9c71373 100755 ---- a/gio/gdbus-2.0/codegen/codegen_main.py -+++ b/gio/gdbus-2.0/codegen/codegen_main.py -@@ -240,7 +240,7 @@ def codegen_main(): - parsed_ifaces = parser.parse_dbus_xml(xml_data) - all_ifaces.extend(parsed_ifaces) - -- if args.annotate != None: -+ if args.annotate is not None: - apply_annotations(all_ifaces, args.annotate) - - for i in all_ifaces: --- -2.35.1 diff --git a/1369.patch b/1369.patch deleted file mode 100644 index 2d5d1c37e36802970c47ec7503f2e500357926d3..0000000000000000000000000000000000000000 --- a/1369.patch +++ /dev/null @@ -1,38 +0,0 @@ -From a18f091c6c090b93cd816f8cd5be763b6e238632 Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Fri, 7 Feb 2020 17:10:23 +0000 -Subject: [PATCH] libcharset: Drop a redundant environment variable - -It was used for running tests when we built with autotools, but is no -longer used in the Meson build system. If we need something similar in -future, it should be done by adding internal API to override the -directory on a per-call basis, rather than loading a path from a shared -global table every time. - -Signed-off-by: Philip Withnall - -Helps: #1919 ---- - glib/libcharset/localcharset.c | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) - -diff --git a/glib/libcharset/localcharset.c b/glib/libcharset/localcharset.c -index 0c4d544be..ab3a2678d 100644 ---- a/glib/libcharset/localcharset.c -+++ b/glib/libcharset/localcharset.c -@@ -117,11 +117,7 @@ _g_locale_get_charset_aliases (void) - const char *base = "charset.alias"; - char *file_name; - -- /* Make it possible to override the charset.alias location. This is -- necessary for running the testsuite before "make install". */ -- dir = getenv ("CHARSETALIASDIR"); -- if (dir == NULL || dir[0] == '\0') -- dir = relocate (GLIB_CHARSETALIAS_DIR); -+ dir = relocate (GLIB_CHARSETALIAS_DIR); - - /* Concatenate dir and base into freshly allocated file_name. */ - { --- -2.31.1 - diff --git a/1596.patch b/1596.patch new file mode 100644 index 0000000000000000000000000000000000000000..786ac7c377d7819856e48817efd0e24fa4121f2d --- /dev/null +++ b/1596.patch @@ -0,0 +1,855 @@ +From 5e42384cc4499293259a8a37a737014a56de34df Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Fri, 23 Oct 2020 18:20:01 +0200 +Subject: [PATCH 1/4] tests: Iterate mainloop during launch test + +When launching an application, we wait for the DBus response from +systemd before executing the binary. Because of this the main loop needs +to be iterated for spawning to completed and the file to be created. + +Without this the test will time out if GLib was able to connect to the +session bus. +--- + gio/tests/desktop-app-info.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/gio/tests/desktop-app-info.c b/gio/tests/desktop-app-info.c +index fcc29c579..743230cbb 100644 +--- a/gio/tests/desktop-app-info.c ++++ b/gio/tests/desktop-app-info.c +@@ -334,6 +334,7 @@ wait_for_file (const gchar *want_this, + */ + while (access (want_this, F_OK) != 0) + { ++ g_main_context_iteration (NULL, FALSE); + g_usleep (100000); /* 100ms */ + g_assert_cmpuint (retries, >, 0); + retries--; +-- +2.31.1 + +From ba3b85a8fea0151e74de50e841a7f16f9b077a56 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Mon, 27 Jul 2020 22:22:32 +0200 +Subject: [PATCH 2/4] gdesktopappinfo: Move launched applications into + transient scope + +Try to move the spawned executable into its own systemd scope. To avoid +possible race conditions and ensure proper accounting, we delay the +execution of the real command until after the DBus call to systemd has +finished. + +From the two approaches we can take here, this is better in the sense +that we have a child that the API consumer can watch. API consumers +should not be doing this, however, gnome-session needs to watch children +during session startup. Until gnome-session is fixed, we will not be +able to change this. + +The alternative approach is to delegate launching itself to systemd by +creating a transient .service unit instead. This is cleaner and has e.g. +the advantage that systemd will take care of log redirection and similar +issues. + +Note that this patch is incomplete. The DBus call is done in a "fire and +forget" manner, which is fine in most cases, but means that "gio open" +will fail to move the child into the new scope as gio quits before the +DBus call finishes. +--- + gio/gdesktopappinfo.c | 264 ++++++++++++++++++++++++++++++++++++------ + 1 file changed, 227 insertions(+), 37 deletions(-) + +diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c +index 1a4b97918..afdcd42ac 100644 +--- a/gio/gdesktopappinfo.c ++++ b/gio/gdesktopappinfo.c +@@ -2730,6 +2730,148 @@ notify_desktop_launch (GDBusConnection *session_bus, + + #define _SPAWN_FLAGS_DEFAULT (G_SPAWN_SEARCH_PATH) + ++#if defined(__linux__) && !defined(__BIONIC__) ++typedef struct { ++ int pipe[2]; ++ GSpawnChildSetupFunc user_setup; ++ gpointer user_setup_data; ++} SpawnWrapperData; ++ ++static void ++launch_uris_with_spawn_delay_exec (gpointer user_data) ++{ ++ SpawnWrapperData *data = user_data; ++ ++ /* Clear CLOEXEC again, as that was set due to ++ * G_SPAWN_LEAVE_DESCRIPTORS_OPEN not being set. */ ++ fcntl (data->pipe[0], F_SETFD, 0); ++ ++ /* No need to close read side, we have CLOEXEC set. */ ++ ++ if (data->user_setup) ++ data->user_setup (data->user_setup_data); ++} ++ ++static gchar * ++systemd_unit_name_escape (const gchar *in) ++{ ++ /* Adapted from systemd source */ ++ GString * const str = g_string_sized_new (strlen (in)); ++ ++ for (; *in; in++) ++ { ++ if (g_ascii_isalnum (*in) || *in == ':' || *in == '_' || *in == '.') ++ g_string_append_c (str, *in); ++ else ++ g_string_append_printf (str, "\\x%02x", *in); ++ } ++ return g_string_free (str, FALSE); ++} ++ ++static void ++create_systemd_scope (GDBusConnection *session_bus, ++ GDesktopAppInfo *info, ++ gint pid, ++ GAsyncReadyCallback callback, ++ gpointer user_data) ++{ ++ GVariantBuilder builder; ++ const char *app_name = g_get_application_name (); ++ char *appid = NULL; ++ char *appid_escaped = NULL; ++ char *snid_escaped = NULL; ++ char *unit_name = NULL; ++ ++ /* In this order: ++ * 1. Actual application ID from file ++ * 2. Stripping the .desktop from the desktop ID ++ * 3. Fall back to using the binary name ++ */ ++ if (info->app_id) ++ appid = g_strdup (info->app_id); ++ else if (info->desktop_id && g_str_has_suffix (info->desktop_id, ".desktop")) ++ appid = g_strndup (info->desktop_id, strlen (info->desktop_id) - 8); ++ else ++ appid = g_path_get_basename (info->binary); ++ ++ appid_escaped = systemd_unit_name_escape (appid); ++ ++ /* Generate a name conforming to ++ * https://systemd.io/DESKTOP_ENVIRONMENTS/ ++ * We use the PID to disambiguate, as that should be unique enough. ++ */ ++ unit_name = g_strdup_printf ("app-glib-%s-%d.scope", appid_escaped, pid); ++ ++ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ssa(sv)a(sa(sv)))")); ++ g_variant_builder_add (&builder, "s", unit_name); ++ g_variant_builder_add (&builder, "s", "fail"); ++ ++ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(sv)")); ++ ++ /* Add a generic human readable description, can be changed at will. */ ++ if (app_name) ++ g_variant_builder_add (&builder, ++ "(sv)", ++ "Description", ++ g_variant_new_take_string (g_strdup_printf ("Application launched by %s", ++ app_name))); ++ g_variant_builder_add (&builder, ++ "(sv)", ++ "PIDs", ++ g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, &pid, 1, 4)); ++ /* Default to let systemd garbage collect failed applications we launched. */ ++ g_variant_builder_add (&builder, ++ "(sv)", ++ "CollectMode", ++ g_variant_new_string ("inactive-or-failed")); ++ ++ g_variant_builder_close (&builder); ++ ++ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(sa(sv))")); ++ g_variant_builder_close (&builder); ++ ++ g_dbus_connection_call (session_bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "StartTransientUnit", ++ g_variant_builder_end (&builder), ++ G_VARIANT_TYPE ("(o)"), ++ G_DBUS_CALL_FLAGS_NO_AUTO_START, ++ 1000, ++ NULL, ++ callback, ++ user_data); ++ ++ g_free (appid); ++ g_free (appid_escaped); ++ g_free (snid_escaped); ++ g_free (unit_name); ++} ++ ++static void ++systemd_scope_created_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ GVariant *res = NULL; ++ GError *error = NULL; ++ ++ res = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error); ++ if (error != NULL) ++ { ++ g_debug ("Failed to move new child into scope: %s", error->message); ++ g_error_free (error); ++ } ++ ++ /* Unblock the waiting wrapper binary. */ ++ close (GPOINTER_TO_INT (user_data)); ++ ++ if (res) ++ g_variant_unref (res); ++} ++#endif ++ + static gboolean + g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + GDBusConnection *session_bus, +@@ -2750,13 +2892,14 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + GList *old_uris; + GList *dup_uris; + +- char **argv, **envp; ++ GStrv argv = NULL, envp = NULL; ++ GStrv wrapped_argv = NULL; ++ GList *launched_uris = NULL; ++ char *sn_id = NULL; + int argc; + + g_return_val_if_fail (info != NULL, FALSE); + +- argv = NULL; +- + if (launch_context) + envp = g_app_launch_context_get_environment (launch_context); + else +@@ -2770,27 +2913,19 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + do + { + GPid pid; +- GList *launched_uris; + GList *iter; +- char *sn_id = NULL; +- char **wrapped_argv; + int i; +- gsize j; +- const gchar * const wrapper_argv[] = +- { +- "/bin/sh", +- "-e", +- "-u", +- "-c", "export GIO_LAUNCHED_DESKTOP_FILE_PID=$$; exec \"$@\"", +- "sh", /* argv[0] for sh */ +- }; ++#if defined(__linux__) && !defined(__BIONIC__) ++ SpawnWrapperData wrapper_data; ++#endif ++ GSpawnChildSetupFunc setup = user_setup; ++ gpointer setup_data = user_setup_data; + + old_uris = dup_uris; + if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, error)) +- goto out; ++ return FALSE; + + /* Get the subset of URIs we're launching with this process */ +- launched_uris = NULL; + for (iter = old_uris; iter != NULL && iter != dup_uris; iter = iter->next) + launched_uris = g_list_prepend (launched_uris, iter->data); + launched_uris = g_list_reverse (launched_uris); +@@ -2799,7 +2934,7 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Unable to find terminal required for application")); +- goto out; ++ return FALSE; + } + + if (info->filename) +@@ -2808,7 +2943,6 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + info->filename, + TRUE); + +- sn_id = NULL; + if (launch_context) + { + GList *launched_files = create_files_for_uris (launched_uris); +@@ -2837,38 +2971,93 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + * with a wrapper program (grep the GLib git history for + * `gio-launch-desktop` for an example of this which could be + * resurrected). */ +- wrapped_argv = g_new (char *, argc + G_N_ELEMENTS (wrapper_argv) + 1); ++ wrapped_argv = g_new (char *, argc + 6 + 1); ++ ++ wrapped_argv[0] = g_strdup ("/bin/sh"); ++ wrapped_argv[1] = g_strdup ("-e"); ++ wrapped_argv[2] = g_strdup ("-u"); ++ wrapped_argv[3] = g_strdup ("-c"); ++ /* argument 4 is filled in below */ ++ wrapped_argv[5] = g_strdup ("sh"); + +- for (j = 0; j < G_N_ELEMENTS (wrapper_argv); j++) +- wrapped_argv[j] = g_strdup (wrapper_argv[j]); + for (i = 0; i < argc; i++) +- wrapped_argv[i + G_N_ELEMENTS (wrapper_argv)] = g_steal_pointer (&argv[i]); ++ wrapped_argv[i + 6] = g_steal_pointer (&argv[i]); ++ ++ wrapped_argv[i + 6] = NULL; ++ g_clear_pointer (&argv, g_free); ++ ++#if defined(__linux__) && !defined(__BIONIC__) ++ /* Create pipes, if we use a setup func, then set cloexec, ++ * otherwise our wrapper script will close both sides. */ ++ if (!g_unix_open_pipe (wrapper_data.pipe, 0, NULL)) ++ { ++ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, ++ _("Unable to create pipe for systemd synchronization")); ++ return FALSE; ++ } ++ ++ /* Set CLOEXEC on the write pipe, so we don't need to deal with it in the child. */ ++ fcntl (wrapper_data.pipe[1], F_SETFD, FD_CLOEXEC); + +- wrapped_argv[i + G_N_ELEMENTS (wrapper_argv)] = NULL; +- g_free (argv); +- argv = NULL; ++ if (!(spawn_flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN)) ++ { ++ /* In this case, we use a setup function (which could probably also ++ * overwrite envp to set GIO_LAUNCHED_DESKTOP_FILE_PID). ++ * ++ * Note that this does not incur an additional cost because ++ * G_SPAWN_LEAVE_DESCRIPTOR_OPEN must be set in order to use ++ * posix_spawn. */ ++ wrapper_data.user_setup = setup; ++ wrapper_data.user_setup_data = setup_data; ++ ++ setup = launch_uris_with_spawn_delay_exec; ++ setup_data = &wrapper_data; ++ } ++ ++ wrapped_argv[4] = g_strdup_printf ("export GIO_LAUNCHED_DESKTOP_FILE_PID=$$; cat <&%1$d; exec \"$@\" %1$d<&-", ++ wrapper_data.pipe[0]); ++#else ++ wrapped_argv[4] = g_strdup ("export GIO_LAUNCHED_DESKTOP_FILE_PID=$$; exec \"$@\""); ++#endif + + if (!g_spawn_async_with_fds (info->path, + wrapped_argv, + envp, + spawn_flags, +- user_setup, +- user_setup_data, ++ setup, ++ setup_data, + &pid, + stdin_fd, + stdout_fd, + stderr_fd, + error)) + { ++#if defined(__linux__) && !defined(__BIONIC__) ++ close (wrapper_data.pipe[0]); ++ close (wrapper_data.pipe[1]); ++#endif ++ + if (sn_id) + g_app_launch_context_launch_failed (launch_context, sn_id); + +- g_free (sn_id); +- g_list_free (launched_uris); +- + goto out; + } + ++#if defined(__linux__) && !defined(__BIONIC__) ++ /* We close write side asynchronously later on when the dbus call ++ * to systemd finishes. */ ++ close (wrapper_data.pipe[0]); ++ ++ if (session_bus) ++ create_systemd_scope (session_bus, ++ info, ++ pid, ++ systemd_scope_created_cb, ++ GINT_TO_POINTER (wrapper_data.pipe[1])); ++ else ++ close (wrapper_data.pipe[1]); ++#endif ++ + if (pid_callback != NULL) + pid_callback (info, pid, pid_callback_data); + +@@ -2893,19 +3082,20 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + sn_id, + launched_uris); + +- g_free (sn_id); +- g_list_free (launched_uris); +- +- g_strfreev (wrapped_argv); +- wrapped_argv = NULL; ++ g_clear_pointer (&sn_id, g_free); ++ g_clear_pointer (&launched_uris, g_list_free); ++ g_clear_pointer (&wrapped_argv, g_strfreev); + } + while (dup_uris != NULL); + + completed = TRUE; + +- out: ++out: + g_strfreev (argv); + g_strfreev (envp); ++ g_clear_pointer (&wrapped_argv, g_strfreev); ++ g_list_free (launched_uris); ++ g_free (sn_id); + + return completed; + } +-- +2.31.1 + +From cd67a1b0256d2397dac0836e154f3449b63a6b19 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Tue, 28 Jul 2020 12:11:13 +0200 +Subject: [PATCH 3/4] gdesktopappinfo: Handle task completion from spawn + function + +This allows delaying the return of the task until all dbus calls (in +particular the ones to setup the scope) have finished. + +This fixes the behaviour of the previous commit which would not +correctly move the process into the scope if the application exited +right after the task returned. +--- + gio/gdesktopappinfo.c | 212 +++++++++++++++++++++++++++++------------- + 1 file changed, 146 insertions(+), 66 deletions(-) + +diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c +index afdcd42ac..8d0f1688e 100644 +--- a/gio/gdesktopappinfo.c ++++ b/gio/gdesktopappinfo.c +@@ -2849,11 +2849,17 @@ create_systemd_scope (GDBusConnection *session_bus, + g_free (unit_name); + } + ++typedef struct { ++ GTask *task; ++ int fd; ++} ScopeCreatedData; ++ + static void + systemd_scope_created_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) + { ++ ScopeCreatedData *data = user_data; + GVariant *res = NULL; + GError *error = NULL; + +@@ -2865,13 +2871,47 @@ systemd_scope_created_cb (GObject *object, + } + + /* Unblock the waiting wrapper binary. */ +- close (GPOINTER_TO_INT (user_data)); ++ ++ close (data->fd); ++ ++ if (data->task) ++ { ++ gint pending; ++ pending = GPOINTER_TO_INT (g_task_get_task_data (data->task)); ++ pending -= 1; ++ g_task_set_task_data (data->task, GINT_TO_POINTER (pending), NULL); ++ ++ if (pending == 0 && !g_task_get_completed (data->task)) ++ g_task_return_boolean (data->task, TRUE); ++ } + + if (res) + g_variant_unref (res); ++ g_clear_object (&data->task); ++ g_free (data); + } + #endif + ++static void ++launch_uris_with_spawn_flush_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ GTask *task = G_TASK (user_data); ++ gint pending; ++ ++ g_dbus_connection_flush_finish (G_DBUS_CONNECTION (object), result, NULL); ++ ++ pending = GPOINTER_TO_INT (g_task_get_task_data (task)); ++ pending -= 1; ++ g_task_set_task_data (task, GINT_TO_POINTER (pending), NULL); ++ ++ if (pending == 0 && !g_task_get_completed (task)) ++ g_task_return_boolean (task, TRUE); ++ ++ g_object_unref (task); ++} ++ + static gboolean + g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + GDBusConnection *session_bus, +@@ -2886,9 +2926,10 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + gint stdin_fd, + gint stdout_fd, + gint stderr_fd, +- GError **error) ++ GTask *task, ++ GError **error_out) + { +- gboolean completed = FALSE; ++ GError *error = NULL; + GList *old_uris; + GList *dup_uris; + +@@ -2898,8 +2939,15 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + char *sn_id = NULL; + int argc; + ++ /* We may get a task to report back on or an error. But never both. */ ++ g_assert (!(task && error_out)); + g_return_val_if_fail (info != NULL, FALSE); + ++ /* Surrounding code must not have set any data on the task ++ * (it is cleared before calling this function). */ ++ if (session_bus && task) ++ g_assert (g_task_get_task_data (task) == NULL); ++ + if (launch_context) + envp = g_app_launch_context_get_environment (launch_context); + else +@@ -2922,8 +2970,8 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + gpointer setup_data = user_setup_data; + + old_uris = dup_uris; +- if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, error)) +- return FALSE; ++ if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, &error)) ++ goto out; + + /* Get the subset of URIs we're launching with this process */ + for (iter = old_uris; iter != NULL && iter != dup_uris; iter = iter->next) +@@ -2932,9 +2980,9 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + + if (info->terminal && !prepend_terminal_to_vector (&argc, &argv)) + { +- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, +- _("Unable to find terminal required for application")); +- return FALSE; ++ error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, ++ _("Unable to find terminal required for application")); ++ goto out; + } + + if (info->filename) +@@ -2991,9 +3039,9 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + * otherwise our wrapper script will close both sides. */ + if (!g_unix_open_pipe (wrapper_data.pipe, 0, NULL)) + { +- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, +- _("Unable to create pipe for systemd synchronization")); +- return FALSE; ++ error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, ++ _("Unable to create pipe for systemd synchronization")); ++ goto out; + } + + /* Set CLOEXEC on the write pipe, so we don't need to deal with it in the child. */ +@@ -3030,7 +3078,7 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + stdin_fd, + stdout_fd, + stderr_fd, +- error)) ++ &error)) + { + #if defined(__linux__) && !defined(__BIONIC__) + close (wrapper_data.pipe[0]); +@@ -3049,11 +3097,29 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + close (wrapper_data.pipe[0]); + + if (session_bus) +- create_systemd_scope (session_bus, +- info, +- pid, +- systemd_scope_created_cb, +- GINT_TO_POINTER (wrapper_data.pipe[1])); ++ { ++ ScopeCreatedData *data; ++ ++ data = g_new0 (ScopeCreatedData, 1); ++ ++ if (task) ++ { ++ gint pending; ++ pending = GPOINTER_TO_INT (g_task_get_task_data (task)); ++ pending += 1; ++ g_task_set_task_data (task, GINT_TO_POINTER (pending), NULL); ++ ++ data->task = g_object_ref (task); ++ } ++ ++ data->fd = wrapper_data.pipe[1]; ++ ++ create_systemd_scope (session_bus, ++ info, ++ pid, ++ systemd_scope_created_cb, ++ data); ++ } + else + close (wrapper_data.pipe[1]); + #endif +@@ -3088,8 +3154,6 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, + } + while (dup_uris != NULL); + +- completed = TRUE; +- + out: + g_strfreev (argv); + g_strfreev (envp); +@@ -3097,7 +3161,52 @@ out: + g_list_free (launched_uris); + g_free (sn_id); + +- return completed; ++ if (!error) ++ { ++ if (session_bus && task) ++ { ++ GCancellable *cancellable = g_task_get_cancellable (task); ++ gint pending; ++ pending = GPOINTER_TO_INT (g_task_get_task_data (task)); ++ pending += 1; ++ g_task_set_task_data (task, GINT_TO_POINTER (pending), NULL); ++ ++ /* FIXME: The D-Bus message from the notify_desktop_launch() function ++ * can be still lost even if flush is called later. See: ++ * https://gitlab.freedesktop.org/dbus/dbus/issues/72 ++ */ ++ g_dbus_connection_flush (session_bus, ++ cancellable, ++ launch_uris_with_spawn_flush_cb, ++ g_steal_pointer (&task)); ++ } ++ else if (session_bus) ++ { ++ /* No task available. */ ++ g_dbus_connection_flush (session_bus, ++ NULL, ++ NULL, ++ NULL); ++ } ++ else if (task) ++ { ++ /* Return the given task. */ ++ g_task_return_boolean (task, TRUE); ++ g_object_unref (task); ++ } ++ } ++ else ++ { ++ if (task) ++ { ++ g_task_return_error (task, error); ++ g_object_unref (task); ++ } ++ else ++ g_propagate_error (error_out, error); ++ } ++ ++ return !error; + } + + static gchar * +@@ -3246,17 +3355,9 @@ g_desktop_app_info_launch_uris_internal (GAppInfo *appinfo, + success = g_desktop_app_info_launch_uris_with_spawn (info, session_bus, info->exec, uris, launch_context, + spawn_flags, user_setup, user_setup_data, + pid_callback, pid_callback_data, +- stdin_fd, stdout_fd, stderr_fd, error); ++ stdin_fd, stdout_fd, stderr_fd, NULL, error); + +- if (session_bus != NULL) +- { +- /* This asynchronous flush holds a reference until it completes, +- * which ensures that the following unref won't immediately kill +- * the connection if we were the initial owner. +- */ +- g_dbus_connection_flush (session_bus, NULL, NULL, NULL); +- g_object_unref (session_bus); +- } ++ g_clear_object (&session_bus); + + return success; + } +@@ -3310,18 +3411,6 @@ launch_uris_with_dbus_cb (GObject *object, + g_object_unref (task); + } + +-static void +-launch_uris_flush_cb (GObject *object, +- GAsyncResult *result, +- gpointer user_data) +-{ +- GTask *task = G_TASK (user_data); +- +- g_dbus_connection_flush_finish (G_DBUS_CONNECTION (object), result, NULL); +- g_task_return_boolean (task, TRUE); +- g_object_unref (task); +-} +- + static void + launch_uris_bus_get_cb (GObject *object, + GAsyncResult *result, +@@ -3330,12 +3419,20 @@ launch_uris_bus_get_cb (GObject *object, + GTask *task = G_TASK (user_data); + GDesktopAppInfo *info = G_DESKTOP_APP_INFO (g_task_get_source_object (task)); + LaunchUrisData *data = g_task_get_task_data (task); ++ LaunchUrisData *data_copy = NULL; + GCancellable *cancellable = g_task_get_cancellable (task); + GDBusConnection *session_bus; +- GError *error = NULL; + + session_bus = g_bus_get_finish (result, NULL); + ++ data_copy = g_new0 (LaunchUrisData, 1); ++ data_copy->appinfo = g_steal_pointer (&data->appinfo); ++ data_copy->uris = g_steal_pointer (&data->uris); ++ data_copy->context = g_steal_pointer (&data->context); ++ ++ /* Allow other data to be attached to the task. */ ++ g_task_set_task_data (task, NULL, NULL); ++ + if (session_bus && info->app_id) + { + /* FIXME: The g_document_portal_add_documents() function, which is called +@@ -3343,34 +3440,21 @@ launch_uris_bus_get_cb (GObject *object, + * uses blocking calls. + */ + g_desktop_app_info_launch_uris_with_dbus (info, session_bus, +- data->uris, data->context, ++ data_copy->uris, data_copy->context, + cancellable, + launch_uris_with_dbus_cb, + g_steal_pointer (&task)); + } + else + { +- /* FIXME: The D-Bus message from the notify_desktop_launch() function +- * can be still lost even if flush is called later. See: +- * https://gitlab.freedesktop.org/dbus/dbus/issues/72 +- */ + g_desktop_app_info_launch_uris_with_spawn (info, session_bus, info->exec, +- data->uris, data->context, ++ data_copy->uris, data_copy->context, + _SPAWN_FLAGS_DEFAULT, NULL, + NULL, NULL, NULL, -1, -1, -1, +- &error); +- if (error != NULL) +- { +- g_task_return_error (task, g_steal_pointer (&error)); +- g_object_unref (task); +- } +- else +- g_dbus_connection_flush (session_bus, +- cancellable, +- launch_uris_flush_cb, +- g_steal_pointer (&task)); ++ g_steal_pointer (&task), NULL); + } + ++ launch_uris_data_free (data_copy); + g_clear_object (&session_bus); + } + +@@ -5186,16 +5270,12 @@ g_desktop_app_info_launch_action (GDesktopAppInfo *info, + if (exec_line) + g_desktop_app_info_launch_uris_with_spawn (info, session_bus, exec_line, NULL, launch_context, + _SPAWN_FLAGS_DEFAULT, NULL, NULL, NULL, NULL, +- -1, -1, -1, NULL); ++ -1, -1, -1, NULL, NULL); + + g_free (exec_line); + } + +- if (session_bus != NULL) +- { +- g_dbus_connection_flush (session_bus, NULL, NULL, NULL); +- g_object_unref (session_bus); +- } ++ g_clear_object (&session_bus); + } + /* Epilogue {{{1 */ + +-- +2.31.1 + +From 8da8a3ef6df8af6de8bd388192bebe8b51b3e782 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Thu, 17 Sep 2020 17:35:58 +0200 +Subject: [PATCH 4/4] gdesktopappinfo: Add SourcePath= to transient systemd + units + +systemd allows setting a SourcePath= which shows the file that the unit +has been generated from. KDE is starting to set this and it seems like a +good idea, so do the same here. + +See https://invent.kde.org/frameworks/kio/-/merge_requests/124 +--- + gio/gdesktopappinfo.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c +index 8d0f1688e..a833de4e6 100644 +--- a/gio/gdesktopappinfo.c ++++ b/gio/gdesktopappinfo.c +@@ -2777,6 +2777,7 @@ create_systemd_scope (GDBusConnection *session_bus, + { + GVariantBuilder builder; + const char *app_name = g_get_application_name (); ++ const char *source_path = NULL; + char *appid = NULL; + char *appid_escaped = NULL; + char *snid_escaped = NULL; +@@ -2802,6 +2803,8 @@ create_systemd_scope (GDBusConnection *session_bus, + */ + unit_name = g_strdup_printf ("app-glib-%s-%d.scope", appid_escaped, pid); + ++ source_path = g_desktop_app_info_get_filename (info); ++ + g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ssa(sv)a(sa(sv)))")); + g_variant_builder_add (&builder, "s", unit_name); + g_variant_builder_add (&builder, "s", "fail"); +@@ -2815,6 +2818,16 @@ create_systemd_scope (GDBusConnection *session_bus, + "Description", + g_variant_new_take_string (g_strdup_printf ("Application launched by %s", + app_name))); ++ ++ /* If we have a .desktop file, document that the scope has been "generated" ++ * from it. ++ */ ++ if (source_path && g_utf8_validate (source_path, -1, NULL)) ++ g_variant_builder_add (&builder, ++ "(sv)", ++ "SourcePath", ++ g_variant_new_string (source_path)); ++ + g_variant_builder_add (&builder, + "(sv)", + "PIDs", +-- +2.31.1 diff --git a/1713.patch b/1713.patch deleted file mode 100644 index cace858a27452b81b1c1c130d4d920205e01bc9a..0000000000000000000000000000000000000000 --- a/1713.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 4f0a31d66c2a6588495b8ae682f555584dafdf45 Mon Sep 17 00:00:00 2001 -From: Claudio Saavedra -Date: Wed, 21 Oct 2020 13:19:42 +0300 -Subject: [PATCH] gmain: g_main_context_check() can skip updating polled FD - sources - -If there is a file descriptor source that has a lower priority -than the one for sources that are going to be dispatched, -all subsequent file descriptor sources (internally sorted by -file descriptor identifier) do not get an update in their GPollRec -and later on wrong sources can be dispatched. - -Fix this by first finding the first GPollRec that matches the current -GPollFD, instead of relying on it to be the current one. At -the same time, document the assumptions about the ordering of the -file descriptor records and array and make explicit in the documentation -that the array needs to be passed to g_main_context_check() as it was -received from g_main_context_query(). - -Added a new test that reproduces the bug by creating two file -descriptor sources and an idle one. Since the first -file descriptor created has a lower identifier and a low priority, -the second one is not dispatched even when it has the same, higher, -priority as the idle source. After fixing this bug, both -higher priority sources are dispatched as expected. - -While this patch was written independently, a similar fix for this -bug was first submitted by Eugene M in GNOME/glib!562. Having a -second fix that basically does the same is a reassurance that we -are in the right here. - -Fixes #1592 ---- - glib/gmain.c | 32 ++++++++++++++++++++++-- - glib/tests/mainloop.c | 57 +++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 87 insertions(+), 2 deletions(-) - -diff --git a/glib/gmain.c b/glib/gmain.c -index 95992253d..a59cd686c 100644 ---- a/glib/gmain.c -+++ b/glib/gmain.c -@@ -3573,7 +3573,10 @@ g_main_context_prepare (GMainContext *context, - * store #GPollFD records that need to be polled. - * @n_fds: (in): length of @fds. - * -- * Determines information necessary to poll this main loop. -+ * Determines information necessary to poll this main loop. You should -+ * be careful to pass the resulting @fds array and its length @n_fds -+ * as is when calling g_main_context_check(), as this function relies -+ * on assumptions made when the array is filled. - * - * You must have successfully acquired the context with - * g_main_context_acquire() before you may call this function. -@@ -3597,6 +3600,10 @@ g_main_context_query (GMainContext *context, - - TRACE (GLIB_MAIN_CONTEXT_BEFORE_QUERY (context, max_priority)); - -+ /* fds is filled sequentially from poll_records. Since poll_records -+ * are incrementally sorted by file descriptor identifier, fds will -+ * also be incrementally sorted. -+ */ - n_poll = 0; - lastpollrec = NULL; - for (pollrec = context->poll_records; pollrec; pollrec = pollrec->next) -@@ -3611,6 +3618,10 @@ g_main_context_query (GMainContext *context, - */ - events = pollrec->fd->events & ~(G_IO_ERR|G_IO_HUP|G_IO_NVAL); - -+ /* This optimization --using the same GPollFD to poll for more -+ * than one poll record-- relies on the poll records being -+ * incrementally sorted. -+ */ - if (lastpollrec && pollrec->fd->fd == lastpollrec->fd->fd) - { - if (n_poll - 1 < n_fds) -@@ -3656,7 +3667,10 @@ g_main_context_query (GMainContext *context, - * the last call to g_main_context_query() - * @n_fds: return value of g_main_context_query() - * -- * Passes the results of polling back to the main loop. -+ * Passes the results of polling back to the main loop. You should be -+ * careful to pass @fds and its length @n_fds as received from -+ * g_main_context_query(), as this functions relies on assumptions -+ * on how @fds is filled. - * - * You must have successfully acquired the context with - * g_main_context_acquire() before you may call this function. -@@ -3711,10 +3725,22 @@ g_main_context_check (GMainContext *context, - return FALSE; - } - -+ /* The linear iteration below relies on the assumption that both -+ * poll records and the fds array are incrementally sorted by file -+ * descriptor identifier. -+ */ - pollrec = context->poll_records; - i = 0; - while (pollrec && i < n_fds) - { -+ /* Make sure that fds is sorted by file descriptor identifier. */ -+ g_assert (i <= 0 || fds[i - 1].fd < fds[i].fd); -+ -+ /* Skip until finding the first GPollRec matching the current GPollFD. */ -+ while (pollrec && pollrec->fd->fd != fds[i].fd) -+ pollrec = pollrec->next; -+ -+ /* Update all consecutive GPollRecs that match. */ - while (pollrec && pollrec->fd->fd == fds[i].fd) - { - if (pollrec->priority <= max_priority) -@@ -3725,6 +3751,7 @@ g_main_context_check (GMainContext *context, - pollrec = pollrec->next; - } - -+ /* Iterate to next GPollFD. */ - i++; - } - -@@ -4320,6 +4347,7 @@ g_main_context_add_poll_unlocked (GMainContext *context, - newrec->fd = fd; - newrec->priority = priority; - -+ /* Poll records are incrementally sorted by file descriptor identifier. */ - prevrec = NULL; - nextrec = context->poll_records; - while (nextrec) -diff --git a/glib/tests/mainloop.c b/glib/tests/mainloop.c -index f5d672a63..397921f2d 100644 ---- a/glib/tests/mainloop.c -+++ b/glib/tests/mainloop.c -@@ -1511,6 +1511,62 @@ test_unix_file_poll (void) - close (fd); - } - -+static void -+test_unix_fd_priority (void) -+{ -+ gint fd1, fd2; -+ GMainLoop *loop; -+ GSource *source; -+ -+ gint s1 = 0; -+ gboolean s2 = FALSE, s3 = FALSE; -+ -+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/1592"); -+ -+ loop = g_main_loop_new (NULL, FALSE); -+ -+ source = g_idle_source_new (); -+ g_source_set_callback (source, count_calls, &s1, NULL); -+ g_source_set_priority (source, 0); -+ g_source_attach (source, NULL); -+ g_source_unref (source); -+ -+ fd1 = open ("/dev/random", O_RDONLY); -+ g_assert_cmpint (fd1, >=, 0); -+ source = g_unix_fd_source_new (fd1, G_IO_IN); -+ g_source_set_callback (source, (GSourceFunc) (void (*)(void)) (flag_bool), &s2, NULL); -+ g_source_set_priority (source, 10); -+ g_source_attach (source, NULL); -+ g_source_unref (source); -+ -+ fd2 = open ("/dev/random", O_RDONLY); -+ g_assert_cmpint (fd2, >=, 0); -+ source = g_unix_fd_source_new (fd2, G_IO_IN); -+ g_source_set_callback (source, (GSourceFunc) (void (*)(void)) (flag_bool), &s3, NULL); -+ g_source_set_priority (source, 0); -+ g_source_attach (source, NULL); -+ g_source_unref (source); -+ -+ /* This tests a bug that depends on the source with the lowest FD -+ identifier to have the lowest priority. Make sure that this is -+ the case. */ -+ g_assert_cmpint (fd1, <, fd2); -+ -+ g_assert_true (g_main_context_iteration (NULL, FALSE)); -+ -+ /* Idle source should have been dispatched. */ -+ g_assert_cmpint (s1, ==, 1); -+ /* Low priority FD source shouldn't have been dispatched. */ -+ g_assert_false (s2); -+ /* Default priority FD source should have been dispatched. */ -+ g_assert_true (s3); -+ -+ g_main_loop_unref (loop); -+ -+ close (fd1); -+ close (fd2); -+} -+ - #endif - - static gboolean -@@ -1751,6 +1807,7 @@ main (int argc, char *argv[]) - g_test_add_func ("/mainloop/source-unix-fd-api", test_source_unix_fd_api); - g_test_add_func ("/mainloop/wait", test_mainloop_wait); - g_test_add_func ("/mainloop/unix-file-poll", test_unix_file_poll); -+ g_test_add_func ("/mainloop/unix-fd-priority", test_unix_fd_priority); - #endif - g_test_add_func ("/mainloop/nfds", test_nfds); - --- -2.31.1 - diff --git a/1965.patch b/1965.patch new file mode 100644 index 0000000000000000000000000000000000000000..59d7cb8382e7210a2db97d5050bef49da10670d0 --- /dev/null +++ b/1965.patch @@ -0,0 +1,222 @@ +From 1248b642ad32b0bdf296211c1a0a8817bebf1c66 Mon Sep 17 00:00:00 2001 +From: Simon McVittie +Date: Thu, 25 Feb 2021 10:35:36 +0000 +Subject: [PATCH 1/2] gversionmacros: Add version macros for GLib 2.70 + +Signed-off-by: Simon McVittie +--- + docs/reference/gio/gio-docs.xml | 4 +++ + docs/reference/glib/glib-docs.xml | 4 +++ + docs/reference/glib/glib-sections.txt | 14 ++++++++ + docs/reference/gobject/gobject-docs.xml | 4 +++ + docs/reference/meson.build | 2 +- + glib/gversionmacros.h | 44 +++++++++++++++++++++++++ + 6 files changed, 71 insertions(+), 1 deletion(-) + +diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml +index 9cd3d0e39..a09d6d31d 100644 +--- a/docs/reference/gio/gio-docs.xml ++++ b/docs/reference/gio/gio-docs.xml +@@ -389,6 +389,10 @@ + Index of new symbols in 2.68 + + ++ ++ Index of new symbols in 2.70 ++ ++ + + + +diff --git a/docs/reference/glib/glib-docs.xml b/docs/reference/glib/glib-docs.xml +index e464fb792..2f5de9e31 100644 +--- a/docs/reference/glib/glib-docs.xml ++++ b/docs/reference/glib/glib-docs.xml +@@ -288,6 +288,10 @@ + Index of new symbols in 2.68 + + ++ ++ Index of new symbols in 2.70 ++ ++ + + + +diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt +index 460a299bf..75994e889 100644 +--- a/docs/reference/glib/glib-sections.txt ++++ b/docs/reference/glib/glib-sections.txt +@@ -138,6 +138,7 @@ GLIB_VERSION_2_62 + GLIB_VERSION_2_64 + GLIB_VERSION_2_66 + GLIB_VERSION_2_68 ++GLIB_VERSION_2_70 + GLIB_VERSION_CUR_STABLE + GLIB_VERSION_PREV_STABLE + GLIB_VERSION_MIN_REQUIRED +@@ -168,6 +169,7 @@ GLIB_AVAILABLE_ENUMERATOR_IN_2_62 + GLIB_AVAILABLE_ENUMERATOR_IN_2_64 + GLIB_AVAILABLE_ENUMERATOR_IN_2_66 + GLIB_AVAILABLE_ENUMERATOR_IN_2_68 ++GLIB_AVAILABLE_ENUMERATOR_IN_2_70 + GLIB_AVAILABLE_IN_ALL + GLIB_AVAILABLE_IN_2_26 + GLIB_AVAILABLE_IN_2_28 +@@ -191,6 +193,7 @@ GLIB_AVAILABLE_IN_2_62 + GLIB_AVAILABLE_IN_2_64 + GLIB_AVAILABLE_IN_2_66 + GLIB_AVAILABLE_IN_2_68 ++GLIB_AVAILABLE_IN_2_70 + GLIB_AVAILABLE_MACRO_IN_2_26 + GLIB_AVAILABLE_MACRO_IN_2_28 + GLIB_AVAILABLE_MACRO_IN_2_30 +@@ -213,12 +216,14 @@ GLIB_AVAILABLE_MACRO_IN_2_62 + GLIB_AVAILABLE_MACRO_IN_2_64 + GLIB_AVAILABLE_MACRO_IN_2_66 + GLIB_AVAILABLE_MACRO_IN_2_68 ++GLIB_AVAILABLE_MACRO_IN_2_70 + GLIB_AVAILABLE_STATIC_INLINE_IN_2_44 + GLIB_AVAILABLE_STATIC_INLINE_IN_2_60 + GLIB_AVAILABLE_STATIC_INLINE_IN_2_62 + GLIB_AVAILABLE_STATIC_INLINE_IN_2_64 + GLIB_AVAILABLE_STATIC_INLINE_IN_2_66 + GLIB_AVAILABLE_STATIC_INLINE_IN_2_68 ++GLIB_AVAILABLE_STATIC_INLINE_IN_2_70 + GLIB_AVAILABLE_TYPE_IN_2_26 + GLIB_AVAILABLE_TYPE_IN_2_28 + GLIB_AVAILABLE_TYPE_IN_2_30 +@@ -241,6 +246,7 @@ GLIB_AVAILABLE_TYPE_IN_2_62 + GLIB_AVAILABLE_TYPE_IN_2_64 + GLIB_AVAILABLE_TYPE_IN_2_66 + GLIB_AVAILABLE_TYPE_IN_2_68 ++GLIB_AVAILABLE_TYPE_IN_2_70 + GLIB_DEPRECATED_ENUMERATOR + GLIB_DEPRECATED_ENUMERATOR_FOR + GLIB_DEPRECATED_ENUMERATOR_IN_2_26 +@@ -287,6 +293,8 @@ GLIB_DEPRECATED_ENUMERATOR_IN_2_66 + GLIB_DEPRECATED_ENUMERATOR_IN_2_66_FOR + GLIB_DEPRECATED_ENUMERATOR_IN_2_68 + GLIB_DEPRECATED_ENUMERATOR_IN_2_68_FOR ++GLIB_DEPRECATED_ENUMERATOR_IN_2_70 ++GLIB_DEPRECATED_ENUMERATOR_IN_2_70_FOR + GLIB_DEPRECATED_IN_2_26 + GLIB_DEPRECATED_IN_2_26_FOR + GLIB_DEPRECATED_IN_2_28 +@@ -331,6 +339,8 @@ GLIB_DEPRECATED_IN_2_66 + GLIB_DEPRECATED_IN_2_66_FOR + GLIB_DEPRECATED_IN_2_68 + GLIB_DEPRECATED_IN_2_68_FOR ++GLIB_DEPRECATED_IN_2_70 ++GLIB_DEPRECATED_IN_2_70_FOR + GLIB_DEPRECATED_MACRO + GLIB_DEPRECATED_MACRO_FOR + GLIB_DEPRECATED_MACRO_IN_2_26 +@@ -377,6 +387,8 @@ GLIB_DEPRECATED_MACRO_IN_2_66 + GLIB_DEPRECATED_MACRO_IN_2_66_FOR + GLIB_DEPRECATED_MACRO_IN_2_68 + GLIB_DEPRECATED_MACRO_IN_2_68_FOR ++GLIB_DEPRECATED_MACRO_IN_2_70 ++GLIB_DEPRECATED_MACRO_IN_2_70_FOR + GLIB_DEPRECATED_TYPE + GLIB_DEPRECATED_TYPE_FOR + GLIB_DEPRECATED_TYPE_IN_2_26 +@@ -423,6 +435,8 @@ GLIB_DEPRECATED_TYPE_IN_2_66 + GLIB_DEPRECATED_TYPE_IN_2_66_FOR + GLIB_DEPRECATED_TYPE_IN_2_68 + GLIB_DEPRECATED_TYPE_IN_2_68_FOR ++GLIB_DEPRECATED_TYPE_IN_2_70 ++GLIB_DEPRECATED_TYPE_IN_2_70_FOR + GLIB_VERSION_CUR_STABLE + GLIB_VERSION_PREV_STABLE + +diff --git a/docs/reference/gobject/gobject-docs.xml b/docs/reference/gobject/gobject-docs.xml +index ddbc9f274..e8e7c76d9 100644 +--- a/docs/reference/gobject/gobject-docs.xml ++++ b/docs/reference/gobject/gobject-docs.xml +@@ -208,6 +208,10 @@ + Index of new symbols in 2.68 + + ++ ++ Index of new symbols in 2.70 ++ ++ + + + +diff --git a/docs/reference/meson.build b/docs/reference/meson.build +index 3f09be555..53ca12ff8 100644 +--- a/docs/reference/meson.build ++++ b/docs/reference/meson.build +@@ -7,7 +7,7 @@ + stable_2_series_versions = [ + '26', '28', '30', '32', '34', '36', '38', + '40', '42', '44', '46', '48', '50', '52', '54', '56', '58', +- '60', '62', '64', '66', '68', ++ '60', '62', '64', '66', '68', '70', + ] + + ignore_decorators = [ +diff --git a/glib/gversionmacros.h b/glib/gversionmacros.h +index 77486eafb..d052709cf 100644 +--- a/glib/gversionmacros.h ++++ b/glib/gversionmacros.h +@@ -255,6 +255,16 @@ + */ + #define GLIB_VERSION_2_68 (G_ENCODE_VERSION (2, 68)) + ++/** ++ * GLIB_VERSION_2_70: ++ * ++ * A macro that evaluates to the 2.70 version of GLib, in a format ++ * that can be used by the C pre-processor. ++ * ++ * Since: 2.70 ++ */ ++#define GLIB_VERSION_2_70 (G_ENCODE_VERSION (2, 70)) ++ + /** + * GLIB_VERSION_CUR_STABLE: + * +@@ -1076,4 +1086,38 @@ + # define GLIB_AVAILABLE_TYPE_IN_2_68 + #endif + ++#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_70 ++# define GLIB_DEPRECATED_IN_2_70 GLIB_DEPRECATED ++# define GLIB_DEPRECATED_IN_2_70_FOR(f) GLIB_DEPRECATED_FOR(f) ++# define GLIB_DEPRECATED_MACRO_IN_2_70 GLIB_DEPRECATED_MACRO ++# define GLIB_DEPRECATED_MACRO_IN_2_70_FOR(f) GLIB_DEPRECATED_MACRO_FOR(f) ++# define GLIB_DEPRECATED_ENUMERATOR_IN_2_70 GLIB_DEPRECATED_ENUMERATOR ++# define GLIB_DEPRECATED_ENUMERATOR_IN_2_70_FOR(f) GLIB_DEPRECATED_ENUMERATOR_FOR(f) ++# define GLIB_DEPRECATED_TYPE_IN_2_70 GLIB_DEPRECATED_TYPE ++# define GLIB_DEPRECATED_TYPE_IN_2_70_FOR(f) GLIB_DEPRECATED_TYPE_FOR(f) ++#else ++# define GLIB_DEPRECATED_IN_2_70 _GLIB_EXTERN ++# define GLIB_DEPRECATED_IN_2_70_FOR(f) _GLIB_EXTERN ++# define GLIB_DEPRECATED_MACRO_IN_2_70 ++# define GLIB_DEPRECATED_MACRO_IN_2_70_FOR(f) ++# define GLIB_DEPRECATED_ENUMERATOR_IN_2_70 ++# define GLIB_DEPRECATED_ENUMERATOR_IN_2_70_FOR(f) ++# define GLIB_DEPRECATED_TYPE_IN_2_70 ++# define GLIB_DEPRECATED_TYPE_IN_2_70_FOR(f) ++#endif ++ ++#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_70 ++# define GLIB_AVAILABLE_IN_2_70 GLIB_UNAVAILABLE(2, 70) ++# define GLIB_AVAILABLE_STATIC_INLINE_IN_2_70 GLIB_UNAVAILABLE_STATIC_INLINE(2, 70) ++# define GLIB_AVAILABLE_MACRO_IN_2_70 GLIB_UNAVAILABLE_MACRO(2, 70) ++# define GLIB_AVAILABLE_ENUMERATOR_IN_2_70 GLIB_UNAVAILABLE_ENUMERATOR(2, 70) ++# define GLIB_AVAILABLE_TYPE_IN_2_70 GLIB_UNAVAILABLE_TYPE(2, 70) ++#else ++# define GLIB_AVAILABLE_IN_2_70 _GLIB_EXTERN ++# define GLIB_AVAILABLE_STATIC_INLINE_IN_2_70 ++# define GLIB_AVAILABLE_MACRO_IN_2_70 ++# define GLIB_AVAILABLE_ENUMERATOR_IN_2_70 ++# define GLIB_AVAILABLE_TYPE_IN_2_70 ++#endif ++ + #endif /* __G_VERSION_MACROS_H__ */ +-- +GitLab diff --git a/1968.patch b/1968.patch new file mode 100644 index 0000000000000000000000000000000000000000..1809214ddab9644bba5d90cc1cdb180ec170f6b5 --- /dev/null +++ b/1968.patch @@ -0,0 +1,1052 @@ +From 9e69f8b280afe8eccd9188cc53b8117e1b238db7 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Tue, 12 Oct 2021 15:52:18 -0500 +Subject: [PATCH 01/10] gspawn: use close_and_invalidate more + +--- + glib/gspawn.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/glib/gspawn.c b/glib/gspawn.c +index a15fb1ca1..5d8422869 100644 +--- a/glib/gspawn.c ++++ b/glib/gspawn.c +@@ -1710,7 +1710,7 @@ do_exec (gint child_err_report_fd, + child_err_report_fd = safe_dup (child_err_report_fd); + + safe_dup2 (source_fds[i], target_fds[i]); +- (void) close (source_fds[i]); ++ close_and_invalidate (&source_fds[i]); + } + } + } +-- +2.33.1 + +From fe2148fd5dd4f2e5c413c5cc0bb56c4a19304887 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Thu, 14 Oct 2021 10:43:52 -0500 +Subject: [PATCH 02/10] gspawn: Improve error message when dup fails + +This error message is no longer accurate now that we allow arbitrary fd +remapping. +--- + glib/gspawn.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/glib/gspawn.c b/glib/gspawn.c +index 5d8422869..e214a3998 100644 +--- a/glib/gspawn.c ++++ b/glib/gspawn.c +@@ -2363,7 +2363,7 @@ fork_exec (gboolean intermediate_child, + g_set_error (error, + G_SPAWN_ERROR, + G_SPAWN_ERROR_FAILED, +- _("Failed to redirect output or input of child process (%s)"), ++ _("Failed to duplicate file descriptor for child process (%s)"), + g_strerror (buf[1])); + + break; +-- +2.33.1 + +From 566eccdb0a2594b4d3ec13c7443028d968b41af8 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Tue, 12 Oct 2021 15:33:59 -0500 +Subject: [PATCH 03/10] gspawn: fix hangs when duping child_err_report_fd + +In case child_err_report_fd conflicts with one of the target_fds, the +code here is careful to dup child_err_report_fd in order to avoid +conflating the two. It was a good idea, but evidently was not tested, +because the newly-created fd is not created with CLOEXEC set. This means +it stays open in the child process, causing the parent to hang forever +waiting to read from the other end of the pipe. Oops! + +The fix is simple: just set CLOEXEC. This removes our only usage of the +safe_dup() function, so it can be dropped. + +Fixes #2506 +--- + glib/gspawn.c | 16 +--------------- + 1 file changed, 1 insertion(+), 15 deletions(-) + +diff --git a/glib/gspawn.c b/glib/gspawn.c +index e214a3998..8bbe573f7 100644 +--- a/glib/gspawn.c ++++ b/glib/gspawn.c +@@ -1500,20 +1500,6 @@ safe_closefrom (int lowfd) + #endif + } + +-/* This function is called between fork() and exec() and hence must be +- * async-signal-safe (see signal-safety(7)). */ +-static gint +-safe_dup (gint fd) +-{ +- gint ret; +- +- do +- ret = dup (fd); +- while (ret < 0 && (errno == EINTR || errno == EBUSY)); +- +- return ret; +-} +- + /* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ + static gint +@@ -1707,7 +1693,7 @@ do_exec (gint child_err_report_fd, + else + { + if (target_fds[i] == child_err_report_fd) +- child_err_report_fd = safe_dup (child_err_report_fd); ++ child_err_report_fd = dupfd_cloexec (child_err_report_fd); + + safe_dup2 (source_fds[i], target_fds[i]); + close_and_invalidate (&source_fds[i]); +-- +2.33.1 + +From b703fa8b760ac9272c5a0ed3e3763b2f71ecf574 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Thu, 14 Oct 2021 10:44:57 -0500 +Subject: [PATCH 04/10] gspawn: fix fd remapping conflation issue + +We currently dup all source fds to avoid possible conflation with the +target fds, but fail to consider that the result of a dup might itself +conflict with one of the target fds. Solve this the easy way by duping +all source_fds to values that are greater than the largest fd in +target_fds. + +Fixes #2503 +--- + glib/gspawn.c | 43 +++++++++++++++++++++++++------------------ + 1 file changed, 25 insertions(+), 18 deletions(-) + +diff --git a/glib/gspawn.c b/glib/gspawn.c +index 8bbe573f7..2b48b5600 100644 +--- a/glib/gspawn.c ++++ b/glib/gspawn.c +@@ -1258,13 +1258,13 @@ unset_cloexec (int fd) + /* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ + static int +-dupfd_cloexec (int parent_fd) ++dupfd_cloexec (int old_fd, int new_fd_min) + { + int fd, errsv; + #ifdef F_DUPFD_CLOEXEC + do + { +- fd = fcntl (parent_fd, F_DUPFD_CLOEXEC, 3); ++ fd = fcntl (old_fd, F_DUPFD_CLOEXEC, new_fd_min); + errsv = errno; + } + while (fd == -1 && errsv == EINTR); +@@ -1275,7 +1275,7 @@ dupfd_cloexec (int parent_fd) + int result, flags; + do + { +- fd = fcntl (parent_fd, F_DUPFD, 3); ++ fd = fcntl (old_fd, F_DUPFD, new_fd_min); + errsv = errno; + } + while (fd == -1 && errsv == EINTR); +@@ -1563,6 +1563,7 @@ do_exec (gint child_err_report_fd, + gpointer user_data) + { + gsize i; ++ gint max_target_fd = 0; + + if (working_directory && chdir (working_directory) < 0) + write_err_and_exit (child_err_report_fd, +@@ -1661,39 +1662,45 @@ do_exec (gint child_err_report_fd, + /* + * Work through the @source_fds and @target_fds mapping. + * +- * Based on code derived from ++ * Based on code originally derived from + * gnome-terminal:src/terminal-screen.c:terminal_screen_child_setup(), +- * used under the LGPLv2+ with permission from author. ++ * used under the LGPLv2+ with permission from author. (The code has ++ * since migrated to vte:src/spawn.cc:SpawnContext::exec and is no longer ++ * terribly similar to what we have here.) + */ + +- /* Basic fd assignments (where source == target) we can just unset FD_CLOEXEC +- * +- * If we're doing remapping fd assignments, we need to handle +- * the case where the user has specified e.g.: +- * 5 -> 4, 4 -> 6 +- * +- * We do this by duping the source fds temporarily in a first pass. +- * +- * If any of the @target_fds conflict with @child_err_report_fd, dup the +- * latter so it doesn’t get conflated. +- */ + if (n_fds > 0) + { ++ for (i = 0; i < n_fds; i++) ++ max_target_fd = MAX (max_target_fd, target_fds[i]); ++ ++ /* If we're doing remapping fd assignments, we need to handle ++ * the case where the user has specified e.g. 5 -> 4, 4 -> 6. ++ * We do this by duping all source fds, taking care to ensure the new ++ * fds are larger than any target fd to avoid introducing new conflicts. ++ */ + for (i = 0; i < n_fds; i++) + { + if (source_fds[i] != target_fds[i]) +- source_fds[i] = dupfd_cloexec (source_fds[i]); ++ source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1); + } ++ + for (i = 0; i < n_fds; i++) + { ++ /* For basic fd assignments (where source == target), we can just ++ * unset FD_CLOEXEC. ++ */ + if (source_fds[i] == target_fds[i]) + { + unset_cloexec (source_fds[i]); + } + else + { ++ /* If any of the @target_fds conflict with @child_err_report_fd, ++ * dup it so it doesn’t get conflated. ++ */ + if (target_fds[i] == child_err_report_fd) +- child_err_report_fd = dupfd_cloexec (child_err_report_fd); ++ child_err_report_fd = dupfd_cloexec (child_err_report_fd, max_target_fd + 1); + + safe_dup2 (source_fds[i], target_fds[i]); + close_and_invalidate (&source_fds[i]); +-- +2.33.1 + +From ecc3538a942760e8b403c319d359711c8e166778 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Thu, 25 Feb 2021 12:20:39 -0600 +Subject: [PATCH 05/10] gspawn: Implement fd remapping for posix_spawn codepath + +This means that GSubprocess will (sometimes) be able to use the +optimized posix_spawn codepath instead of having to fall back to +fork/exec. +--- + glib/gspawn.c | 65 +++++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 58 insertions(+), 7 deletions(-) + +diff --git a/glib/gspawn.c b/glib/gspawn.c +index 2b48b5600..9ef78dbe1 100644 +--- a/glib/gspawn.c ++++ b/glib/gspawn.c +@@ -1786,9 +1786,14 @@ do_posix_spawn (const gchar * const *argv, + gint *child_close_fds, + gint stdin_fd, + gint stdout_fd, +- gint stderr_fd) ++ gint stderr_fd, ++ const gint *source_fds, ++ const gint *target_fds, ++ gsize n_fds) + { + pid_t pid; ++ gint *duped_source_fds = NULL; ++ gint max_target_fd = 0; + const gchar * const *argv_pass; + posix_spawnattr_t attr; + posix_spawn_file_actions_t file_actions; +@@ -1797,7 +1802,8 @@ do_posix_spawn (const gchar * const *argv, + GSList *child_close = NULL; + GSList *elem; + sigset_t mask; +- int i, r; ++ size_t i; ++ int r; + + if (*argv[0] == '\0') + { +@@ -1911,6 +1917,43 @@ do_posix_spawn (const gchar * const *argv, + goto out_close_fds; + } + ++ /* If source_fds[i] != target_fds[i], we need to handle the case ++ * where the user has specified, e.g., 5 -> 4, 4 -> 6. We do this ++ * by duping the source fds, taking care to ensure the new fds are ++ * larger than any target fd to avoid introducing new conflicts. ++ * ++ * If source_fds[i] == target_fds[i], then we just need to leak ++ * the fd into the child process, which we *could* do by temporarily ++ * unsetting CLOEXEC and then setting it again after we spawn if ++ * it was originally set. POSIX requires that the addup2 action unset ++ * CLOEXEC if source and target are identical, so you'd think doing it ++ * manually wouldn't be needed, but unfortunately as of 2021 many ++ * libcs still don't do so. Example nonconforming libcs: ++ * Bionic: https://android.googlesource.com/platform/bionic/+/f6e5b582604715729b09db3e36a7aeb8c24b36a4/libc/bionic/spawn.cpp#71 ++ * uclibc-ng: https://cgit.uclibc-ng.org/cgi/cgit/uclibc-ng.git/tree/librt/spawn.c?id=7c36bcae09d66bbaa35cbb02253ae0556f42677e#n88 ++ * ++ * Anyway, unsetting CLOEXEC ourselves would open a small race window ++ * where the fd could be inherited into a child process if another ++ * thread spawns something at the same time, because we have not ++ * called fork() and are multithreaded here. This race is avoidable by ++ * using dupfd_cloexec, which we already have to do to handle the ++ * source_fds[i] != target_fds[i] case. So let's always do it! ++ */ ++ ++ for (i = 0; i < n_fds; i++) ++ max_target_fd = MAX (max_target_fd, target_fds[i]); ++ ++ duped_source_fds = g_new (gint, n_fds); ++ for (i = 0; i < n_fds; i++) ++ duped_source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1); ++ ++ for (i = 0; i < n_fds; i++) ++ { ++ r = posix_spawn_file_actions_adddup2 (&file_actions, duped_source_fds[i], target_fds[i]); ++ if (r != 0) ++ goto out_close_fds; ++ } ++ + /* Intentionally close the fds in the child as the last file action, + * having been careful not to add the same fd to this list twice. + * +@@ -1940,9 +1983,16 @@ do_posix_spawn (const gchar * const *argv, + *child_pid = pid; + + out_close_fds: +- for (i = 0; i < num_parent_close_fds; i++) ++ for (i = 0; i < (size_t) num_parent_close_fds; i++) + close_and_invalidate (&parent_close_fds [i]); + ++ if (duped_source_fds != NULL) ++ { ++ for (i = 0; i < n_fds; i++) ++ close_and_invalidate (&duped_source_fds[i]); ++ g_free (duped_source_fds); ++ } ++ + posix_spawn_file_actions_destroy (&file_actions); + out_free_spawnattr: + posix_spawnattr_destroy (&attr); +@@ -2030,10 +2080,8 @@ fork_exec (gboolean intermediate_child, + child_close_fds[n_child_close_fds++] = -1; + + #ifdef POSIX_SPAWN_AVAILABLE +- /* FIXME: Handle @source_fds and @target_fds in do_posix_spawn() using the +- * file actions API. */ + if (!intermediate_child && working_directory == NULL && !close_descriptors && +- !search_path_from_envp && child_setup == NULL && n_fds == 0) ++ !search_path_from_envp && child_setup == NULL) + { + g_trace_mark (G_TRACE_CURRENT_TIME, 0, + "GLib", "posix_spawn", +@@ -2050,7 +2098,10 @@ fork_exec (gboolean intermediate_child, + child_close_fds, + stdin_fd, + stdout_fd, +- stderr_fd); ++ stderr_fd, ++ source_fds, ++ target_fds, ++ n_fds); + if (status == 0) + goto success; + +-- +2.33.1 + +From 731d6c32105dc97f2b777ef9a34c6b76d1489c04 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Thu, 25 Feb 2021 12:21:38 -0600 +Subject: [PATCH 06/10] gsubprocess: ensure we test fd remapping on the + posix_spawn() codepath + +We should run test_pass_fd twice, once using gspawn's fork/exec codepath +and once attempting to use its posix_spawn() codepath. There's no +guarantee we'll actually get the posix_spawn() codepath, but it works +for now on Linux. + +For good measure, run it a third time with no flags at all. + +This causes the test to fail if I separately break the fd remapping +implementation. Without this, we fail to test fd remapping on the +posix_spawn() codepath. +--- + gio/tests/gsubprocess.c | 44 ++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 41 insertions(+), 3 deletions(-) + +diff --git a/gio/tests/gsubprocess.c b/gio/tests/gsubprocess.c +index 7e22678ec..ba49c1c43 100644 +--- a/gio/tests/gsubprocess.c ++++ b/gio/tests/gsubprocess.c +@@ -1697,7 +1697,8 @@ test_child_setup (void) + } + + static void +-test_pass_fd (void) ++do_test_pass_fd (GSubprocessFlags flags, ++ GSpawnChildSetupFunc child_setup) + { + GError *local_error = NULL; + GError **error = &local_error; +@@ -1722,9 +1723,11 @@ test_pass_fd (void) + needdup_fd_str = g_strdup_printf ("%d", needdup_pipefds[1] + 1); + + args = get_test_subprocess_args ("write-to-fds", basic_fd_str, needdup_fd_str, NULL); +- launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE); ++ launcher = g_subprocess_launcher_new (flags); + g_subprocess_launcher_take_fd (launcher, basic_pipefds[1], basic_pipefds[1]); + g_subprocess_launcher_take_fd (launcher, needdup_pipefds[1], needdup_pipefds[1] + 1); ++ if (child_setup != NULL) ++ g_subprocess_launcher_set_child_setup (launcher, child_setup, NULL, NULL); + proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error); + g_ptr_array_free (args, TRUE); + g_assert_no_error (local_error); +@@ -1754,6 +1757,39 @@ test_pass_fd (void) + g_object_unref (proc); + } + ++static void ++test_pass_fd (void) ++{ ++ do_test_pass_fd (G_SUBPROCESS_FLAGS_NONE, NULL); ++} ++ ++static void ++empty_child_setup (gpointer user_data) ++{ ++} ++ ++static void ++test_pass_fd_empty_child_setup (void) ++{ ++ /* Using a child setup function forces gspawn to use fork/exec ++ * rather than posix_spawn. ++ */ ++ do_test_pass_fd (G_SUBPROCESS_FLAGS_NONE, empty_child_setup); ++} ++ ++static void ++test_pass_fd_inherit_fds (void) ++{ ++ /* Try to test the optimized posix_spawn codepath instead of ++ * fork/exec. Currently this requires using INHERIT_FDS since gspawn's ++ * posix_spawn codepath does not currently handle closing ++ * non-inherited fds. Note that using INHERIT_FDS means our testing of ++ * g_subprocess_launcher_take_fd() is less-comprehensive than when ++ * using G_SUBPROCESS_FLAGS_NONE. ++ */ ++ do_test_pass_fd (G_SUBPROCESS_FLAGS_INHERIT_FDS, NULL); ++} ++ + #endif + + static void +@@ -1891,7 +1927,9 @@ main (int argc, char **argv) + g_test_add_func ("/gsubprocess/stdout-file", test_stdout_file); + g_test_add_func ("/gsubprocess/stdout-fd", test_stdout_fd); + g_test_add_func ("/gsubprocess/child-setup", test_child_setup); +- g_test_add_func ("/gsubprocess/pass-fd", test_pass_fd); ++ g_test_add_func ("/gsubprocess/pass-fd/basic", test_pass_fd); ++ g_test_add_func ("/gsubprocess/pass-fd/empty-child-setup", test_pass_fd_empty_child_setup); ++ g_test_add_func ("/gsubprocess/pass-fd/inherit-fds", test_pass_fd_inherit_fds); + #endif + g_test_add_func ("/gsubprocess/launcher-environment", test_launcher_environment); + +-- +2.33.1 + +From 4608940466a04a32d4e6e71dbe872cfecb136118 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Thu, 14 Oct 2021 11:01:33 -0500 +Subject: [PATCH 07/10] gspawn: Check from errors from safe_dup2() and + dupfd_cloexec() + +Although unlikely, these functions can fail, e.g. if we run out of file +descriptors. Check for errors to improve robustness. This is especially +important now that I changed our use of dupfd_cloexec() to avoid +returning fds smaller than the largest fd in target_fds. An application +that attempts to remap to the highest-allowed fd value deserves at least +some sort of attempt at error reporting, not silent failure. +--- + glib/gspawn.c | 40 +++++++++++++++++++++++++++++----------- + 1 file changed, 29 insertions(+), 11 deletions(-) + +diff --git a/glib/gspawn.c b/glib/gspawn.c +index 9ef78dbe1..7ef678047 100644 +--- a/glib/gspawn.c ++++ b/glib/gspawn.c +@@ -1572,7 +1572,6 @@ do_exec (gint child_err_report_fd, + /* Redirect pipes as required */ + if (stdin_fd >= 0) + { +- /* dup2 can't actually fail here I don't think */ + if (safe_dup2 (stdin_fd, 0) < 0) + write_err_and_exit (child_err_report_fd, + CHILD_DUP2_FAILED); +@@ -1588,13 +1587,14 @@ do_exec (gint child_err_report_fd, + if (read_null < 0) + write_err_and_exit (child_err_report_fd, + CHILD_DUP2_FAILED); +- safe_dup2 (read_null, 0); ++ if (safe_dup2 (read_null, 0) < 0) ++ write_err_and_exit (child_err_report_fd, ++ CHILD_DUP2_FAILED); + close_and_invalidate (&read_null); + } + + if (stdout_fd >= 0) + { +- /* dup2 can't actually fail here I don't think */ + if (safe_dup2 (stdout_fd, 1) < 0) + write_err_and_exit (child_err_report_fd, + CHILD_DUP2_FAILED); +@@ -1609,13 +1609,14 @@ do_exec (gint child_err_report_fd, + if (write_null < 0) + write_err_and_exit (child_err_report_fd, + CHILD_DUP2_FAILED); +- safe_dup2 (write_null, 1); ++ if (safe_dup2 (write_null, 1) < 0) ++ write_err_and_exit (child_err_report_fd, ++ CHILD_DUP2_FAILED); + close_and_invalidate (&write_null); + } + + if (stderr_fd >= 0) + { +- /* dup2 can't actually fail here I don't think */ + if (safe_dup2 (stderr_fd, 2) < 0) + write_err_and_exit (child_err_report_fd, + CHILD_DUP2_FAILED); +@@ -1630,7 +1631,9 @@ do_exec (gint child_err_report_fd, + if (write_null < 0) + write_err_and_exit (child_err_report_fd, + CHILD_DUP2_FAILED); +- safe_dup2 (write_null, 2); ++ if (safe_dup2 (write_null, 2) < 0) ++ write_err_and_exit (child_err_report_fd, ++ CHILD_DUP2_FAILED); + close_and_invalidate (&write_null); + } + +@@ -1643,7 +1646,8 @@ do_exec (gint child_err_report_fd, + { + if (child_setup == NULL && n_fds == 0) + { +- safe_dup2 (child_err_report_fd, 3); ++ if (safe_dup2 (child_err_report_fd, 3) < 0) ++ write_err_and_exit (child_err_report_fd, CHILD_DUP2_FAILED); + set_cloexec (GINT_TO_POINTER (0), 3); + safe_closefrom (4); + child_err_report_fd = 3; +@@ -1682,7 +1686,11 @@ do_exec (gint child_err_report_fd, + for (i = 0; i < n_fds; i++) + { + if (source_fds[i] != target_fds[i]) +- source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1); ++ { ++ source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1); ++ if (source_fds[i] < 0) ++ write_err_and_exit (child_err_report_fd, CHILD_DUP2_FAILED); ++ } + } + + for (i = 0; i < n_fds; i++) +@@ -1700,9 +1708,15 @@ do_exec (gint child_err_report_fd, + * dup it so it doesn’t get conflated. + */ + if (target_fds[i] == child_err_report_fd) +- child_err_report_fd = dupfd_cloexec (child_err_report_fd, max_target_fd + 1); ++ { ++ child_err_report_fd = dupfd_cloexec (child_err_report_fd, max_target_fd + 1); ++ if (child_err_report_fd < 0) ++ write_err_and_exit (child_err_report_fd, CHILD_DUP2_FAILED); ++ } ++ ++ if (safe_dup2 (source_fds[i], target_fds[i]) < 0) ++ write_err_and_exit (child_err_report_fd, CHILD_DUP2_FAILED); + +- safe_dup2 (source_fds[i], target_fds[i]); + close_and_invalidate (&source_fds[i]); + } + } +@@ -1945,7 +1959,11 @@ do_posix_spawn (const gchar * const *argv, + + duped_source_fds = g_new (gint, n_fds); + for (i = 0; i < n_fds; i++) +- duped_source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1); ++ { ++ duped_source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1); ++ if (duped_source_fds[i] < 0) ++ goto out_close_fds; ++ } + + for (i = 0; i < n_fds; i++) + { +-- +2.33.1 + +From 0198b6a1c8c215f524d7c6ed2d240fb1b31d9865 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Wed, 20 Oct 2021 16:51:44 -0500 +Subject: [PATCH 08/10] gspawn: add new error message for open() failures + +Reporting these as dup2() failures is bogus. +--- + glib/gspawn.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/glib/gspawn.c b/glib/gspawn.c +index 7ef678047..c2fe306dc 100644 +--- a/glib/gspawn.c ++++ b/glib/gspawn.c +@@ -1532,6 +1532,7 @@ enum + { + CHILD_CHDIR_FAILED, + CHILD_EXEC_FAILED, ++ CHILD_OPEN_FAILED, + CHILD_DUP2_FAILED, + CHILD_FORK_FAILED + }; +@@ -1586,7 +1587,7 @@ do_exec (gint child_err_report_fd, + gint read_null = safe_open ("/dev/null", O_RDONLY); + if (read_null < 0) + write_err_and_exit (child_err_report_fd, +- CHILD_DUP2_FAILED); ++ CHILD_OPEN_FAILED); + if (safe_dup2 (read_null, 0) < 0) + write_err_and_exit (child_err_report_fd, + CHILD_DUP2_FAILED); +@@ -1608,7 +1609,7 @@ do_exec (gint child_err_report_fd, + gint write_null = safe_open ("/dev/null", O_WRONLY); + if (write_null < 0) + write_err_and_exit (child_err_report_fd, +- CHILD_DUP2_FAILED); ++ CHILD_OPEN_FAILED); + if (safe_dup2 (write_null, 1) < 0) + write_err_and_exit (child_err_report_fd, + CHILD_DUP2_FAILED); +@@ -1630,7 +1631,7 @@ do_exec (gint child_err_report_fd, + gint write_null = safe_open ("/dev/null", O_WRONLY); + if (write_null < 0) + write_err_and_exit (child_err_report_fd, +- CHILD_DUP2_FAILED); ++ CHILD_OPEN_FAILED); + if (safe_dup2 (write_null, 2) < 0) + write_err_and_exit (child_err_report_fd, + CHILD_DUP2_FAILED); +@@ -2420,7 +2421,15 @@ fork_exec (gboolean intermediate_child, + g_strerror (buf[1])); + + break; +- ++ ++ case CHILD_OPEN_FAILED: ++ g_set_error (error, ++ G_SPAWN_ERROR, ++ G_SPAWN_ERROR_FAILED, ++ _("Failed to open file to remap file descriptor (%s)"), ++ g_strerror (buf[1])); ++ break; ++ + case CHILD_DUP2_FAILED: + g_set_error (error, + G_SPAWN_ERROR, +-- +2.33.1 + +From e4abb5f3db85b2f730e192e6398f26934e41ba21 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Tue, 26 Oct 2021 21:27:15 -0500 +Subject: [PATCH 09/10] Add tests for GSubprocess fd conflation issues + +This tests for #2503. It's fragile, but there is no non-fragile way to +test this. If the test breaks in the future, it will pass without +successfully testing the bug, not fail spuriously, so I think this is +OK. +--- + gio/tests/gsubprocess-testprog.c | 53 +++++++++++- + gio/tests/gsubprocess.c | 144 +++++++++++++++++++++++++++++++ + 2 files changed, 195 insertions(+), 2 deletions(-) + +diff --git a/gio/tests/gsubprocess-testprog.c b/gio/tests/gsubprocess-testprog.c +index c9b06c2a2..58cb1c71d 100644 +--- a/gio/tests/gsubprocess-testprog.c ++++ b/gio/tests/gsubprocess-testprog.c +@@ -5,8 +5,6 @@ + #include + #ifdef G_OS_UNIX + #include +-#include +-#include + #else + #include + #endif +@@ -150,6 +148,55 @@ write_to_fds (int argc, char **argv) + return 0; + } + ++static int ++read_from_fd (int argc, char **argv) ++{ ++ int fd; ++ const char expectedResult[] = "Yay success!"; ++ guint8 buf[sizeof (expectedResult) + 1]; ++ gsize bytes_read; ++ FILE *f; ++ ++ if (argc != 3) ++ { ++ g_print ("Usage: %s read-from-fd FD\n", argv[0]); ++ return 1; ++ } ++ ++ fd = atoi (argv[2]); ++ if (fd == 0) ++ { ++ g_warning ("Argument \"%s\" does not look like a valid nonzero file descriptor", argv[2]); ++ return 1; ++ } ++ ++ f = fdopen (fd, "r"); ++ if (f == NULL) ++ { ++ g_warning ("Failed to open fd %d: %s", fd, g_strerror (errno)); ++ return 1; ++ } ++ ++ bytes_read = fread (buf, 1, sizeof (buf), f); ++ if (bytes_read != sizeof (expectedResult)) ++ { ++ g_warning ("Read %zu bytes, but expected %zu", bytes_read, sizeof (expectedResult)); ++ return 1; ++ } ++ ++ if (memcmp (expectedResult, buf, sizeof (expectedResult)) != 0) ++ { ++ buf[sizeof (expectedResult)] = '\0'; ++ g_warning ("Expected \"%s\" but read \"%s\"", expectedResult, (char *)buf); ++ return 1; ++ } ++ ++ if (fclose (f) == -1) ++ g_assert_not_reached (); ++ ++ return 0; ++} ++ + static int + env_mode (int argc, char **argv) + { +@@ -242,6 +289,8 @@ main (int argc, char **argv) + return sleep_forever_mode (argc, argv); + else if (strcmp (mode, "write-to-fds") == 0) + return write_to_fds (argc, argv); ++ else if (strcmp (mode, "read-from-fd") == 0) ++ return read_from_fd (argc, argv); + else if (strcmp (mode, "env") == 0) + return env_mode (argc, argv); + else if (strcmp (mode, "cwd") == 0) +diff --git a/gio/tests/gsubprocess.c b/gio/tests/gsubprocess.c +index ba49c1c43..a6e24c2e8 100644 +--- a/gio/tests/gsubprocess.c ++++ b/gio/tests/gsubprocess.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1790,6 +1791,146 @@ test_pass_fd_inherit_fds (void) + do_test_pass_fd (G_SUBPROCESS_FLAGS_INHERIT_FDS, NULL); + } + ++static void ++do_test_fd_conflation (GSubprocessFlags flags, ++ GSpawnChildSetupFunc child_setup) ++{ ++ char success_message[] = "Yay success!"; ++ GError *error = NULL; ++ GOutputStream *output_stream; ++ GSubprocessLauncher *launcher; ++ GSubprocess *proc; ++ GPtrArray *args; ++ int unused_pipefds[2]; ++ int pipefds[2]; ++ gsize bytes_written; ++ gboolean success; ++ char *fd_str; ++ ++ /* This test must run in a new process because it is extremely sensitive to ++ * order of opened fds. ++ */ ++ if (!g_test_subprocess ()) ++ { ++ g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_INHERIT_STDOUT | G_TEST_SUBPROCESS_INHERIT_STDERR); ++ g_test_trap_assert_passed (); ++ return; ++ } ++ ++ g_unix_open_pipe (unused_pipefds, FD_CLOEXEC, &error); ++ g_assert_no_error (error); ++ ++ g_unix_open_pipe (pipefds, FD_CLOEXEC, &error); ++ g_assert_no_error (error); ++ ++ /* The fds should be sequential since we are in a new process. */ ++ g_assert_cmpint (unused_pipefds[0] /* 3 */, ==, unused_pipefds[1] - 1); ++ g_assert_cmpint (unused_pipefds[1] /* 4 */, ==, pipefds[0] - 1); ++ g_assert_cmpint (pipefds[0] /* 5 */, ==, pipefds[1] /* 6 */ - 1); ++ ++ /* Because GSubprocess allows arbitrary remapping of fds, it has to be careful ++ * to avoid fd conflation issues, e.g. it should properly handle 5 -> 4 and ++ * 4 -> 5 at the same time. GIO previously attempted to handle this by naively ++ * dup'ing the source fds, but this was not good enough because it was ++ * possible that the dup'ed result could still conflict with one of the target ++ * fds. For example: ++ * ++ * source_fd 5 -> target_fd 9, source_fd 3 -> target_fd 7 ++ * ++ * dup(5) -> dup returns 8 ++ * dup(3) -> dup returns 9 ++ * ++ * After dup'ing, we wind up with: 8 -> 9, 9 -> 7. That means that after we ++ * dup2(8, 9), we have clobbered fd 9 before we dup2(9, 7). The end result is ++ * we have remapped 5 -> 9 as expected, but then remapped 5 -> 7 instead of ++ * 3 -> 7 as the application intended. ++ * ++ * This issue has been fixed in the simplest way possible, by passing a ++ * minimum fd value when using F_DUPFD_CLOEXEC that is higher than any of the ++ * target fds, to guarantee all source fds are different than all target fds, ++ * eliminating any possibility of conflation. ++ * ++ * Anyway, that is why we have the unused_pipefds here. We need to open fds in ++ * a certain order in order to trick older GSubprocess into conflating the ++ * fds. The primary goal of this test is to ensure this particular conflation ++ * issue is not reintroduced. See glib#2503. ++ * ++ * Be aware this test is necessarily extremely fragile. To reproduce these ++ * bugs, it relies on internals of gspawn and gmain that will likely change ++ * in the future, eventually causing this test to no longer test the the bugs ++ * it was originally designed to test. That is OK! If the test fails, at ++ * least you know *something* is wrong. ++ */ ++ launcher = g_subprocess_launcher_new (flags); ++ g_subprocess_launcher_take_fd (launcher, pipefds[0] /* 5 */, pipefds[1] + 3 /* 9 */); ++ g_subprocess_launcher_take_fd (launcher, unused_pipefds[0] /* 3 */, pipefds[1] + 1 /* 7 */); ++ if (child_setup != NULL) ++ g_subprocess_launcher_set_child_setup (launcher, child_setup, NULL, NULL); ++ fd_str = g_strdup_printf ("%d", pipefds[1] + 3); ++ args = get_test_subprocess_args ("read-from-fd", fd_str, NULL); ++ proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, &error); ++ g_assert_no_error (error); ++ g_assert_nonnull (proc); ++ g_ptr_array_free (args, TRUE); ++ g_object_unref (launcher); ++ g_free (fd_str); ++ ++ /* Close the read ends of the pipes. */ ++ close (unused_pipefds[0]); ++ close (pipefds[0]); ++ ++ /* Also close the write end of the unused pipe. */ ++ close (unused_pipefds[1]); ++ ++ /* So now pipefds[0] should be inherited into the subprocess as ++ * pipefds[1] + 2, and unused_pipefds[0] should be inherited as ++ * pipefds[1] + 1. We will write to pipefds[1] and the subprocess will verify ++ * that it reads the expected data. But older broken GIO will accidentally ++ * clobber pipefds[1] + 2 with pipefds[1] + 1! This will cause the subprocess ++ * to hang trying to read from the wrong pipe. ++ */ ++ output_stream = g_unix_output_stream_new (pipefds[1], TRUE); ++ success = g_output_stream_write_all (output_stream, ++ success_message, sizeof (success_message), ++ &bytes_written, ++ NULL, ++ &error); ++ g_assert_no_error (error); ++ g_assert_cmpint (bytes_written, ==, sizeof (success_message)); ++ g_assert_true (success); ++ g_object_unref (output_stream); ++ ++ success = g_subprocess_wait_check (proc, NULL, &error); ++ g_assert_no_error (error); ++ g_object_unref (proc); ++} ++ ++static void ++test_fd_conflation (void) ++{ ++ do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, NULL); ++} ++ ++static void ++test_fd_conflation_empty_child_setup (void) ++{ ++ /* Using a child setup function forces gspawn to use fork/exec ++ * rather than posix_spawn. ++ */ ++ do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, empty_child_setup); ++} ++ ++static void ++test_fd_conflation_inherit_fds (void) ++{ ++ /* Try to test the optimized posix_spawn codepath instead of ++ * fork/exec. Currently this requires using INHERIT_FDS since gspawn's ++ * posix_spawn codepath does not currently handle closing ++ * non-inherited fds. ++ */ ++ do_test_fd_conflation (G_SUBPROCESS_FLAGS_INHERIT_FDS, NULL); ++} ++ + #endif + + static void +@@ -1930,6 +2071,9 @@ main (int argc, char **argv) + g_test_add_func ("/gsubprocess/pass-fd/basic", test_pass_fd); + g_test_add_func ("/gsubprocess/pass-fd/empty-child-setup", test_pass_fd_empty_child_setup); + g_test_add_func ("/gsubprocess/pass-fd/inherit-fds", test_pass_fd_inherit_fds); ++ g_test_add_func ("/gsubprocess/fd-conflation/basic", test_fd_conflation); ++ g_test_add_func ("/gsubprocess/fd-conflation/empty-child-setup", test_fd_conflation_empty_child_setup); ++ g_test_add_func ("/gsubprocess/fd-conflation/inherit-fds", test_fd_conflation_inherit_fds); + #endif + g_test_add_func ("/gsubprocess/launcher-environment", test_launcher_environment); + +-- +2.33.1 + +From 5542612c805857a244561ec160e904dd302ae799 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Wed, 27 Oct 2021 18:30:47 -0500 +Subject: [PATCH 10/10] Add test for child_err_report_fd conflation with target + fds + +This tests for glib#2506. +--- + gio/tests/gsubprocess.c | 42 ++++++++++++++++++++++++++++++++++------- + 1 file changed, 35 insertions(+), 7 deletions(-) + +diff --git a/gio/tests/gsubprocess.c b/gio/tests/gsubprocess.c +index a6e24c2e8..4629cdea7 100644 +--- a/gio/tests/gsubprocess.c ++++ b/gio/tests/gsubprocess.c +@@ -1793,7 +1793,8 @@ test_pass_fd_inherit_fds (void) + + static void + do_test_fd_conflation (GSubprocessFlags flags, +- GSpawnChildSetupFunc child_setup) ++ GSpawnChildSetupFunc child_setup, ++ gboolean test_child_err_report_fd) + { + char success_message[] = "Yay success!"; + GError *error = NULL; +@@ -1803,6 +1804,7 @@ do_test_fd_conflation (GSubprocessFlags flags, + GPtrArray *args; + int unused_pipefds[2]; + int pipefds[2]; ++ int fd_to_pass_to_child; + gsize bytes_written; + gboolean success; + char *fd_str; +@@ -1855,18 +1857,26 @@ do_test_fd_conflation (GSubprocessFlags flags, + * fds. The primary goal of this test is to ensure this particular conflation + * issue is not reintroduced. See glib#2503. + * ++ * This test also has an alternate mode of operation where it instead tests ++ * for conflation with gspawn's child_err_report_fd, glib#2506. ++ * + * Be aware this test is necessarily extremely fragile. To reproduce these + * bugs, it relies on internals of gspawn and gmain that will likely change + * in the future, eventually causing this test to no longer test the the bugs + * it was originally designed to test. That is OK! If the test fails, at + * least you know *something* is wrong. + */ ++ if (test_child_err_report_fd) ++ fd_to_pass_to_child = pipefds[1] + 2 /* 8 */; ++ else ++ fd_to_pass_to_child = pipefds[1] + 3 /* 9 */; ++ + launcher = g_subprocess_launcher_new (flags); +- g_subprocess_launcher_take_fd (launcher, pipefds[0] /* 5 */, pipefds[1] + 3 /* 9 */); ++ g_subprocess_launcher_take_fd (launcher, pipefds[0] /* 5 */, fd_to_pass_to_child); + g_subprocess_launcher_take_fd (launcher, unused_pipefds[0] /* 3 */, pipefds[1] + 1 /* 7 */); + if (child_setup != NULL) + g_subprocess_launcher_set_child_setup (launcher, child_setup, NULL, NULL); +- fd_str = g_strdup_printf ("%d", pipefds[1] + 3); ++ fd_str = g_strdup_printf ("%d", fd_to_pass_to_child); + args = get_test_subprocess_args ("read-from-fd", fd_str, NULL); + proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, &error); + g_assert_no_error (error); +@@ -1882,12 +1892,20 @@ do_test_fd_conflation (GSubprocessFlags flags, + /* Also close the write end of the unused pipe. */ + close (unused_pipefds[1]); + +- /* So now pipefds[0] should be inherited into the subprocess as ++ /* If doing our normal test: ++ * ++ * So now pipefds[0] should be inherited into the subprocess as + * pipefds[1] + 2, and unused_pipefds[0] should be inherited as + * pipefds[1] + 1. We will write to pipefds[1] and the subprocess will verify + * that it reads the expected data. But older broken GIO will accidentally + * clobber pipefds[1] + 2 with pipefds[1] + 1! This will cause the subprocess + * to hang trying to read from the wrong pipe. ++ * ++ * If testing conflation with child_err_report_fd: ++ * ++ * We are actually already done. The real test succeeded if we made it this ++ * far without hanging while spawning the child. But let's continue with our ++ * write and read anyway, to ensure things are good. + */ + output_stream = g_unix_output_stream_new (pipefds[1], TRUE); + success = g_output_stream_write_all (output_stream, +@@ -1908,7 +1926,7 @@ do_test_fd_conflation (GSubprocessFlags flags, + static void + test_fd_conflation (void) + { +- do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, NULL); ++ do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, NULL, FALSE); + } + + static void +@@ -1917,7 +1935,7 @@ test_fd_conflation_empty_child_setup (void) + /* Using a child setup function forces gspawn to use fork/exec + * rather than posix_spawn. + */ +- do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, empty_child_setup); ++ do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, empty_child_setup, FALSE); + } + + static void +@@ -1928,7 +1946,16 @@ test_fd_conflation_inherit_fds (void) + * posix_spawn codepath does not currently handle closing + * non-inherited fds. + */ +- do_test_fd_conflation (G_SUBPROCESS_FLAGS_INHERIT_FDS, NULL); ++ do_test_fd_conflation (G_SUBPROCESS_FLAGS_INHERIT_FDS, NULL, FALSE); ++} ++ ++static void ++test_fd_conflation_child_err_report_fd (void) ++{ ++ /* Using a child setup function forces gspawn to use fork/exec ++ * rather than posix_spawn. ++ */ ++ do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, empty_child_setup, TRUE); + } + + #endif +@@ -2074,6 +2101,7 @@ main (int argc, char **argv) + g_test_add_func ("/gsubprocess/fd-conflation/basic", test_fd_conflation); + g_test_add_func ("/gsubprocess/fd-conflation/empty-child-setup", test_fd_conflation_empty_child_setup); + g_test_add_func ("/gsubprocess/fd-conflation/inherit-fds", test_fd_conflation_inherit_fds); ++ g_test_add_func ("/gsubprocess/fd-conflation/child-err-report-fd", test_fd_conflation_child_err_report_fd); + #endif + g_test_add_func ("/gsubprocess/launcher-environment", test_launcher_environment); + +-- +2.33.1 + diff --git a/2194.patch b/2194.patch new file mode 100644 index 0000000000000000000000000000000000000000..5c9aaf2ea195a58baf8335db0c9ab500d4c6f523 --- /dev/null +++ b/2194.patch @@ -0,0 +1,920 @@ +From 2e500304e304e45042a59855319ff0379b1978b3 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Tue, 27 Jul 2021 17:24:17 +0200 +Subject: [PATCH 1/4] tests: Remove unused constant in GMemoryMonitor test + +--- + gio/tests/memory-monitor-dbus.py.in | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/gio/tests/memory-monitor-dbus.py.in b/gio/tests/memory-monitor-dbus.py.in +index cd16cf4e3..7823e7309 100755 +--- a/gio/tests/memory-monitor-dbus.py.in ++++ b/gio/tests/memory-monitor-dbus.py.in +@@ -31,9 +31,6 @@ try: + + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + +- # XDG_DESKTOP_PORTAL_PATH = os.path.expanduser("~/.cache/jhbuild/build/xdg-desktop-portal/xdg-desktop-portal") +- XDG_DESKTOP_PORTAL_PATH = "@libexecdir@/xdg-desktop-portal" +- + class TestLowMemoryMonitor(dbusmock.DBusTestCase): + '''Test GMemoryMonitorDBus''' + +-- +GitLab + + +From a7000cd989438b01e599b2cfa8b6d5a360bfd102 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Wed, 28 Jul 2021 15:10:16 +0200 +Subject: [PATCH 2/4] gio: g_clear_signal_handler() can handle NULL args + +--- + gio/gmemorymonitordbus.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/gio/gmemorymonitordbus.c b/gio/gmemorymonitordbus.c +index a34a58d3b..08dc53df1 100644 +--- a/gio/gmemorymonitordbus.c ++++ b/gio/gmemorymonitordbus.c +@@ -115,8 +115,7 @@ lmm_vanished_cb (GDBusConnection *connection, + { + GMemoryMonitorDBus *dbus = user_data; + +- if (dbus->proxy != NULL) +- g_clear_signal_handler (&dbus->signal_id, dbus->proxy); ++ g_clear_signal_handler (&dbus->signal_id, dbus->proxy); + g_clear_object (&dbus->proxy); + } + +@@ -143,8 +142,7 @@ g_memory_monitor_dbus_finalize (GObject *object) + { + GMemoryMonitorDBus *dbus = G_MEMORY_MONITOR_DBUS (object); + +- if (dbus->proxy != NULL) +- g_clear_signal_handler (&dbus->signal_id, dbus->proxy); ++ g_clear_signal_handler (&dbus->signal_id, dbus->proxy); + g_clear_object (&dbus->proxy); + g_clear_handle_id (&dbus->watch_id, g_bus_unwatch_name); + +-- +GitLab + + +From 92399e7114e590f0371b1a5d71f478f840cb4074 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Wed, 28 Jul 2021 15:30:15 +0200 +Subject: [PATCH 3/4] gio: Do not block when low-memory-monitor daemon appears + +--- + gio/gmemorymonitordbus.c | 42 +++++++++++++++++++++++++++------------- + 1 file changed, 29 insertions(+), 13 deletions(-) + +diff --git a/gio/gmemorymonitordbus.c b/gio/gmemorymonitordbus.c +index 08dc53df1..739b83214 100644 +--- a/gio/gmemorymonitordbus.c ++++ b/gio/gmemorymonitordbus.c +@@ -25,6 +25,7 @@ + #include "giomodule-priv.h" + #include "glibintl.h" + #include "glib/gstdio.h" ++#include "gcancellable.h" + #include "gdbusproxy.h" + #include "gdbusnamewatching.h" + +@@ -38,6 +39,7 @@ struct _GMemoryMonitorDBus + GObject parent_instance; + + guint watch_id; ++ GCancellable *cancellable; + GDBusProxy *proxy; + gulong signal_id; + }; +@@ -77,24 +79,15 @@ proxy_signal_cb (GDBusProxy *proxy, + } + + static void +-lmm_appeared_cb (GDBusConnection *connection, +- const gchar *name, +- const gchar *name_owner, +- gpointer user_data) ++lmm_proxy_cb (GObject *source_object, ++ GAsyncResult *res, ++ gpointer user_data) + { + GMemoryMonitorDBus *dbus = user_data; + GDBusProxy *proxy; + GError *error = NULL; + +- proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, +- G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, +- NULL, +- "org.freedesktop.LowMemoryMonitor", +- "/org/freedesktop/LowMemoryMonitor", +- "org.freedesktop.LowMemoryMonitor", +- NULL, +- &error); +- ++ proxy = g_dbus_proxy_new_finish (res, &error); + if (!proxy) + { + g_debug ("Failed to create LowMemoryMonitor D-Bus proxy: %s", +@@ -106,6 +99,26 @@ lmm_appeared_cb (GDBusConnection *connection, + dbus->signal_id = g_signal_connect (G_OBJECT (proxy), "g-signal", + G_CALLBACK (proxy_signal_cb), dbus); + dbus->proxy = proxy; ++ ++} ++ ++static void ++lmm_appeared_cb (GDBusConnection *connection, ++ const gchar *name, ++ const gchar *name_owner, ++ gpointer user_data) ++{ ++ GMemoryMonitorDBus *dbus = user_data; ++ ++ g_dbus_proxy_new (connection, ++ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, ++ NULL, ++ "org.freedesktop.LowMemoryMonitor", ++ "/org/freedesktop/LowMemoryMonitor", ++ "org.freedesktop.LowMemoryMonitor", ++ dbus->cancellable, ++ lmm_proxy_cb, ++ dbus); + } + + static void +@@ -126,6 +139,7 @@ g_memory_monitor_dbus_initable_init (GInitable *initable, + { + GMemoryMonitorDBus *dbus = G_MEMORY_MONITOR_DBUS (initable); + ++ dbus->cancellable = g_cancellable_new (); + dbus->watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, + "org.freedesktop.LowMemoryMonitor", + G_BUS_NAME_WATCHER_FLAGS_AUTO_START, +@@ -142,6 +156,8 @@ g_memory_monitor_dbus_finalize (GObject *object) + { + GMemoryMonitorDBus *dbus = G_MEMORY_MONITOR_DBUS (object); + ++ g_cancellable_cancel (dbus->cancellable); ++ g_clear_object (&dbus->cancellable); + g_clear_signal_handler (&dbus->signal_id, dbus->proxy); + g_clear_object (&dbus->proxy); + g_clear_handle_id (&dbus->watch_id, g_bus_unwatch_name); +-- +GitLab + + +From 889bdb994fed44344a84ad01aa5633a1b1b62b19 Mon Sep 17 00:00:00 2001 +From: Patrick Griffis +Date: Tue, 20 Jul 2021 16:04:31 -0500 +Subject: [PATCH 4/4] Add GPowerProfileMonitor + +--- + docs/reference/gio/gio-docs.xml | 1 + + docs/reference/gio/gio-sections-common.txt | 18 ++ + docs/reference/gio/meson.build | 1 + + gio/gio.h | 1 + + gio/giomodule.c | 7 + + gio/gpowerprofilemonitor.c | 141 ++++++++++++ + gio/gpowerprofilemonitor.h | 63 ++++++ + gio/gpowerprofilemonitordbus.c | 240 +++++++++++++++++++++ + gio/gpowerprofilemonitordbus.h | 32 +++ + gio/meson.build | 3 + + gio/tests/meson.build | 1 + + gio/tests/power-profile-monitor.c | 79 +++++++ + 12 files changed, 587 insertions(+) + create mode 100644 gio/gpowerprofilemonitor.c + create mode 100644 gio/gpowerprofilemonitor.h + create mode 100644 gio/gpowerprofilemonitordbus.c + create mode 100644 gio/gpowerprofilemonitordbus.h + create mode 100644 gio/tests/power-profile-monitor.c + +diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml +index a09d6d31d..b01133900 100644 +--- a/docs/reference/gio/gio-docs.xml ++++ b/docs/reference/gio/gio-docs.xml +@@ -238,6 +238,7 @@ + + + ++ + + + Extending GIO +diff --git a/docs/reference/gio/gio-sections-common.txt b/docs/reference/gio/gio-sections-common.txt +index 250491a42..a7addedc2 100644 +--- a/docs/reference/gio/gio-sections-common.txt ++++ b/docs/reference/gio/gio-sections-common.txt +@@ -4247,6 +4247,24 @@ G_NETWORK_MONITOR_GET_INTERFACE + g_network_connectivity_get_type + + ++
++gpowerprofilemonitor ++GPowerProfileMonitor ++GPowerProfileMonitor ++GPowerProfileMonitorInterface ++G_POWER_PROFILE_MONITOR_EXTENSION_POINT_NAME ++g_power_profile_monitor_dup_default ++g_power_profile_monitor_get_power_saver_enabled ++ ++g_power_profile_monitor_get_type ++G_TYPE_POWER_PROFILE_MONITOR ++G_POWER_PROFILE_MONITOR ++G_IS_POWER_PROFILE_MONITOR ++G_POWER_PROFILE_MONITOR_GET_INTERFACE ++G_TYPE_POWER_PROFILE_LEVEL ++g_power_profile_level_get_type ++
++ +
+ gmenuexporter + g_dbus_connection_export_menu_model +diff --git a/docs/reference/gio/meson.build b/docs/reference/gio/meson.build +index 4d0364819..fbabd25ca 100644 +--- a/docs/reference/gio/meson.build ++++ b/docs/reference/gio/meson.build +@@ -65,6 +65,7 @@ if get_option('gtk_doc') + 'gopenuriportal.h', + 'gpollfilemonitor.h', + 'gportalsupport.h', ++ 'gpowerprofilemonitordbus.h', + 'gproxyresolverportal.h', + 'gregistrysettingsbackend.h', + 'gresourcefile.h', +diff --git a/gio/gio.h b/gio/gio.h +index f5d2dd5a3..e9afab666 100644 +--- a/gio/gio.h ++++ b/gio/gio.h +@@ -120,6 +120,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/gio/giomodule.c b/gio/giomodule.c +index c1d451b5c..dfd895717 100644 +--- a/gio/giomodule.c ++++ b/gio/giomodule.c +@@ -48,6 +48,8 @@ + #include "gmemorymonitor.h" + #include "gmemorymonitorportal.h" + #include "gmemorymonitordbus.h" ++#include "gpowerprofilemonitor.h" ++#include "gpowerprofilemonitordbus.h" + #ifdef G_OS_WIN32 + #include "gregistrysettingsbackend.h" + #include "giowin32-priv.h" +@@ -1077,6 +1079,7 @@ extern GType _g_network_monitor_nm_get_type (void); + + extern GType g_memory_monitor_dbus_get_type (void); + extern GType g_memory_monitor_portal_get_type (void); ++extern GType g_power_profile_monitor_dbus_get_type (void); + + #ifdef G_OS_UNIX + extern GType g_fdo_notification_backend_get_type (void); +@@ -1187,6 +1190,9 @@ _g_io_modules_ensure_extension_points_registered (void) + + ep = g_io_extension_point_register (G_MEMORY_MONITOR_EXTENSION_POINT_NAME); + g_io_extension_point_set_required_type (ep, G_TYPE_MEMORY_MONITOR); ++ ++ ep = g_io_extension_point_register (G_POWER_PROFILE_MONITOR_EXTENSION_POINT_NAME); ++ g_io_extension_point_set_required_type (ep, G_TYPE_POWER_PROFILE_MONITOR); + } + + G_UNLOCK (registered_extensions); +@@ -1272,6 +1278,7 @@ _g_io_modules_ensure_loaded (void) + g_type_ensure (g_null_settings_backend_get_type ()); + g_type_ensure (g_memory_settings_backend_get_type ()); + g_type_ensure (g_keyfile_settings_backend_get_type ()); ++ g_type_ensure (g_power_profile_monitor_dbus_get_type ()); + #if defined(HAVE_INOTIFY_INIT1) + g_type_ensure (g_inotify_file_monitor_get_type ()); + #endif +diff --git a/gio/gpowerprofilemonitor.c b/gio/gpowerprofilemonitor.c +new file mode 100644 +index 000000000..f5028b3e8 +--- /dev/null ++++ b/gio/gpowerprofilemonitor.c +@@ -0,0 +1,141 @@ ++/* GIO - GLib Input, Output and Streaming Library ++ * ++ * Copyright 2019 Red Hat, Inc ++ * Copyright 2021 Igalia S.L. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General ++ * Public License along with this library; if not, see . ++ */ ++ ++#include "config.h" ++#include "glib.h" ++#include "glibintl.h" ++ ++#include "gpowerprofilemonitor.h" ++#include "ginetaddress.h" ++#include "ginetsocketaddress.h" ++#include "ginitable.h" ++#include "gioenumtypes.h" ++#include "giomodule-priv.h" ++#include "gtask.h" ++ ++/** ++ * SECTION:gpowerprofilemonitor ++ * @title: GPowerProfileMonitor ++ * @short_description: Power profile monitor ++ * @include: gio/gio.h ++ * ++ * #GPowerProfileMonitor makes it possible for applications as well as OS components ++ * to monitor system power profiles and act upon them. It currently only exports ++ * whether the system is in “Power Saver” mode (known as “Low Power” mode on ++ * some systems). ++ * ++ * When in “Low Power” mode, it is recommended that applications: ++ * - disabling automatic downloads ++ * - reduce the rate of refresh from online sources such as calendar or ++ * email synchronisation ++ * - if the application has expensive visual effects, reduce them ++ * ++ * It is also likely that OS components providing services to applications will ++ * lower their own background activity, for the sake of the system. ++ * ++ * There are a variety of tools that exist for power consumption analysis, but those ++ * usually depend on the OS and hardware used. On Linux, one could use `upower` to ++ * monitor the battery discharge rate, `powertop` to check on the background activity ++ * or activity at all), `sysprof` to inspect CPU usage, and `intel_gpu_time` to ++ * profile GPU usage. ++ * ++ * Don't forget to disconnect the #GPowerProfileMonitor::notify::power-saver-enabled ++ * signal, and unref the #GPowerProfileMonitor itself when exiting. ++ * ++ * Since: 2.70 ++ */ ++ ++/** ++ * GPowerProfileMonitor: ++ * ++ * #GPowerProfileMonitor monitors system power profile and notifies on ++ * changes. ++ * ++ * Since: 2.70 ++ */ ++ ++/** ++ * GPowerProfileMonitorInterface: ++ * @g_iface: The parent interface. ++ * ++ * The virtual function table for #GPowerProfileMonitor. ++ * ++ * Since: 2.70 ++ */ ++ ++G_DEFINE_INTERFACE_WITH_CODE (GPowerProfileMonitor, g_power_profile_monitor, G_TYPE_OBJECT, ++ g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_INITABLE)) ++ ++ ++/** ++ * g_power_profile_monitor_dup_default: ++ * ++ * Gets a reference to the default #GPowerProfileMonitor for the system. ++ * ++ * Returns: (not nullable) (transfer full): a new reference to the default #GPowerProfileMonitor ++ * ++ * Since: 2.70 ++ */ ++GPowerProfileMonitor * ++g_power_profile_monitor_dup_default (void) ++{ ++ return g_object_ref (_g_io_module_get_default (G_POWER_PROFILE_MONITOR_EXTENSION_POINT_NAME, ++ "GIO_USE_POWER_PROFILE_MONITOR", ++ NULL)); ++} ++ ++/** ++ * g_power_profile_monitor_get_power_saver_enabled: ++ * @monitor: a #GPowerProfileMonitor ++ * ++ * Gets whether the system is in “Power Saver” mode. ++ * ++ * You are expected to listen to the ++ * #GPowerProfileMonitor::notify::power-saver-enabled signal to know when the profile has ++ * changed. ++ * ++ * Returns: Whether the system is in “Power Saver” mode. ++ * ++ * Since: 2.70 ++ */ ++gboolean ++g_power_profile_monitor_get_power_saver_enabled (GPowerProfileMonitor *monitor) ++{ ++ gboolean enabled; ++ g_object_get (monitor, "power-saver-enabled", &enabled, NULL); ++ return enabled; ++} ++ ++static void ++g_power_profile_monitor_default_init (GPowerProfileMonitorInterface *iface) ++{ ++ /** ++ * GPowerProfileMonitor:power-saver-enabled: ++ * ++ * Whether “Power Saver” mode is enabled on the system. ++ * ++ * Since: 2.70 ++ */ ++ g_object_interface_install_property (iface, ++ g_param_spec_boolean ("power-saver-enabled", ++ "power-saver-enabled", ++ "Power Saver Enabled", ++ FALSE, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY)); ++} +diff --git a/gio/gpowerprofilemonitor.h b/gio/gpowerprofilemonitor.h +new file mode 100644 +index 000000000..0891fc3dc +--- /dev/null ++++ b/gio/gpowerprofilemonitor.h +@@ -0,0 +1,63 @@ ++/* GIO - GLib Input, Output and Streaming Library ++ * ++ * Copyright 2019 Red Hat, Inc. ++ * Copyright 2021 Igalia S.L. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General ++ * Public License along with this library; if not, see . ++ */ ++ ++#ifndef __G_POWER_PROFILE_MONITOR_H__ ++#define __G_POWER_PROFILE_MONITOR_H__ ++ ++#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) ++#error "Only can be included directly." ++#endif ++ ++#include ++ ++G_BEGIN_DECLS ++ ++/** ++ * G_POWER_PROFILE_MONITOR_EXTENSION_POINT_NAME: ++ * ++ * Extension point for power profile usage monitoring functionality. ++ * See [Extending GIO][extending-gio]. ++ * ++ * Since: 2.70 ++ */ ++#define G_POWER_PROFILE_MONITOR_EXTENSION_POINT_NAME "gio-power-profile-monitor" ++ ++#define G_TYPE_POWER_PROFILE_MONITOR (g_power_profile_monitor_get_type ()) ++GLIB_AVAILABLE_IN_2_70 ++G_DECLARE_INTERFACE (GPowerProfileMonitor, g_power_profile_monitor, g, power_profile_monitor, GObject) ++ ++#define G_POWER_PROFILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_POWER_PROFILE_MONITOR, GPowerProfileMonitor)) ++#define G_IS_POWER_PROFILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_POWER_PROFILE_MONITOR)) ++#define G_POWER_PROFILE_MONITOR_GET_INTERFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), G_TYPE_POWER_PROFILE_MONITOR, GPowerProfileMonitorInterface)) ++ ++struct _GPowerProfileMonitorInterface ++{ ++ /*< private >*/ ++ GTypeInterface g_iface; ++}; ++ ++GLIB_AVAILABLE_IN_2_70 ++GPowerProfileMonitor *g_power_profile_monitor_dup_default (void); ++ ++GLIB_AVAILABLE_IN_2_70 ++gboolean g_power_profile_monitor_get_power_saver_enabled (GPowerProfileMonitor *monitor); ++ ++G_END_DECLS ++ ++#endif /* __G_POWER_PROFILE_MONITOR_H__ */ +diff --git a/gio/gpowerprofilemonitordbus.c b/gio/gpowerprofilemonitordbus.c +new file mode 100644 +index 000000000..8bbfe3acc +--- /dev/null ++++ b/gio/gpowerprofilemonitordbus.c +@@ -0,0 +1,240 @@ ++/* GIO - GLib Input, Output and Streaming Library ++ * ++ * Copyright 2019 Red Hat, Inc. ++ * Copyrgith 2021 Igalia S.L. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General ++ * Public License along with this library; if not, see . ++ */ ++ ++#include "config.h" ++ ++#include "gpowerprofilemonitor.h" ++#include "gpowerprofilemonitordbus.h" ++#include "gioerror.h" ++#include "ginitable.h" ++#include "giomodule-priv.h" ++#include "glibintl.h" ++#include "glib/gstdio.h" ++#include "gcancellable.h" ++#include "gdbusproxy.h" ++#include "gdbusnamewatching.h" ++ ++#define G_POWER_PROFILE_MONITOR_DBUS_GET_INITABLE_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), G_TYPE_INITABLE, GInitable)) ++ ++static void g_power_profile_monitor_dbus_iface_init (GPowerProfileMonitorInterface *iface); ++static void g_power_profile_monitor_dbus_initable_iface_init (GInitableIface *iface); ++ ++struct _GPowerProfileMonitorDBus ++{ ++ GObject parent_instance; ++ ++ guint watch_id; ++ GCancellable *cancellable; ++ GDBusProxy *proxy; ++ gulong signal_id; ++ ++ gboolean power_saver_enabled; ++}; ++ ++typedef enum ++{ ++ PROP_POWER_SAVER_ENABLED = 1, ++} GPowerProfileMonitorDBusProperty; ++ ++#define POWERPROFILES_DBUS_NAME "net.hadess.PowerProfiles" ++#define POWERPROFILES_DBUS_IFACE "net.hadess.PowerProfiles" ++#define POWERPROFILES_DBUS_PATH "/net/hadess/PowerProfiles" ++ ++G_DEFINE_TYPE_WITH_CODE (GPowerProfileMonitorDBus, g_power_profile_monitor_dbus, G_TYPE_OBJECT, ++ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, ++ g_power_profile_monitor_dbus_initable_iface_init) ++ G_IMPLEMENT_INTERFACE (G_TYPE_POWER_PROFILE_MONITOR, ++ g_power_profile_monitor_dbus_iface_init) ++ _g_io_modules_ensure_extension_points_registered (); ++ g_io_extension_point_implement (G_POWER_PROFILE_MONITOR_EXTENSION_POINT_NAME, ++ g_define_type_id, ++ "dbus", ++ 30)) ++ ++static void ++g_power_profile_monitor_dbus_init (GPowerProfileMonitorDBus *dbus) ++{ ++ dbus->power_saver_enabled = FALSE; ++} ++ ++static void ++ppd_properties_changed_cb (GDBusProxy *proxy, ++ GVariant *changed_properties, ++ GStrv *invalidated_properties, ++ gpointer user_data) ++{ ++ GPowerProfileMonitorDBus *dbus = user_data; ++ const char *active_profile; ++ gboolean enabled; ++ ++ if (!g_variant_lookup (changed_properties, "ActiveProfile", "&s", &active_profile)) ++ return; ++ ++ enabled = g_strcmp0 (active_profile, "power-saver") == 0; ++ if (enabled == dbus->power_saver_enabled) ++ return; ++ ++ dbus->power_saver_enabled = enabled; ++ g_object_notify (G_OBJECT (dbus), "power-saver-enabled"); ++} ++ ++static void ++ppd_proxy_cb (GObject *source_object, ++ GAsyncResult *res, ++ gpointer user_data) ++{ ++ GPowerProfileMonitorDBus *dbus = user_data; ++ GVariant *active_profile_variant; ++ GDBusProxy *proxy; ++ GError *error = NULL; ++ const char *active_profile; ++ gboolean power_saver_enabled; ++ ++ proxy = g_dbus_proxy_new_finish (res, &error); ++ if (!proxy) ++ { ++ g_debug ("GPowerProfileMonitorDBus: Failed to create PowerProfiles D-Bus proxy: %s", ++ error->message); ++ g_error_free (error); ++ return; ++ } ++ ++ active_profile_variant = g_dbus_proxy_get_cached_property (proxy, "ActiveProfile"); ++ if (g_variant_is_of_type (active_profile_variant, G_VARIANT_TYPE_STRING)) ++ { ++ active_profile = g_variant_get_string (active_profile_variant, NULL); ++ power_saver_enabled = g_strcmp0 (active_profile, "power-saver") == 0; ++ if (power_saver_enabled != dbus->power_saver_enabled) ++ { ++ dbus->power_saver_enabled = power_saver_enabled; ++ g_object_notify (G_OBJECT (dbus), "power-saver-enabled"); ++ } ++ } ++ ++ dbus->signal_id = g_signal_connect (G_OBJECT (proxy), "g-properties-changed", ++ G_CALLBACK (ppd_properties_changed_cb), dbus); ++ dbus->proxy = g_steal_pointer (&proxy); ++} ++ ++static void ++ppd_appeared_cb (GDBusConnection *connection, ++ const gchar *name, ++ const gchar *name_owner, ++ gpointer user_data) ++{ ++ GPowerProfileMonitorDBus *dbus = user_data; ++ ++ g_dbus_proxy_new (connection, ++ G_DBUS_PROXY_FLAGS_NONE, ++ NULL, ++ POWERPROFILES_DBUS_NAME, ++ POWERPROFILES_DBUS_PATH, ++ POWERPROFILES_DBUS_IFACE, ++ dbus->cancellable, ++ ppd_proxy_cb, ++ dbus); ++} ++ ++static void ++ppd_vanished_cb (GDBusConnection *connection, ++ const gchar *name, ++ gpointer user_data) ++{ ++ GPowerProfileMonitorDBus *dbus = user_data; ++ ++ g_clear_signal_handler (&dbus->signal_id, dbus->proxy); ++ g_clear_object (&dbus->proxy); ++ ++ dbus->power_saver_enabled = FALSE; ++ g_object_notify (G_OBJECT (dbus), "power-saver-enabled"); ++} ++ ++static void ++g_power_profile_monitor_dbus_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ GPowerProfileMonitorDBus *dbus = G_POWER_PROFILE_MONITOR_DBUS (object); ++ ++ switch ((GPowerProfileMonitorDBusProperty) prop_id) ++ { ++ case PROP_POWER_SAVER_ENABLED: ++ g_value_set_boolean (value, dbus->power_saver_enabled); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static gboolean ++g_power_profile_monitor_dbus_initable_init (GInitable *initable, ++ GCancellable *cancellable, ++ GError **error) ++{ ++ GPowerProfileMonitorDBus *dbus = G_POWER_PROFILE_MONITOR_DBUS (initable); ++ ++ dbus->cancellable = g_cancellable_new (); ++ dbus->watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, ++ POWERPROFILES_DBUS_NAME, ++ G_BUS_NAME_WATCHER_FLAGS_AUTO_START, ++ ppd_appeared_cb, ++ ppd_vanished_cb, ++ dbus, ++ NULL); ++ ++ return TRUE; ++} ++ ++static void ++g_power_profile_monitor_dbus_finalize (GObject *object) ++{ ++ GPowerProfileMonitorDBus *dbus = G_POWER_PROFILE_MONITOR_DBUS (object); ++ ++ g_cancellable_cancel (dbus->cancellable); ++ g_clear_object (&dbus->cancellable); ++ g_clear_signal_handler (&dbus->signal_id, dbus->proxy); ++ g_clear_object (&dbus->proxy); ++ g_clear_handle_id (&dbus->watch_id, g_bus_unwatch_name); ++ ++ G_OBJECT_CLASS (g_power_profile_monitor_dbus_parent_class)->finalize (object); ++} ++ ++static void ++g_power_profile_monitor_dbus_class_init (GPowerProfileMonitorDBusClass *nl_class) ++{ ++ GObjectClass *gobject_class = G_OBJECT_CLASS (nl_class); ++ ++ gobject_class->get_property = g_power_profile_monitor_dbus_get_property; ++ gobject_class->finalize = g_power_profile_monitor_dbus_finalize; ++ ++ g_object_class_override_property (gobject_class, PROP_POWER_SAVER_ENABLED, "power-saver-enabled"); ++} ++ ++static void ++g_power_profile_monitor_dbus_iface_init (GPowerProfileMonitorInterface *monitor_iface) ++{ ++} ++ ++static void ++g_power_profile_monitor_dbus_initable_iface_init (GInitableIface *iface) ++{ ++ iface->init = g_power_profile_monitor_dbus_initable_init; ++} +diff --git a/gio/gpowerprofilemonitordbus.h b/gio/gpowerprofilemonitordbus.h +new file mode 100644 +index 000000000..ecf7246d1 +--- /dev/null ++++ b/gio/gpowerprofilemonitordbus.h +@@ -0,0 +1,32 @@ ++/* GIO - GLib Input, Output and Streaming Library ++ * ++ * Copyright 2019 Red Hat, Inc. ++ * Copyright 2021 Igalia S.L. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General ++ * Public License along with this library; if not, see . ++ */ ++ ++#ifndef __G_POWER_PROFILE_MONITOR_DBUS_H__ ++#define __G_POWER_PROFILE_MONITOR_DBUS_H__ ++ ++#include ++ ++G_BEGIN_DECLS ++ ++#define G_TYPE_POWER_PROFILE_MONITOR_DBUS (g_power_profile_monitor_dbus_get_type ()) ++G_DECLARE_FINAL_TYPE (GPowerProfileMonitorDBus, g_power_profile_monitor_dbus, G, POWER_PROFILE_MONITOR_DBUS, GObject) ++ ++G_END_DECLS ++ ++#endif /* __G_POWER_PROFILE_MONITOR_DBUS_H__ */ +diff --git a/gio/meson.build b/gio/meson.build +index 49a37a7bd..d5838ed8a 100644 +--- a/gio/meson.build ++++ b/gio/meson.build +@@ -533,6 +533,8 @@ gio_sources = files( + 'gpollableoutputstream.c', + 'gpollableutils.c', + 'gpollfilemonitor.c', ++ 'gpowerprofilemonitor.c', ++ 'gpowerprofilemonitordbus.c', + 'gproxy.c', + 'gproxyaddress.c', + 'gproxyaddressenumerator.c', +@@ -673,6 +675,7 @@ gio_headers = files( + 'gpollableinputstream.h', + 'gpollableoutputstream.h', + 'gpollableutils.h', ++ 'gpowerprofilemonitor.h', + 'gproxy.h', + 'gproxyaddress.h', + 'gproxyaddressenumerator.h', +diff --git a/gio/tests/meson.build b/gio/tests/meson.build +index 98d1401d0..fc2055101 100644 +--- a/gio/tests/meson.build ++++ b/gio/tests/meson.build +@@ -75,6 +75,7 @@ gio_tests = { + 'network-monitor-race' : {}, + 'permission' : {}, + 'pollable' : {'dependencies' : [libdl_dep]}, ++ 'power-profile-monitor' : {}, + 'proxy-test' : {}, + 'readwrite' : {}, + 'simple-async-result' : {}, +diff --git a/gio/tests/power-profile-monitor.c b/gio/tests/power-profile-monitor.c +new file mode 100644 +index 000000000..bb32f181f +--- /dev/null ++++ b/gio/tests/power-profile-monitor.c +@@ -0,0 +1,79 @@ ++/* GIO - GLib Input, Output and Streaming Library ++ * ++ * Copyright 2021 Igalia S.L. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General ++ * Public License along with this library; if not, see . ++ */ ++ ++#include ++ ++static void ++test_dup_default (void) ++{ ++ GPowerProfileMonitor *monitor; ++ ++ monitor = g_power_profile_monitor_dup_default (); ++ g_assert_nonnull (monitor); ++ g_object_unref (monitor); ++} ++ ++static void ++power_saver_enabled_cb (GPowerProfileMonitor *monitor, ++ GParamSpec *pspec, ++ gpointer user_data) ++{ ++ gboolean enabled; ++ ++ enabled = g_power_profile_monitor_get_power_saver_enabled (monitor); ++ g_debug ("Power Saver %s (%d)", enabled ? "enabled" : "disabled", enabled); ++} ++ ++static void ++do_watch_power_profile (void) ++{ ++ GPowerProfileMonitor *monitor; ++ GMainLoop *loop; ++ gulong signal_id; ++ ++ monitor = g_power_profile_monitor_dup_default (); ++ signal_id = g_signal_connect (G_OBJECT (monitor), "notify::power-saver-enabled", ++ G_CALLBACK (power_saver_enabled_cb), NULL); ++ ++ loop = g_main_loop_new (NULL, TRUE); ++ g_main_loop_run (loop); ++ ++ g_signal_handler_disconnect (monitor, signal_id); ++ g_object_unref (monitor); ++ g_main_loop_unref (loop); ++} ++ ++int ++main (int argc, char **argv) ++{ ++ int ret; ++ ++ if (argc == 2 && !strcmp (argv[1], "--watch")) ++ { ++ do_watch_power_profile (); ++ return 0; ++ } ++ ++ g_test_init (&argc, &argv, NULL); ++ ++ g_test_add_func ("/power-profile-monitor/default", test_dup_default); ++ ++ ret = g_test_run (); ++ ++ return ret; ++} +-- +GitLab + diff --git a/2222.patch b/2222.patch new file mode 100644 index 0000000000000000000000000000000000000000..0b6106f1375928ced307cf0563b8715db38f05b0 --- /dev/null +++ b/2222.patch @@ -0,0 +1,739 @@ +From 9645cbffa8ba1a08b73fdae50b31125d11aa5684 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Mon, 9 Aug 2021 23:19:17 +0200 +Subject: [PATCH 1/4] gio: Add portal version of GPowerProfileMonitor + +--- + docs/reference/gio/meson.build | 1 + + gio/giomodule.c | 2 + + gio/gpowerprofilemonitorportal.c | 182 +++++++++++++++++++++++++++++++ + gio/gpowerprofilemonitorportal.h | 31 ++++++ + gio/meson.build | 1 + + 5 files changed, 217 insertions(+) + create mode 100644 gio/gpowerprofilemonitorportal.c + create mode 100644 gio/gpowerprofilemonitorportal.h + +diff --git a/docs/reference/gio/meson.build b/docs/reference/gio/meson.build +index fbabd25ca..9aaafeed5 100644 +--- a/docs/reference/gio/meson.build ++++ b/docs/reference/gio/meson.build +@@ -66,6 +66,7 @@ if get_option('gtk_doc') + 'gpollfilemonitor.h', + 'gportalsupport.h', + 'gpowerprofilemonitordbus.h', ++ 'gpowerprofilemonitorportal.h', + 'gproxyresolverportal.h', + 'gregistrysettingsbackend.h', + 'gresourcefile.h', +diff --git a/gio/giomodule.c b/gio/giomodule.c +index dfd895717..d34037a45 100644 +--- a/gio/giomodule.c ++++ b/gio/giomodule.c +@@ -50,6 +50,7 @@ + #include "gmemorymonitordbus.h" + #include "gpowerprofilemonitor.h" + #include "gpowerprofilemonitordbus.h" ++#include "gpowerprofilemonitorportal.h" + #ifdef G_OS_WIN32 + #include "gregistrysettingsbackend.h" + #include "giowin32-priv.h" +@@ -1305,6 +1306,7 @@ _g_io_modules_ensure_loaded (void) + g_type_ensure (g_memory_monitor_dbus_get_type ()); + g_type_ensure (g_memory_monitor_portal_get_type ()); + g_type_ensure (g_network_monitor_portal_get_type ()); ++ g_type_ensure (g_power_profile_monitor_portal_get_type ()); + g_type_ensure (g_proxy_resolver_portal_get_type ()); + #endif + #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +diff --git a/gio/gpowerprofilemonitorportal.c b/gio/gpowerprofilemonitorportal.c +new file mode 100644 +index 000000000..bb1b4fd15 +--- /dev/null ++++ b/gio/gpowerprofilemonitorportal.c +@@ -0,0 +1,182 @@ ++/* GIO - GLib Input, Output and Streaming Library ++ * ++ * Copyright 2021 Red Hat, Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General ++ * Public License along with this library; if not, see . ++ */ ++ ++#include "config.h" ++ ++#include "gpowerprofilemonitor.h" ++#include "gpowerprofilemonitorportal.h" ++#include "gdbuserror.h" ++#include "gdbusproxy.h" ++#include "ginitable.h" ++#include "gioerror.h" ++#include "giomodule-priv.h" ++#include "gportalsupport.h" ++ ++#define G_POWER_PROFILE_MONITOR_PORTAL_GET_INITABLE_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), G_TYPE_INITABLE, GInitable)) ++ ++static void g_power_profile_monitor_portal_iface_init (GPowerProfileMonitorInterface *iface); ++static void g_power_profile_monitor_portal_initable_iface_init (GInitableIface *iface); ++ ++typedef enum ++{ ++ PROP_POWER_SAVER_ENABLED = 1, ++} GPowerProfileMonitorPortalProperty; ++ ++struct _GPowerProfileMonitorPortal ++{ ++ GObject parent_instance; ++ ++ GDBusProxy *proxy; ++ gulong signal_id; ++ gboolean power_saver_enabled; ++}; ++ ++G_DEFINE_TYPE_WITH_CODE (GPowerProfileMonitorPortal, g_power_profile_monitor_portal, G_TYPE_OBJECT, ++ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, ++ g_power_profile_monitor_portal_initable_iface_init) ++ G_IMPLEMENT_INTERFACE (G_TYPE_POWER_PROFILE_MONITOR, ++ g_power_profile_monitor_portal_iface_init) ++ _g_io_modules_ensure_extension_points_registered (); ++ g_io_extension_point_implement (G_POWER_PROFILE_MONITOR_EXTENSION_POINT_NAME, ++ g_define_type_id, ++ "portal", ++ 40)) ++ ++static void ++g_power_profile_monitor_portal_init (GPowerProfileMonitorPortal *portal) ++{ ++} ++ ++static void ++proxy_properties_changed (GDBusProxy *proxy, ++ GVariant *changed_properties, ++ GStrv invalidated_properties, ++ gpointer user_data) ++{ ++ GPowerProfileMonitorPortal *ppm = user_data; ++ gboolean power_saver_enabled; ++ ++ if (!g_variant_lookup (changed_properties, "power-saver-enabled", "b", &power_saver_enabled)) ++ return; ++ ++ if (power_saver_enabled == ppm->power_saver_enabled) ++ return; ++ ++ ppm->power_saver_enabled = power_saver_enabled; ++ g_object_notify (G_OBJECT (ppm), "power-saver-enabled"); ++} ++ ++static void ++g_power_profile_monitor_portal_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ GPowerProfileMonitorPortal *ppm = G_POWER_PROFILE_MONITOR_PORTAL (object); ++ ++ switch ((GPowerProfileMonitorPortalProperty) prop_id) ++ { ++ case PROP_POWER_SAVER_ENABLED: ++ g_value_set_boolean (value, ppm->power_saver_enabled); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static gboolean ++g_power_profile_monitor_portal_initable_init (GInitable *initable, ++ GCancellable *cancellable, ++ GError **error) ++{ ++ GPowerProfileMonitorPortal *ppm = G_POWER_PROFILE_MONITOR_PORTAL (initable); ++ GDBusProxy *proxy; ++ gchar *name_owner; ++ ++ if (!glib_should_use_portal ()) ++ { ++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Not using portals"); ++ return FALSE; ++ } ++ ++ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, ++ G_DBUS_PROXY_FLAGS_NONE, ++ NULL, ++ "org.freedesktop.portal.Desktop", ++ "/org/freedesktop/portal/desktop", ++ "org.freedesktop.portal.PowerProfileMonitor", ++ cancellable, ++ error); ++ if (!proxy) ++ return FALSE; ++ ++ name_owner = g_dbus_proxy_get_name_owner (proxy); ++ ++ if (name_owner == NULL) ++ { ++ g_object_unref (proxy); ++ g_set_error (error, ++ G_DBUS_ERROR, ++ G_DBUS_ERROR_NAME_HAS_NO_OWNER, ++ "Desktop portal not found"); ++ return FALSE; ++ } ++ ++ g_free (name_owner); ++ ++ ppm->signal_id = g_signal_connect (proxy, "g-properties-changed", ++ G_CALLBACK (proxy_properties_changed), ppm); ++ ++ ppm->proxy = g_steal_pointer (&proxy); ++ ++ return TRUE; ++} ++ ++static void ++g_power_profile_monitor_portal_finalize (GObject *object) ++{ ++ GPowerProfileMonitorPortal *ppm = G_POWER_PROFILE_MONITOR_PORTAL (object); ++ ++ g_clear_signal_handler (&ppm->signal_id, ppm->proxy); ++ g_clear_object (&ppm->proxy); ++ ++ G_OBJECT_CLASS (g_power_profile_monitor_portal_parent_class)->finalize (object); ++} ++ ++static void ++g_power_profile_monitor_portal_class_init (GPowerProfileMonitorPortalClass *nl_class) ++{ ++ GObjectClass *gobject_class = G_OBJECT_CLASS (nl_class); ++ ++ gobject_class->get_property = g_power_profile_monitor_portal_get_property; ++ gobject_class->finalize = g_power_profile_monitor_portal_finalize; ++ ++ g_object_class_override_property (gobject_class, PROP_POWER_SAVER_ENABLED, "power-saver-enabled"); ++} ++ ++static void ++g_power_profile_monitor_portal_iface_init (GPowerProfileMonitorInterface *monitor_iface) ++{ ++} ++ ++static void ++g_power_profile_monitor_portal_initable_iface_init (GInitableIface *iface) ++{ ++ iface->init = g_power_profile_monitor_portal_initable_init; ++} +diff --git a/gio/gpowerprofilemonitorportal.h b/gio/gpowerprofilemonitorportal.h +new file mode 100644 +index 000000000..b91a14610 +--- /dev/null ++++ b/gio/gpowerprofilemonitorportal.h +@@ -0,0 +1,31 @@ ++/* GIO - GLib Input, Output and Streaming Library ++ * ++ * Copyright 2021 Red Hat, Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General ++ * Public License along with this library; if not, see . ++ */ ++ ++#ifndef __G_POWER_PROFILE_MONITOR_PORTAL_H__ ++#define __G_POWER_PROFILE_MONITOR_PORTAL_H__ ++ ++#include ++ ++G_BEGIN_DECLS ++ ++#define G_TYPE_POWER_PROFILE_MONITOR_PORTAL (g_power_profile_monitor_portal_get_type ()) ++G_DECLARE_FINAL_TYPE (GPowerProfileMonitorPortal, g_power_profile_monitor_portal, G, POWER_PROFILE_MONITOR_PORTAL, GObject) ++ ++G_END_DECLS ++ ++#endif /* __G_POWER_PROFILE_MONITOR_PORTAL_H__ */ +diff --git a/gio/meson.build b/gio/meson.build +index d5838ed8a..ac3373f2b 100644 +--- a/gio/meson.build ++++ b/gio/meson.build +@@ -383,6 +383,7 @@ if host_system != 'windows' + 'gopenuriportal.c', + 'gmemorymonitorportal.c', + 'gnetworkmonitorportal.c', ++ 'gpowerprofilemonitorportal.c', + 'gproxyresolverportal.c', + 'gtrashportal.c', + 'gportalsupport.c', +-- +GitLab + + +From 18eb29897d80bf662d58bd11a89617ddd7ebfeed Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Tue, 10 Aug 2021 10:58:53 +0200 +Subject: [PATCH 2/4] gio: Add GPowerProfileMonitor tests + +Tests both the portal and direct D-Bus variants. +--- + gio/tests/meson.build | 14 ++- + gio/tests/power-profile-monitor-dbus.py.in | 107 ++++++++++++++++ + gio/tests/power-profile-monitor-portal.py.in | 126 +++++++++++++++++++ + 3 files changed, 241 insertions(+), 6 deletions(-) + create mode 100755 gio/tests/power-profile-monitor-dbus.py.in + create mode 100755 gio/tests/power-profile-monitor-portal.py.in + +diff --git a/gio/tests/meson.build b/gio/tests/meson.build +index fc2055101..5dbfb8e60 100644 +--- a/gio/tests/meson.build ++++ b/gio/tests/meson.build +@@ -541,27 +541,29 @@ if installed_tests_enabled + install_subdir('static-link', install_dir : installed_tests_execdir) + install_data('static-link.py', install_dir : installed_tests_execdir) + +- memory_monitor_tests = [ ++ monitor_tests = [ + 'memory-monitor-dbus', + 'memory-monitor-portal', ++ 'power-profile-monitor-dbus', ++ 'power-profile-monitor-portal' + ] + +- foreach memory_monitor_test : memory_monitor_tests ++ foreach monitor_test : monitor_tests + cdata = configuration_data() + cdata.set('installed_tests_dir', installed_tests_execdir) +- cdata.set('program', memory_monitor_test + '.py') ++ cdata.set('program', monitor_test + '.py') + cdata.set('env', '') + configure_file( + input: installed_tests_template_tap, +- output: memory_monitor_test + '.test', ++ output: monitor_test + '.test', + install_dir: installed_tests_metadir, + configuration: cdata + ) + cdata = configuration_data() + cdata.set('libexecdir', join_paths(glib_prefix, get_option('libexecdir'))) + configure_file( +- input: memory_monitor_test + '.py.in', +- output: memory_monitor_test + '.py', ++ input: monitor_test + '.py.in', ++ output: monitor_test + '.py', + install_dir : installed_tests_execdir, + configuration: cdata, + ) +diff --git a/gio/tests/power-profile-monitor-dbus.py.in b/gio/tests/power-profile-monitor-dbus.py.in +new file mode 100755 +index 000000000..06e594f4a +--- /dev/null ++++ b/gio/tests/power-profile-monitor-dbus.py.in +@@ -0,0 +1,107 @@ ++#!/usr/bin/python3 ++ ++# This program is free software; you can redistribute it and/or modify it under ++# the terms of the GNU Lesser General Public License as published by the Free ++# Software Foundation; either version 3 of the License, or (at your option) any ++# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text ++# of the license. ++ ++__author__ = 'Bastien Nocera' ++__email__ = 'hadess@hadess.net' ++__copyright__ = '(c) 2019, 2021 Red Hat Inc.' ++__license__ = 'LGPL 3+' ++ ++import unittest ++import sys ++import subprocess ++import fcntl ++import os ++import time ++ ++import taptestrunner ++ ++try: ++ # Do all non-standard imports here so we can skip the tests if any ++ # needed packages are not available. ++ import dbus ++ import dbus.mainloop.glib ++ import dbusmock ++ from gi.repository import GLib ++ from gi.repository import Gio ++ ++ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) ++ ++ class TestPowerProfileMonitor(dbusmock.DBusTestCase): ++ '''Test GPowerProfileMonitorDBus''' ++ ++ @classmethod ++ def setUpClass(klass): ++ klass.start_system_bus() ++ klass.dbus_con = klass.get_dbus(True) ++ ++ def setUp(self): ++ try: ++ Gio.PowerProfileMonitor ++ except AttributeError: ++ raise unittest.SkipTest('Power Profile Monitor not in ' ++ 'introspection data. Requires ' ++ 'GObject-Introspection ≥ 1.63.2') # FIXME version ++ try: ++ (self.p_mock, self.obj_ppd) = self.spawn_server_template( ++ 'power_profiles_daemon', {}, stdout=subprocess.PIPE) ++ except ModuleNotFoundError: ++ raise unittest.SkipTest("power-profiles-daemon dbusmock template not " ++ "found. Requires dbusmock > 0.23.1.") # FIXME version ++ # set log to nonblocking ++ flags = fcntl.fcntl(self.p_mock.stdout, fcntl.F_GETFL) ++ fcntl.fcntl(self.p_mock.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK) ++ self.power_saver_enabled = False ++ self.dbus_props = dbus.Interface(self.obj_ppd, dbus.PROPERTIES_IFACE) ++ self.power_profile_monitor = Gio.PowerProfileMonitor.dup_default() ++ self.power_profile_monitor.connect("notify::power-saver-enabled", self.power_saver_enabled_cb) ++ self.mainloop = GLib.MainLoop() ++ self.main_context = self.mainloop.get_context() ++ ++ def tearDown(self): ++ self.p_mock.terminate() ++ self.p_mock.wait() ++ ++ def assertEventually(self, condition, message=None, timeout=50): ++ '''Assert that condition function eventually returns True. ++ ++ Timeout is in deciseconds, defaulting to 50 (5 seconds). message is ++ printed on failure. ++ ''' ++ while timeout >= 0: ++ context = GLib.MainContext.default() ++ while context.iteration(False): ++ pass ++ if condition(): ++ break ++ timeout -= 1 ++ time.sleep(0.1) ++ else: ++ self.fail(message or 'timed out waiting for ' + str(condition)) ++ ++ def power_saver_enabled_cb(self, spec, data): ++ self.power_saver_enabled = self.power_profile_monitor.get_power_saver_enabled() ++ self.main_context.wakeup() ++ ++ def test_power_profile_power_saver_enabled(self): ++ '''power-saver-enabled property''' ++ ++ self.assertEqual(self.power_profile_monitor.get_power_saver_enabled(), False) ++ self.dbus_props.Set('net.hadess.PowerProfiles', 'ActiveProfile', dbus.String('power-saver', variant_level=1)) ++ self.assertEventually(lambda: self.power_saver_enabled == True, "power-saver didn't become enabled", 10) ++ ++ self.dbus_props.Set('net.hadess.PowerProfiles', 'ActiveProfile', dbus.String('balanced', variant_level=1)) ++ self.assertEventually(lambda: self.power_saver_enabled == False, "power-saver didn't become disabled", 10) ++ ++except ImportError as e: ++ @unittest.skip("Cannot import %s" % e.name) ++ class TestPowerProfileMonitor(unittest.TestCase): ++ def test_power_profile_power_saver_enabled(self): ++ pass ++ ++if __name__ == '__main__': ++ unittest.main(testRunner=taptestrunner.TAPTestRunner()) +diff --git a/gio/tests/power-profile-monitor-portal.py.in b/gio/tests/power-profile-monitor-portal.py.in +new file mode 100755 +index 000000000..960a62232 +--- /dev/null ++++ b/gio/tests/power-profile-monitor-portal.py.in +@@ -0,0 +1,126 @@ ++#!/usr/bin/python3 ++ ++# This program is free software; you can redistribute it and/or modify it under ++# the terms of the GNU Lesser General Public License as published by the Free ++# Software Foundation; either version 3 of the License, or (at your option) any ++# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text ++# of the license. ++ ++__author__ = 'Bastien Nocera' ++__email__ = 'hadess@hadess.net' ++__copyright__ = '(c) 2021 Red Hat Inc.' ++__license__ = 'LGPL 3+' ++ ++import unittest ++import sys ++import subprocess ++import fcntl ++import os ++import time ++ ++import taptestrunner ++ ++try: ++ # Do all non-standard imports here so we can skip the tests if any ++ # needed packages are not available. ++ import dbus ++ import dbus.mainloop.glib ++ import dbusmock ++ from gi.repository import GLib ++ from gi.repository import Gio ++ ++ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) ++ ++ # XDG_DESKTOP_PORTAL_PATH = os.path.expanduser("~/.cache/jhbuild/build/xdg-desktop-portal/xdg-desktop-portal") ++ XDG_DESKTOP_PORTAL_PATH = "@libexecdir@/xdg-desktop-portal" ++ ++ class TestPowerProfileMonitorPortal(dbusmock.DBusTestCase): ++ '''Test GPowerProfileMonitorPortal''' ++ ++ @classmethod ++ def setUpClass(klass): ++ klass.start_system_bus() ++ klass.dbus_con = klass.get_dbus(True) ++ # Start session bus so that xdg-desktop-portal can run on it ++ klass.start_session_bus() ++ ++ def setUp(self): ++ try: ++ Gio.PowerProfileMonitor ++ except AttributeError: ++ raise unittest.SkipTest('Power Profile Monitor not in ' ++ 'introspection data. Requires ' ++ 'GObject-Introspection > 1.69.0') ++ try: ++ (self.p_mock, self.obj_ppd) = self.spawn_server_template( ++ 'power_profiles_daemon', {}, stdout=subprocess.PIPE) ++ except ModuleNotFoundError: ++ raise unittest.SkipTest("power-profiles-daemon dbusmock template not " ++ "found. Requires dbusmock > 0.23.1.") ++ # set log to nonblocking ++ flags = fcntl.fcntl(self.p_mock.stdout, fcntl.F_GETFL) ++ fcntl.fcntl(self.p_mock.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK) ++ self.power_saver_enabled = False ++ self.dbus_props = dbus.Interface(self.obj_ppd, dbus.PROPERTIES_IFACE) ++ try: ++ self.xdp = subprocess.Popen([XDG_DESKTOP_PORTAL_PATH]) ++ except FileNotFoundError: ++ raise unittest.SkipTest("xdg-desktop-portal not available") ++ ++ try: ++ self.wait_for_bus_object('org.freedesktop.portal.Desktop', ++ '/org/freedesktop/portal/desktop') ++ except: ++ raise ++ # subprocess.Popen(['gdbus', 'monitor', '--session', '--dest', 'org.freedesktop.portal.Desktop']) ++ ++ os.environ['GTK_USE_PORTAL'] = "1" ++ self.power_profile_monitor = Gio.PowerProfileMonitor.dup_default() ++ assert("GPowerProfileMonitorPortal" in str(self.power_profile_monitor)) ++ self.power_profile_monitor.connect("notify::power-saver-enabled", self.power_saver_enabled_cb) ++ self.mainloop = GLib.MainLoop() ++ self.main_context = self.mainloop.get_context() ++ ++ def tearDown(self): ++ self.p_mock.terminate() ++ self.p_mock.wait() ++ ++ def assertEventually(self, condition, message=None, timeout=50): ++ '''Assert that condition function eventually returns True. ++ ++ Timeout is in deciseconds, defaulting to 50 (5 seconds). message is ++ printed on failure. ++ ''' ++ while timeout >= 0: ++ context = GLib.MainContext.default() ++ while context.iteration(False): ++ pass ++ if condition(): ++ break ++ timeout -= 1 ++ time.sleep(0.1) ++ else: ++ self.fail(message or 'timed out waiting for ' + str(condition)) ++ ++ def power_saver_enabled_cb(self, spec, data): ++ self.power_saver_enabled = self.power_profile_monitor.get_power_saver_enabled() ++ self.main_context.wakeup() ++ ++ def test_power_profile_power_saver_enabled_portal(self): ++ '''power-saver-enabled property''' ++ ++ self.assertEqual(self.power_profile_monitor.get_power_saver_enabled(), False) ++ self.dbus_props.Set('net.hadess.PowerProfiles', 'ActiveProfile', dbus.String('power-saver', variant_level=1)) ++ self.assertEventually(lambda: self.power_saver_enabled == True, "power-saver didn't become enabled", 10) ++ ++ self.dbus_props.Set('net.hadess.PowerProfiles', 'ActiveProfile', dbus.String('balanced', variant_level=1)) ++ self.assertEventually(lambda: self.power_saver_enabled == False, "power-saver didn't become disabled", 10) ++ ++except ImportError as e: ++ @unittest.skip("Cannot import %s" % e.name) ++ class TestPowerProfileMonitorPortal(unittest.TestCase): ++ def test_power_profile_power_saver_enabled_portal(self): ++ pass ++ ++if __name__ == '__main__': ++ unittest.main(testRunner=taptestrunner.TAPTestRunner()) +-- +GitLab + + +From 66acea8418eb3d8e46bb6f93dc0c3f13a1f7822b Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Wed, 11 Aug 2021 15:37:40 +0200 +Subject: [PATCH 3/4] gio: Remove left-over debug statement from memory monitor + portal test + +--- + gio/tests/memory-monitor-portal.py.in | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/gio/tests/memory-monitor-portal.py.in b/gio/tests/memory-monitor-portal.py.in +index cb4a960eb..f5fd2283f 100755 +--- a/gio/tests/memory-monitor-portal.py.in ++++ b/gio/tests/memory-monitor-portal.py.in +@@ -31,7 +31,6 @@ try: + + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + +- # XDG_DESKTOP_PORTAL_PATH = os.path.expanduser("~/.cache/jhbuild/build/xdg-desktop-portal/xdg-desktop-portal") + XDG_DESKTOP_PORTAL_PATH = "@libexecdir@/xdg-desktop-portal" + + class TestLowMemoryMonitorPortal(dbusmock.DBusTestCase): +-- +GitLab + + +From 2e9842cafc73a7fb94cfde7937e125e1a91f35f8 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Wed, 11 Aug 2021 15:38:12 +0200 +Subject: [PATCH 4/4] gio: Simplify memory monitor tests by using + assertEventually() helper + +assertEventually is a helper used in a number of projects that use +dbusmock. + +See https://github.com/martinpitt/python-dbusmock/issues/82 +--- + gio/tests/memory-monitor-dbus.py.in | 31 ++++++++++++++++----------- + gio/tests/memory-monitor-portal.py.in | 31 ++++++++++++++++----------- + 2 files changed, 38 insertions(+), 24 deletions(-) + +diff --git a/gio/tests/memory-monitor-dbus.py.in b/gio/tests/memory-monitor-dbus.py.in +index 7823e7309..e8ac28faf 100755 +--- a/gio/tests/memory-monitor-dbus.py.in ++++ b/gio/tests/memory-monitor-dbus.py.in +@@ -66,6 +66,23 @@ try: + self.p_mock.terminate() + self.p_mock.wait() + ++ def assertEventually(self, condition, message=None, timeout=50): ++ '''Assert that condition function eventually returns True. ++ ++ Timeout is in deciseconds, defaulting to 50 (5 seconds). message is ++ printed on failure. ++ ''' ++ while timeout >= 0: ++ context = GLib.MainContext.default() ++ while context.iteration(False): ++ pass ++ if condition(): ++ break ++ timeout -= 1 ++ time.sleep(0.1) ++ else: ++ self.fail(message or 'timed out waiting for ' + str(condition)) ++ + def memory_warning_cb(self, monitor, level): + self.last_warning = level + self.main_context.wakeup() +@@ -82,21 +99,11 @@ try: + + self.dbusmock.EmitWarning(100) + # Wait 2 seconds or until warning +- timeout = 2 +- while timeout > 0 and self.last_warning != 100: +- time.sleep(0.5) +- timeout -= 0.5 +- self.main_context.iteration(False) +- self.assertEqual(self.last_warning, 100) ++ self.assertEventually(self.last_warning == 100, "'100' low-memory warning not received", 20) + + self.dbusmock.EmitWarning(255) + # Wait 2 seconds or until warning +- timeout = 2 +- while timeout > 0 and self.last_warning != 255: +- time.sleep(0.5) +- timeout -= 0.5 +- self.main_context.iteration(False) +- self.assertEqual(self.last_warning, 255) ++ self.assertEventually(self.last_warning == 255, "'255' low-memory warning not received", 20) + + except ImportError as e: + @unittest.skip("Cannot import %s" % e.name) +diff --git a/gio/tests/memory-monitor-portal.py.in b/gio/tests/memory-monitor-portal.py.in +index f5fd2283f..36d5094d3 100755 +--- a/gio/tests/memory-monitor-portal.py.in ++++ b/gio/tests/memory-monitor-portal.py.in +@@ -84,6 +84,23 @@ try: + self.p_mock.terminate() + self.p_mock.wait() + ++ def assertEventually(self, condition, message=None, timeout=50): ++ '''Assert that condition function eventually returns True. ++ ++ Timeout is in deciseconds, defaulting to 50 (5 seconds). message is ++ printed on failure. ++ ''' ++ while timeout >= 0: ++ context = GLib.MainContext.default() ++ while context.iteration(False): ++ pass ++ if condition(): ++ break ++ timeout -= 1 ++ time.sleep(0.1) ++ else: ++ self.fail(message or 'timed out waiting for ' + str(condition)) ++ + def portal_memory_warning_cb(self, monitor, level): + self.last_warning = level + self.main_context.wakeup() +@@ -100,21 +117,11 @@ try: + + self.dbusmock.EmitWarning(100) + # Wait 2 seconds or until warning +- timeout = 2 +- while timeout > 0 and self.last_warning != 100: +- time.sleep(0.5) +- timeout -= 0.5 +- self.main_context.iteration(False) +- self.assertEqual(self.last_warning, 100) ++ self.assertEventually(self.last_warning == 100, "'100' low-memory warning not received", 20) + + self.dbusmock.EmitWarning(255) + # Wait 2 seconds or until warning +- timeout = 2 +- while timeout > 0 and self.last_warning != 255: +- time.sleep(0.5) +- timeout -= 0.5 +- self.main_context.iteration(False) +- self.assertEqual(self.last_warning, 255) ++ self.assertEventually(self.last_warning == 255, "'255' low-memory warning not received", 20) + + except ImportError as e: + @unittest.skip("Cannot import %s" % e.name) +-- +GitLab + diff --git a/2291.patch b/2291.patch new file mode 100644 index 0000000000000000000000000000000000000000..2e4e44d5e2796d38f4ad97c20f13a37930c46307 --- /dev/null +++ b/2291.patch @@ -0,0 +1,129 @@ +From f419966808475cb6c0f0ba2f63967876218ffdaf Mon Sep 17 00:00:00 2001 +From: Julian Andres Klode +Date: Tue, 12 Oct 2021 12:01:50 +0200 +Subject: [PATCH 1/2] gnetworkmonitornm: Stop using removed PropertiesChanged + signal + +Use the org.freedesktop.DBus.Properties interface to listen +to PropertiesChanged signals on /org/freedesktop/NetworkManager. + +NetworkManager used to provide its own legacy PropertiesChanged +signal, but that was dropped in +https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/853 + +This requires NetworkManager >= 1.2 (2016) + +Fixes: #2505 +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1946196 +--- + gio/gnetworkmonitornm.c | 29 +++++++---------------------- + 1 file changed, 7 insertions(+), 22 deletions(-) + +diff --git a/gio/gnetworkmonitornm.c b/gio/gnetworkmonitornm.c +index 5a36a0ba1..6a6d1d666 100644 +--- a/gio/gnetworkmonitornm.c ++++ b/gio/gnetworkmonitornm.c +@@ -267,29 +267,14 @@ update_cached_property (GDBusProxy *proxy, + } + + static void +-proxy_signal_cb (GDBusProxy *proxy, +- const gchar *sender_name, +- const gchar *signal_name, +- GVariant *parameters, +- GNetworkMonitorNM *nm) ++proxy_properties_changed_cb (GDBusProxy *proxy, ++ GVariant *changed_properties, ++ GStrv invalidated_properties, ++ GNetworkMonitorNM *nm) + { +- GVariant *asv; + GVariantDict *dict; + +- if (g_strcmp0 (signal_name, "PropertiesChanged") != 0) +- return; +- +- g_variant_get (parameters, "(@a{sv})", &asv); +- if (!asv) +- return; +- +- dict = g_variant_dict_new (asv); +- g_variant_unref (asv); +- if (!dict) +- { +- g_warning ("Failed to handle PropertiesChanged signal from NetworkManager"); +- return; +- } ++ dict = g_variant_dict_new (changed_properties); + + update_cached_property (nm->priv->proxy, "Connectivity", dict); + +@@ -361,8 +346,8 @@ g_network_monitor_nm_initable_init (GInitable *initable, + return FALSE; + } + +- nm->priv->signal_id = g_signal_connect (G_OBJECT (proxy), "g-signal", +- G_CALLBACK (proxy_signal_cb), nm); ++ nm->priv->signal_id = g_signal_connect (G_OBJECT (proxy), "g-properties-changed", ++ G_CALLBACK (proxy_properties_changed_cb), nm); + nm->priv->proxy = proxy; + sync_properties (nm, FALSE); + +-- +GitLab + + +From 643fc7ea49e818310f6b3f6e4ebe621c7a4d6bd7 Mon Sep 17 00:00:00 2001 +From: Julian Andres Klode +Date: Tue, 12 Oct 2021 17:31:42 +0200 +Subject: [PATCH 2/2] gnetworkmonitornm: Do not re-update cached property + +GDBusProxy already takes care of updating the cached property +before emitting the signal, so there is no need to do this +a second time ourselves. +--- + gio/gnetworkmonitornm.c | 22 ---------------------- + 1 file changed, 22 deletions(-) + +diff --git a/gio/gnetworkmonitornm.c b/gio/gnetworkmonitornm.c +index 6a6d1d666..a8040fb36 100644 +--- a/gio/gnetworkmonitornm.c ++++ b/gio/gnetworkmonitornm.c +@@ -252,34 +252,12 @@ sync_properties (GNetworkMonitorNM *nm, + } + } + +-static void +-update_cached_property (GDBusProxy *proxy, +- const char *property_name, +- GVariantDict *dict) +-{ +- GVariant *v; +- +- v = g_variant_dict_lookup_value (dict, property_name, NULL); +- if (!v) +- return; +- g_dbus_proxy_set_cached_property (proxy, property_name, v); +- g_variant_unref (v); +-} +- + static void + proxy_properties_changed_cb (GDBusProxy *proxy, + GVariant *changed_properties, + GStrv invalidated_properties, + GNetworkMonitorNM *nm) + { +- GVariantDict *dict; +- +- dict = g_variant_dict_new (changed_properties); +- +- update_cached_property (nm->priv->proxy, "Connectivity", dict); +- +- g_variant_dict_unref (dict); +- + sync_properties (nm, TRUE); + } + +-- +GitLab + diff --git a/2435.patch b/2435.patch new file mode 100644 index 0000000000000000000000000000000000000000..862503be6d0a22f3a93b75bb5e40092f619534a2 --- /dev/null +++ b/2435.patch @@ -0,0 +1,132 @@ +From a879d08e912a4421786b44af479f94f7b4503f5a Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Mon, 17 Jan 2022 15:27:24 +0000 +Subject: [PATCH] gspawn: Report errors with closing file descriptors between + fork/exec +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If a seccomp policy is set up incorrectly so that it returns `EPERM` for +`close_range()` rather than `ENOSYS` due to it not being recognised, no +error would previously be reported from GLib, but some file descriptors +wouldn’t be closed, and that would cause a hung zombie process. The +zombie process would be waiting for one half of a socket to be closed. + +Fix that by correctly propagating errors from `close_range()` back to the +parent process so they can be reported correctly. + +Distributions which aren’t yet carrying the Docker fix to correctly +return `ENOSYS` from unrecognised syscalls may want to temporarily carry +an additional patch to fall back to `safe_fdwalk()` if `close_range()` +fails with `EPERM`. This change will not be accepted upstream as `EPERM` +is not the right error for `close_range()` to be returning. + +Signed-off-by: Philip Withnall + +Fixes: #2580 +--- + glib/gspawn.c | 35 ++++++++++++++++++++++++++--------- + 1 file changed, 26 insertions(+), 9 deletions(-) + +diff --git a/glib/gspawn.c b/glib/gspawn.c +index c2fe306dc..9c2f7ba7b 100644 +--- a/glib/gspawn.c ++++ b/glib/gspawn.c +@@ -1457,8 +1457,10 @@ safe_fdwalk (int (*cb)(void *data, int fd), void *data) + } + + /* This function is called between fork() and exec() and hence must be +- * async-signal-safe (see signal-safety(7)). */ +-static void ++ * async-signal-safe (see signal-safety(7)). ++ * ++ * On failure, `-1` will be returned and errno will be set. */ ++static int + safe_closefrom (int lowfd) + { + #if defined(__FreeBSD__) || defined(__OpenBSD__) +@@ -1472,6 +1474,7 @@ safe_closefrom (int lowfd) + * should be safe to use. + */ + (void) closefrom (lowfd); ++ return 0; + #elif defined(__DragonFly__) + /* It is unclear whether closefrom function included in DragonFlyBSD libc_r + * is safe to use because it calls a lot of library functions. It is also +@@ -1479,12 +1482,13 @@ safe_closefrom (int lowfd) + * direct system call here ourselves to avoid possible issues. + */ + (void) syscall (SYS_closefrom, lowfd); ++ return 0; + #elif defined(F_CLOSEM) + /* NetBSD and AIX have a special fcntl command which does the same thing as + * closefrom. NetBSD also includes closefrom function, which seems to be a + * simple wrapper of the fcntl command. + */ +- (void) fcntl (lowfd, F_CLOSEM); ++ return fcntl (lowfd, F_CLOSEM); + #else + + #if defined(HAVE_CLOSE_RANGE) +@@ -1494,9 +1498,11 @@ safe_closefrom (int lowfd) + * + * Handle ENOSYS in case it’s supported in libc but not the kernel; if so, + * fall back to safe_fdwalk(). */ +- if (close_range (lowfd, G_MAXUINT, 0) != 0 && errno == ENOSYS) ++ int ret = close_range (lowfd, G_MAXUINT, 0); ++ if (ret == 0 || errno != ENOSYS) ++ return ret; + #endif /* HAVE_CLOSE_RANGE */ +- (void) safe_fdwalk (close_func, GINT_TO_POINTER (lowfd)); ++ return safe_fdwalk (close_func, GINT_TO_POINTER (lowfd)); + #endif + } + +@@ -1534,7 +1540,8 @@ enum + CHILD_EXEC_FAILED, + CHILD_OPEN_FAILED, + CHILD_DUP2_FAILED, +- CHILD_FORK_FAILED ++ CHILD_FORK_FAILED, ++ CHILD_CLOSE_FAILED, + }; + + /* This function is called between fork() and exec() and hence must be +@@ -1650,12 +1657,14 @@ do_exec (gint child_err_report_fd, + if (safe_dup2 (child_err_report_fd, 3) < 0) + write_err_and_exit (child_err_report_fd, CHILD_DUP2_FAILED); + set_cloexec (GINT_TO_POINTER (0), 3); +- safe_closefrom (4); ++ if (safe_closefrom (4) < 0) ++ write_err_and_exit (child_err_report_fd, CHILD_CLOSE_FAILED); + child_err_report_fd = 3; + } + else + { +- safe_fdwalk (set_cloexec, GINT_TO_POINTER (3)); ++ if (safe_fdwalk (set_cloexec, GINT_TO_POINTER (3)) < 0) ++ write_err_and_exit (child_err_report_fd, CHILD_CLOSE_FAILED); + } + } + else +@@ -2446,7 +2455,15 @@ fork_exec (gboolean intermediate_child, + _("Failed to fork child process (%s)"), + g_strerror (buf[1])); + break; +- ++ ++ case CHILD_CLOSE_FAILED: ++ g_set_error (error, ++ G_SPAWN_ERROR, ++ G_SPAWN_ERROR_FAILED, ++ _("Failed to close file descriptor for child process (%s)"), ++ g_strerror (buf[1])); ++ break; ++ + default: + g_set_error (error, + G_SPAWN_ERROR, +-- +2.34.1 + diff --git a/309.patch b/309.patch deleted file mode 100644 index eb5ed238e3e490aa784811b4695ab54c92557317..0000000000000000000000000000000000000000 --- a/309.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 64b76c7ca5cf5b4ede2f4b423114f46141890e1e Mon Sep 17 00:00:00 2001 -From: Robert Ancell -Date: Fri, 7 Sep 2018 10:19:05 +1200 -Subject: [PATCH] codegen: Change pointer casting to remove type-punning - warnings - -The existing code was generating code with undefined results that modern compilers warn about: - -accounts-generated.c:204:23: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] - (GDBusArgInfo **) &_accounts_accounts_method_info_list_cached_users_OUT_ARG_pointers, ---- - gio/gdbus-2.0/codegen/codegen.py | 22 +++++++++++----------- - 1 file changed, 11 insertions(+), 11 deletions(-) - -diff --git a/gio/gdbus-2.0/codegen/codegen.py b/gio/gdbus-2.0/codegen/codegen.py -index e74131cdb..0d95cdcda 100644 ---- a/gio/gdbus-2.0/codegen/codegen.py -+++ b/gio/gdbus-2.0/codegen/codegen.py -@@ -1129,10 +1129,10 @@ class CodeGenerator: - '\n') - - if len(args) > 0: -- self.outfile.write('static const _ExtendedGDBusArgInfo * const %s_pointers[] =\n' -+ self.outfile.write('static const GDBusArgInfo * const %s_pointers[] =\n' - '{\n'%(prefix)) - for a in args: -- self.outfile.write(' &%s_%s,\n'%(prefix, a.name)) -+ self.outfile.write(' &%s_%s.parent_struct,\n'%(prefix, a.name)) - self.outfile.write(' NULL\n' - '};\n' - '\n') -@@ -1175,10 +1175,10 @@ class CodeGenerator: - self.outfile.write('};\n' - '\n') - -- self.outfile.write('static const _ExtendedGDBusMethodInfo * const _%s_method_info_pointers[] =\n' -+ self.outfile.write('static const GDBusMethodInfo * const _%s_method_info_pointers[] =\n' - '{\n'%(i.name_lower)) - for m in i.methods: -- self.outfile.write(' &_%s_method_info_%s,\n'%(i.name_lower, m.name_lower)) -+ self.outfile.write(' &_%s_method_info_%s.parent_struct,\n'%(i.name_lower, m.name_lower)) - self.outfile.write(' NULL\n' - '};\n' - '\n') -@@ -1209,10 +1209,10 @@ class CodeGenerator: - self.outfile.write('};\n' - '\n') - -- self.outfile.write('static const _ExtendedGDBusSignalInfo * const _%s_signal_info_pointers[] =\n' -+ self.outfile.write('static const GDBusSignalInfo * const _%s_signal_info_pointers[] =\n' - '{\n'%(i.name_lower)) - for s in i.signals: -- self.outfile.write(' &_%s_signal_info_%s,\n'%(i.name_lower, s.name_lower)) -+ self.outfile.write(' &_%s_signal_info_%s.parent_struct,\n'%(i.name_lower, s.name_lower)) - self.outfile.write(' NULL\n' - '};\n' - '\n') -@@ -1251,10 +1251,10 @@ class CodeGenerator: - self.outfile.write('};\n' - '\n') - -- self.outfile.write('static const _ExtendedGDBusPropertyInfo * const _%s_property_info_pointers[] =\n' -+ self.outfile.write('static const GDBusPropertyInfo * const _%s_property_info_pointers[] =\n' - '{\n'%(i.name_lower)) - for p in i.properties: -- self.outfile.write(' &_%s_property_info_%s,\n'%(i.name_lower, p.name_lower)) -+ self.outfile.write(' &_%s_property_info_%s.parent_struct,\n'%(i.name_lower, p.name_lower)) - self.outfile.write(' NULL\n' - '};\n' - '\n') -@@ -1948,7 +1948,7 @@ class CodeGenerator: - self.outfile.write(' const _ExtendedGDBusPropertyInfo *info;\n' - ' GVariant *variant;\n' - ' g_assert (prop_id != 0 && prop_id - 1 < %d);\n' -- ' info = _%s_property_info_pointers[prop_id - 1];\n' -+ ' info = (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1];\n' - ' variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name);\n' - ' if (info->use_gvariant)\n' - ' {\n' -@@ -2001,7 +2001,7 @@ class CodeGenerator: - self.outfile.write(' const _ExtendedGDBusPropertyInfo *info;\n' - ' GVariant *variant;\n' - ' g_assert (prop_id != 0 && prop_id - 1 < %d);\n' -- ' info = _%s_property_info_pointers[prop_id - 1];\n' -+ ' info = (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1];\n' - ' variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature));\n' - ' g_dbus_proxy_call (G_DBUS_PROXY (object),\n' - ' "org.freedesktop.DBus.Properties.Set",\n' -@@ -2887,7 +2887,7 @@ class CodeGenerator: - ' if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1]))\n' - ' {\n' - ' if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL)\n' -- ' _%s_schedule_emit_changed (skeleton, _%s_property_info_pointers[prop_id - 1], prop_id, &skeleton->priv->properties[prop_id - 1]);\n' -+ ' _%s_schedule_emit_changed (skeleton, (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1], prop_id, &skeleton->priv->properties[prop_id - 1]);\n' - ' g_value_copy (value, &skeleton->priv->properties[prop_id - 1]);\n' - ' g_object_notify_by_pspec (object, pspec);\n' - ' }\n' --- -2.19.1 - diff --git a/409.patch b/409.patch deleted file mode 100644 index 7a2aea3553361b2ef7f5e9d1f78431c180d0a692..0000000000000000000000000000000000000000 --- a/409.patch +++ /dev/null @@ -1,56 +0,0 @@ -From d7233ef81e575e84d831414605ba6368394d88b5 Mon Sep 17 00:00:00 2001 -From: Colin Walters -Date: Mon, 15 Oct 2018 21:50:31 +0000 -Subject: [PATCH] build-sys: Pass CFLAGS to $(DTRACE) - -Fedora is using https://fedoraproject.org/wiki/Changes/Annobin -to try to ensure that all objects are built with hardening flags. -Pass down `CFLAGS` to ensure the SystemTap objects use them. ---- - gio/Makefile.am | 2 +- - glib/Makefile.am | 2 +- - gobject/Makefile.am | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/gio/Makefile.am b/gio/Makefile.am -index fc0b91855..05b20cdef 100644 ---- a/gio/Makefile.am -+++ b/gio/Makefile.am -@@ -896,7 +896,7 @@ gio_probes.h: gio_probes.d - < $@.tmp > $@ && rm -f $@.tmp - - gio_probes.lo: gio_probes.d -- $(AM_V_GEN) $(LIBTOOL) --mode=compile $(AM_V_lt) --tag=CC $(DTRACE) -G -s $< -o $@ -+ $(AM_V_GEN) $(LIBTOOL) --mode=compile $(AM_V_lt) --tag=CC env CFLAGS="$(CFLAGS)" $(DTRACE) -G -s $< -o $@ - - BUILT_SOURCES += gio_probes.h gio_probes.lo - CLEANFILES += gio_probes.h gio_probes.h.tmp -diff --git a/glib/Makefile.am b/glib/Makefile.am -index 90d33d082..39163aa7f 100644 ---- a/glib/Makefile.am -+++ b/glib/Makefile.am -@@ -386,7 +386,7 @@ glib_probes.h: glib_probes.d - < $@.tmp > $@ && rm -f $@.tmp - - glib_probes.lo: glib_probes.d -- $(AM_V_GEN) $(LIBTOOL) --mode=compile $(AM_V_lt) --tag=CC $(DTRACE) -G -s $< -o $@ -+ $(AM_V_GEN) $(LIBTOOL) --mode=compile $(AM_V_lt) --tag=CC env CFLAGS="$(CFLAGS)" $(DTRACE) -G -s $< -o $@ - - BUILT_SOURCES += glib_probes.h glib_probes.lo - CLEANFILES += glib_probes.h glib_probes.h.tmp -diff --git a/gobject/Makefile.am b/gobject/Makefile.am -index 4c28acdff..78748e96c 100644 ---- a/gobject/Makefile.am -+++ b/gobject/Makefile.am -@@ -119,7 +119,7 @@ gobject_probes.h: gobject_probes.d - < $@.tmp > $@ && rm -f $@.tmp - - gobject_probes.lo: gobject_probes.d -- $(AM_V_GEN) $(LIBTOOL) --mode=compile $(AM_V_lt) --tag=CC $(DTRACE) -G -s $< -o $@ -+ $(AM_V_GEN) $(LIBTOOL) --mode=compile $(AM_V_lt) --tag=CC env CFLAGS="$(CFLAGS)" $(DTRACE) -G -s $< -o $@ - - BUILT_SOURCES += gobject_probes.h gobject_probes.lo - CLEANFILES += gobject_probes.h --- -2.21.0 - diff --git a/50.patch b/50.patch deleted file mode 100644 index 8ac8b87c715d2258457d6571bb927c4ba3243203..0000000000000000000000000000000000000000 --- a/50.patch +++ /dev/null @@ -1,27 +0,0 @@ -From fe803a6da0c7d73cd689d905258847384e11d1fd Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 17 Dec 2018 14:36:07 -0500 -Subject: [PATCH] gdbus unix addresses test: don't g_debug when also testing - stdout - -At the moment the gdbus-unix-addresses test will fail if -G_MESSAGES_DEBUG is set, since the test checks stdout, and the -test has a g_debug call. - -This commit drops the g_debug call, which isn't that useful anyway. ---- - gio/tests/gdbus-unix-addresses.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/gio/tests/gdbus-unix-addresses.c b/gio/tests/gdbus-unix-addresses.c -index e08328711..d020edd06 100644 ---- a/gio/tests/gdbus-unix-addresses.c -+++ b/gio/tests/gdbus-unix-addresses.c -@@ -106,7 +106,6 @@ set_up_mock_dbus_launch (void) - { - path = g_strconcat (g_test_get_dir (G_TEST_BUILT), ":", - g_getenv ("PATH"), NULL); -- g_debug ("PATH=%s", path); - g_setenv ("PATH", path, TRUE); - - /* libdbus won't even try X11 autolaunch if DISPLAY is unset; GDBus diff --git a/532.patch b/532.patch deleted file mode 100644 index 09e2c84ab39c536fca7396b4fc97802d0eca0207..0000000000000000000000000000000000000000 --- a/532.patch +++ /dev/null @@ -1,613 +0,0 @@ -From aea538fe703652fd0a39b2ac9185133849cfdcc4 Mon Sep 17 00:00:00 2001 -From: Thomas Jost -Date: Thu, 13 Dec 2018 03:06:02 -0800 -Subject: [PATCH] gdbus-codegen: honor "Property.EmitsChangedSignal" - annotations - -Co-Authored-by: Andy Holmes ---- - gio/gdbus-2.0/codegen/codegen.py | 18 ++++++++++----- - gio/gdbus-2.0/codegen/dbustypes.py | 7 ++++++ - gio/tests/gdbus-test-codegen.c | 36 +++++++++++++++++++++++++----- - gio/tests/test-codegen.xml | 6 +++++ - 4 files changed, 56 insertions(+), 11 deletions(-) - -diff --git a/gio/gdbus-2.0/codegen/codegen.py b/gio/gdbus-2.0/codegen/codegen.py -index f6892af95..442bd3f5d 100644 ---- a/gio/gdbus-2.0/codegen/codegen.py -+++ b/gio/gdbus-2.0/codegen/codegen.py -@@ -638,61 +638,62 @@ class CodeGenerator: - '# include \n' - '#endif\n' - '\n') - - self.outfile.write('typedef struct\n' - '{\n' - ' GDBusArgInfo parent_struct;\n' - ' gboolean use_gvariant;\n' - '} _ExtendedGDBusArgInfo;\n' - '\n') - - self.outfile.write('typedef struct\n' - '{\n' - ' GDBusMethodInfo parent_struct;\n' - ' const gchar *signal_name;\n' - ' gboolean pass_fdlist;\n' - '} _ExtendedGDBusMethodInfo;\n' - '\n') - - self.outfile.write('typedef struct\n' - '{\n' - ' GDBusSignalInfo parent_struct;\n' - ' const gchar *signal_name;\n' - '} _ExtendedGDBusSignalInfo;\n' - '\n') - - self.outfile.write('typedef struct\n' - '{\n' - ' GDBusPropertyInfo parent_struct;\n' - ' const gchar *hyphen_name;\n' -- ' gboolean use_gvariant;\n' -+ ' guint use_gvariant : 1;\n' -+ ' guint emits_changed_signal : 1;\n' - '} _ExtendedGDBusPropertyInfo;\n' - '\n') - - self.outfile.write('typedef struct\n' - '{\n' - ' GDBusInterfaceInfo parent_struct;\n' - ' const gchar *hyphen_name;\n' - '} _ExtendedGDBusInterfaceInfo;\n' - '\n') - - self.outfile.write('typedef struct\n' - '{\n' - ' const _ExtendedGDBusPropertyInfo *info;\n' - ' guint prop_id;\n' - ' GValue orig_value; /* the value before the change */\n' - '} ChangedProperty;\n' - '\n' - 'static void\n' - '_changed_property_free (ChangedProperty *data)\n' - '{\n' - ' g_value_unset (&data->orig_value);\n' - ' g_free (data);\n' - '}\n' - '\n') - - self.outfile.write('static gboolean\n' - '_g_strv_equal0 (gchar **a, gchar **b)\n' - '{\n' - ' gboolean ret = FALSE;\n' - ' guint n;\n' -@@ -933,63 +934,67 @@ class CodeGenerator: - '\n') - - # --- - - if len(i.properties) > 0: - for p in i.properties: - if p.readable and p.writable: - access = 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE' - elif p.readable: - access = 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE' - elif p.writable: - access = 'G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE' - else: - access = 'G_DBUS_PROPERTY_INFO_FLAGS_NONE' - num_anno = self.generate_annotations('_%s_property_%s_annotation_info'%(i.name_lower, p.name_lower), p.annotations) - self.outfile.write('static const _ExtendedGDBusPropertyInfo _%s_property_info_%s =\n' - '{\n' - ' {\n' - ' -1,\n' - ' (gchar *) "%s",\n' - ' (gchar *) "%s",\n' - ' %s,\n'%(i.name_lower, p.name_lower, p.name, p.arg.signature, access)) - if num_anno == 0: - self.outfile.write(' NULL\n') - else: - self.outfile.write(' (GDBusAnnotationInfo **) &_%s_property_%s_annotation_info_pointers\n'%(i.name_lower, p.name_lower)) - self.outfile.write(' },\n' - ' "%s",\n' - %(p.name_hyphen)) - if not utils.lookup_annotation(p.annotations, 'org.gtk.GDBus.C.ForceGVariant'): -- self.outfile.write(' FALSE\n') -+ self.outfile.write(' FALSE,\n') - else: -+ self.outfile.write(' TRUE,\n') -+ if p.emits_changed_signal: - self.outfile.write(' TRUE\n') -+ else: -+ self.outfile.write(' FALSE\n') - self.outfile.write('};\n' - '\n') - - self.outfile.write('static const GDBusPropertyInfo * const _%s_property_info_pointers[] =\n' - '{\n'%(i.name_lower)) - for p in i.properties: - self.outfile.write(' &_%s_property_info_%s.parent_struct,\n'%(i.name_lower, p.name_lower)) - self.outfile.write(' NULL\n' - '};\n' - '\n') - - num_anno = self.generate_annotations('_%s_annotation_info'%(i.name_lower), i.annotations) - self.outfile.write('static const _ExtendedGDBusInterfaceInfo _%s_interface_info =\n' - '{\n' - ' {\n' - ' -1,\n' - ' (gchar *) "%s",\n'%(i.name_lower, i.name)) - if len(i.methods) == 0: - self.outfile.write(' NULL,\n') - else: - self.outfile.write(' (GDBusMethodInfo **) &_%s_method_info_pointers,\n'%(i.name_lower)) - if len(i.signals) == 0: - self.outfile.write(' NULL,\n') - else: - self.outfile.write(' (GDBusSignalInfo **) &_%s_signal_info_pointers,\n'%(i.name_lower)) - if len(i.properties) == 0: - self.outfile.write(' NULL,\n') - else: - self.outfile.write(' (GDBusPropertyInfo **) &_%s_property_info_pointers,\n'%(i.name_lower)) - if num_anno == 0: -@@ -2568,68 +2573,71 @@ class CodeGenerator: - # this allows use of g_object_freeze_notify()/g_object_thaw_notify() ... - # This is useful when updating several properties from another thread than - # where the idle will be emitted from - self.outfile.write('static void\n' - '%s_skeleton_notify (GObject *object,\n' - ' GParamSpec *pspec G_GNUC_UNUSED)\n' - '{\n' - ' %sSkeleton *skeleton = %s%s_SKELETON (object);\n' - ' g_mutex_lock (&skeleton->priv->lock);\n' - ' if (skeleton->priv->changed_properties != NULL &&\n' - ' skeleton->priv->changed_properties_idle_source == NULL)\n' - ' {\n' - ' skeleton->priv->changed_properties_idle_source = g_idle_source_new ();\n' - ' g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);\n' - ' g_source_set_callback (skeleton->priv->changed_properties_idle_source, _%s_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);\n' - ' g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _%s_emit_changed");\n' - ' g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);\n' - ' g_source_unref (skeleton->priv->changed_properties_idle_source);\n' - ' }\n' - ' g_mutex_unlock (&skeleton->priv->lock);\n' - '}\n' - '\n' - %(i.name_lower, i.camel_name, i.ns_upper, i.name_upper, i.name_lower, i.name_lower)) - - self.outfile.write('static void\n' - '%s_skeleton_set_property (GObject *object,\n' - ' guint prop_id,\n' - ' const GValue *value,\n' - ' GParamSpec *pspec)\n' - '{\n'%(i.name_lower)) -- self.outfile.write(' %sSkeleton *skeleton = %s%s_SKELETON (object);\n' -+ self.outfile.write(' const _ExtendedGDBusPropertyInfo *info;\n' -+ ' %sSkeleton *skeleton = %s%s_SKELETON (object);\n' - ' g_assert (prop_id != 0 && prop_id - 1 < %d);\n' -+ ' info = (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1];\n' - ' g_mutex_lock (&skeleton->priv->lock);\n' - ' g_object_freeze_notify (object);\n' - ' if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1]))\n' - ' {\n' -- ' if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL)\n' -- ' _%s_schedule_emit_changed (skeleton, (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1], prop_id, &skeleton->priv->properties[prop_id - 1]);\n' -+ ' if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL &&\n' -+ ' info->emits_changed_signal)\n' -+ ' _%s_schedule_emit_changed (skeleton, info, prop_id, &skeleton->priv->properties[prop_id - 1]);\n' - ' g_value_copy (value, &skeleton->priv->properties[prop_id - 1]);\n' - ' g_object_notify_by_pspec (object, pspec);\n' - ' }\n' - ' g_mutex_unlock (&skeleton->priv->lock);\n' - ' g_object_thaw_notify (object);\n' - %(i.camel_name, i.ns_upper, i.name_upper, len(i.properties), i.name_lower, i.name_lower)) - self.outfile.write('}\n' - '\n') - - self.outfile.write('static void\n' - '%s_skeleton_init (%sSkeleton *skeleton)\n' - '{\n' - '#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38\n' - ' skeleton->priv = %s_skeleton_get_instance_private (skeleton);\n' - '#else\n' - ' skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, %sTYPE_%s_SKELETON, %sSkeletonPrivate);\n' - '#endif\n\n' - %(i.name_lower, i.camel_name, - i.name_lower, - i.ns_upper, i.name_upper, i.camel_name)) - self.outfile.write(' g_mutex_init (&skeleton->priv->lock);\n') - self.outfile.write(' skeleton->priv->context = g_main_context_ref_thread_default ();\n') - if len(i.properties) > 0: - self.outfile.write(' skeleton->priv->properties = g_new0 (GValue, %d);\n'%(len(i.properties))) - n = 0 - for p in i.properties: - self.outfile.write(' g_value_init (&skeleton->priv->properties[%d], %s);\n'%(n, p.arg.gtype)) - n += 1 - self.outfile.write('}\n' - '\n') -diff --git a/gio/gdbus-2.0/codegen/dbustypes.py b/gio/gdbus-2.0/codegen/dbustypes.py -index bfc69f596..359880ff7 100644 ---- a/gio/gdbus-2.0/codegen/dbustypes.py -+++ b/gio/gdbus-2.0/codegen/dbustypes.py -@@ -300,89 +300,96 @@ class Signal: - arg_count = 0 - for a in self.args: - a.post_process(interface_prefix, cns, cns_upper, cns_lower, arg_count) - arg_count += 1 - - if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true': - self.deprecated = True - - class Property: - def __init__(self, name, signature, access): - self.name = name - self.signature = signature - self.access = access - self.annotations = [] - self.arg = Arg('value', self.signature) - self.arg.annotations = self.annotations - self.readable = False - self.writable = False - if self.access == 'readwrite': - self.readable = True - self.writable = True - elif self.access == 'read': - self.readable = True - elif self.access == 'write': - self.writable = True - else: - print_error('Invalid access type "{}"'.format(self.access)) - self.doc_string = '' - self.since = '' - self.deprecated = False -+ self.emits_changed_signal = True - - def post_process(self, interface_prefix, cns, cns_upper, cns_lower, containing_iface): - if len(self.doc_string) == 0: - self.doc_string = utils.lookup_docs(self.annotations) - if len(self.since) == 0: - self.since = utils.lookup_since(self.annotations) - if len(self.since) == 0: - self.since = containing_iface.since - - name = self.name - overridden_name = utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.Name') - if utils.is_ugly_case(overridden_name): - self.name_lower = overridden_name.lower() - else: - if overridden_name: - name = overridden_name - self.name_lower = utils.camel_case_to_uscore(name).lower().replace('-', '_') - self.name_hyphen = self.name_lower.replace('_', '-') - # don't clash with the GType getter, e.g.: GType foo_bar_get_type (void); G_GNUC_CONST - if self.name_lower == 'type': - self.name_lower = 'type_' - - # recalculate arg - self.arg.annotations = self.annotations - self.arg.post_process(interface_prefix, cns, cns_upper, cns_lower, 0) - - if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true': - self.deprecated = True - -+ # FIXME: for now we only support 'false' and 'const' on the signal itself, see #674913 and -+ # http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format -+ # for details -+ if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Property.EmitsChangedSignal') in ('false', 'const'): -+ self.emits_changed_signal = False -+ - class Interface: - def __init__(self, name): - self.name = name - self.methods = [] - self.signals = [] - self.properties = [] - self.annotations = [] - self.doc_string = '' - self.doc_string_brief = '' - self.since = '' - self.deprecated = False - - def post_process(self, interface_prefix, c_namespace): - if len(self.doc_string) == 0: - self.doc_string = utils.lookup_docs(self.annotations) - if len(self.doc_string_brief) == 0: - self.doc_string_brief = utils.lookup_brief_docs(self.annotations) - if len(self.since) == 0: - self.since = utils.lookup_since(self.annotations) - - if len(c_namespace) > 0: - if utils.is_ugly_case(c_namespace): - cns = c_namespace.replace('_', '') - cns_upper = c_namespace.upper() + '_' - cns_lower = c_namespace.lower() + '_' - else: - cns = c_namespace - cns_upper = utils.camel_case_to_uscore(c_namespace).upper() + '_' - cns_lower = utils.camel_case_to_uscore(c_namespace).lower() + '_' - else: -diff --git a/gio/tests/gdbus-test-codegen.c b/gio/tests/gdbus-test-codegen.c -index 1c4e83c4c..c906d05ae 100644 ---- a/gio/tests/gdbus-test-codegen.c -+++ b/gio/tests/gdbus-test-codegen.c -@@ -1740,103 +1740,127 @@ on_object_proxy_added (GDBusObjectManagerClient *manager, - gpointer user_data) - { - OMData *om_data = user_data; - om_data->num_object_proxy_added_signals += 1; - g_signal_connect (object_proxy, - "interface-added", - G_CALLBACK (on_interface_added), - om_data); - g_signal_connect (object_proxy, - "interface-removed", - G_CALLBACK (on_interface_removed), - om_data); - } - - static void - on_object_proxy_removed (GDBusObjectManagerClient *manager, - GDBusObjectProxy *object_proxy, - gpointer user_data) - { - OMData *om_data = user_data; - om_data->num_object_proxy_removed_signals += 1; - g_assert_cmpint (g_signal_handlers_disconnect_by_func (object_proxy, - G_CALLBACK (on_interface_added), - om_data), ==, 1); - g_assert_cmpint (g_signal_handlers_disconnect_by_func (object_proxy, - G_CALLBACK (on_interface_removed), - om_data), ==, 1); - } - - static void --property_d_changed (GObject *object, -- GParamSpec *pspec, -- gpointer user_data) -+property_changed (GObject *object, -+ GParamSpec *pspec, -+ gpointer user_data) - { - gboolean *changed = user_data; - - *changed = TRUE; - } - - static void - om_check_property_and_signal_emission (GMainLoop *loop, - FooiGenBar *skeleton, - FooiGenBar *proxy) - { - gboolean d_changed = FALSE; -+ gboolean quiet_changed = FALSE; -+ gboolean quiet_too_changed = FALSE; - guint handler; - - /* First PropertiesChanged */ - g_assert_cmpint (foo_igen_bar_get_i (skeleton), ==, 0); - g_assert_cmpint (foo_igen_bar_get_i (proxy), ==, 0); - foo_igen_bar_set_i (skeleton, 1); - _g_assert_property_notify (proxy, "i"); - g_assert_cmpint (foo_igen_bar_get_i (skeleton), ==, 1); - g_assert_cmpint (foo_igen_bar_get_i (proxy), ==, 1); - - /* Double-check the gdouble case */ - g_assert_cmpfloat (foo_igen_bar_get_d (skeleton), ==, 0.0); - g_assert_cmpfloat (foo_igen_bar_get_d (proxy), ==, 0.0); - foo_igen_bar_set_d (skeleton, 1.0); - _g_assert_property_notify (proxy, "d"); - - /* Verify that re-setting it to the same value doesn't cause a - * notify on the proxy, by taking advantage of the fact that - * notifications are serialized. - */ - handler = g_signal_connect (proxy, "notify::d", -- G_CALLBACK (property_d_changed), &d_changed); -+ G_CALLBACK (property_changed), &d_changed); - foo_igen_bar_set_d (skeleton, 1.0); - foo_igen_bar_set_i (skeleton, 2); - _g_assert_property_notify (proxy, "i"); - g_assert (d_changed == FALSE); - g_signal_handler_disconnect (proxy, handler); - -+ /* Verify that re-setting a property with the "EmitsChangedSignal" -+ * set to false doesn't emit a signal. */ -+ handler = g_signal_connect (proxy, "notify::quiet", -+ G_CALLBACK (property_changed), &quiet_changed); -+ foo_igen_bar_set_quiet (skeleton, "hush!"); -+ foo_igen_bar_set_i (skeleton, 3); -+ _g_assert_property_notify (proxy, "i"); -+ g_assert (quiet_changed == FALSE); -+ g_assert_cmpstr (foo_igen_bar_get_quiet (skeleton), ==, "hush!"); -+ g_signal_handler_disconnect (proxy, handler); -+ -+ /* Also verify that re-setting a property with the "EmitsChangedSignal" -+ * set to 'const' doesn't emit a signal. */ -+ handler = g_signal_connect (proxy, "notify::quiet-too", -+ G_CALLBACK (property_changed), &quiet_changed); -+ foo_igen_bar_set_quiet_too (skeleton, "hush too!"); -+ foo_igen_bar_set_i (skeleton, 4); -+ _g_assert_property_notify (proxy, "i"); -+ g_assert (quiet_too_changed == FALSE); -+ g_assert_cmpstr (foo_igen_bar_get_quiet_too (skeleton), ==, "hush too!"); -+ g_signal_handler_disconnect (proxy, handler); -+ - /* Then just a regular signal */ - foo_igen_bar_emit_another_signal (skeleton, "word"); - _g_assert_signal_received (proxy, "another-signal"); - } - - static void - check_object_manager (void) - { - FooiGenObjectSkeleton *o = NULL; - FooiGenObjectSkeleton *o2 = NULL; - FooiGenObjectSkeleton *o3 = NULL; - GDBusInterfaceSkeleton *i; - GDBusConnection *c; - GDBusObjectManagerServer *manager = NULL; - GDBusNodeInfo *info; - GError *error; - GMainLoop *loop; - OMData *om_data = NULL; - guint om_signal_id = -1; - GDBusObjectManager *pm = NULL; - GList *object_proxies; - GList *proxies; - GDBusObject *op; - GDBusProxy *p; - FooiGenBar *bar_skeleton; - GDBusInterface *iface; - gchar *path, *name, *name_owner; - GDBusConnection *c2; - GDBusObjectManagerClientFlags flags; - -@@ -2124,73 +2148,73 @@ check_object_manager (void) - "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}},)"); - - /* -------------------------------------------------- */ - - /* create a new object with two interfaces */ - o2 = foo_igen_object_skeleton_new ("/managed/second"); - i = G_DBUS_INTERFACE_SKELETON (foo_igen_bar_skeleton_new ()); - bar_skeleton = FOO_IGEN_BAR (i); /* save for later test */ - foo_igen_object_skeleton_set_bar (o2, FOO_IGEN_BAR (i)); - g_clear_object (&i); - i = G_DBUS_INTERFACE_SKELETON (foo_igen_bat_skeleton_new ()); - foo_igen_object_skeleton_set_bat (o2, FOO_IGEN_BAT (i)); - g_clear_object (&i); - /* ... add it */ - g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (o2)); - /* ... check we get the InterfacesAdded with _two_ interfaces */ - om_data->state = 101; - g_main_loop_run (om_data->loop); - g_assert_cmpint (om_data->state, ==, 102); - g_assert_cmpint (om_data->num_object_proxy_added_signals, ==, 5); - g_assert_cmpint (om_data->num_object_proxy_removed_signals, ==, 3); - g_assert_cmpint (om_data->num_interface_added_signals, ==, 1); - g_assert_cmpint (om_data->num_interface_removed_signals, ==, 1); - - /* -------------------------------------------------- */ - - /* Now that we have a couple of objects with interfaces, check - * that ObjectManager.GetManagedObjects() works - */ - om_check_get_all (c, loop, -- "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}, '/managed/second': {'org.project.Bar': {'y': , 'b': , 'n': , 'q': , 'i': <0>, 'u': , 'x': , 't': , 'd': <0.0>, 's': <''>, 'o': , 'g': , 'ay': , 'as': <@as []>, 'aay': <@aay []>, 'ao': <@ao []>, 'ag': <@ag []>, 'FinallyNormalName': <''>, 'ReadonlyProperty': <''>, 'unset_i': <0>, 'unset_d': <0.0>, 'unset_s': <''>, 'unset_o': , 'unset_g': , 'unset_ay': , 'unset_as': <@as []>, 'unset_ao': <@ao []>, 'unset_ag': <@ag []>, 'unset_struct': <(0, 0.0, '', objectpath '/', signature '', @ay [], @as [], @ao [], @ag [])>}, 'org.project.Bat': {'force_i': <0>, 'force_s': <''>, 'force_ay': <@ay []>, 'force_struct': <(0,)>}}},)"); -+ "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}, '/managed/second': {'org.project.Bar': {'y': , 'b': , 'n': , 'q': , 'i': <0>, 'u': , 'x': , 't': , 'd': <0.0>, 's': <''>, 'o': , 'g': , 'ay': , 'as': <@as []>, 'aay': <@aay []>, 'ao': <@ao []>, 'ag': <@ag []>, 'FinallyNormalName': <''>, 'ReadonlyProperty': <''>, 'quiet': <''>, 'quiet_too': <''>, 'unset_i': <0>, 'unset_d': <0.0>, 'unset_s': <''>, 'unset_o': , 'unset_g': , 'unset_ay': , 'unset_as': <@as []>, 'unset_ao': <@ao []>, 'unset_ag': <@ag []>, 'unset_struct': <(0, 0.0, '', objectpath '/', signature '', @ay [], @as [], @ao [], @ag [])>}, 'org.project.Bat': {'force_i': <0>, 'force_s': <''>, 'force_ay': <@ay []>, 'force_struct': <(0,)>}}},)"); - - /* Set connection to NULL, causing everything to be unexported.. verify this.. and - * then set the connection back.. and then check things still work - */ - g_dbus_object_manager_server_set_connection (manager, NULL); - info = introspect (c, g_dbus_connection_get_unique_name (c), "/managed", loop); - g_assert_cmpint (count_interfaces (info), ==, 0); /* nothing */ - g_dbus_node_info_unref (info); - - g_dbus_object_manager_server_set_connection (manager, c); - om_check_get_all (c, loop, -- "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}, '/managed/second': {'org.project.Bar': {'y': , 'b': , 'n': , 'q': , 'i': <0>, 'u': , 'x': , 't': , 'd': <0.0>, 's': <''>, 'o': , 'g': , 'ay': , 'as': <@as []>, 'aay': <@aay []>, 'ao': <@ao []>, 'ag': <@ag []>, 'FinallyNormalName': <''>, 'ReadonlyProperty': <''>, 'unset_i': <0>, 'unset_d': <0.0>, 'unset_s': <''>, 'unset_o': , 'unset_g': , 'unset_ay': , 'unset_as': <@as []>, 'unset_ao': <@ao []>, 'unset_ag': <@ag []>, 'unset_struct': <(0, 0.0, '', objectpath '/', signature '', @ay [], @as [], @ao [], @ag [])>}, 'org.project.Bat': {'force_i': <0>, 'force_s': <''>, 'force_ay': <@ay []>, 'force_struct': <(0,)>}}},)"); -+ "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}, '/managed/second': {'org.project.Bar': {'y': , 'b': , 'n': , 'q': , 'i': <0>, 'u': , 'x': , 't': , 'd': <0.0>, 's': <''>, 'o': , 'g': , 'ay': , 'as': <@as []>, 'aay': <@aay []>, 'ao': <@ao []>, 'ag': <@ag []>, 'FinallyNormalName': <''>, 'ReadonlyProperty': <''>, 'quiet': <''>, 'quiet_too': <''>, 'unset_i': <0>, 'unset_d': <0.0>, 'unset_s': <''>, 'unset_o': , 'unset_g': , 'unset_ay': , 'unset_as': <@as []>, 'unset_ao': <@ao []>, 'unset_ag': <@ag []>, 'unset_struct': <(0, 0.0, '', objectpath '/', signature '', @ay [], @as [], @ao [], @ag [])>}, 'org.project.Bat': {'force_i': <0>, 'force_s': <''>, 'force_ay': <@ay []>, 'force_struct': <(0,)>}}},)"); - - /* Also check that the ObjectManagerClient returns these objects - and - * that they are of the right GType cf. what was requested via - * the generated ::get-proxy-type signal handler - */ - object_proxies = g_dbus_object_manager_get_objects (pm); - g_assert (g_list_length (object_proxies) == 2); - g_list_free_full (object_proxies, g_object_unref); - op = g_dbus_object_manager_get_object (pm, "/managed/first"); - g_assert (op != NULL); - g_assert (FOO_IGEN_IS_OBJECT_PROXY (op)); - g_assert_cmpstr (g_dbus_object_get_object_path (op), ==, "/managed/first"); - proxies = g_dbus_object_get_interfaces (op); - g_assert (g_list_length (proxies) == 1); - g_list_free_full (proxies, g_object_unref); - p = G_DBUS_PROXY (foo_igen_object_get_com_acme_coyote (FOO_IGEN_OBJECT (op))); - g_assert (p != NULL); - g_assert_cmpint (G_TYPE_FROM_INSTANCE (p), ==, FOO_IGEN_TYPE_COM_ACME_COYOTE_PROXY); - g_assert (g_type_is_a (G_TYPE_FROM_INSTANCE (p), FOO_IGEN_TYPE_COM_ACME_COYOTE)); - g_clear_object (&p); - p = (GDBusProxy *) g_dbus_object_get_interface (op, "org.project.NonExisting"); - g_assert (p == NULL); - g_clear_object (&op); - - /* -- */ - op = g_dbus_object_manager_get_object (pm, "/managed/second"); - g_assert (op != NULL); - g_assert (FOO_IGEN_IS_OBJECT_PROXY (op)); - g_assert_cmpstr (g_dbus_object_get_object_path (op), ==, "/managed/second"); - proxies = g_dbus_object_get_interfaces (op); -diff --git a/gio/tests/test-codegen.xml b/gio/tests/test-codegen.xml -index 885a21f77..39d8769c7 100644 ---- a/gio/tests/test-codegen.xml -+++ b/gio/tests/test-codegen.xml -@@ -79,60 +79,66 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ -+ -+ -+ -+ -+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --- -2.21.0 - diff --git a/546.patch b/546.patch deleted file mode 100644 index 13525610e4fe16d0fca1591a469e34ae7f537fd0..0000000000000000000000000000000000000000 --- a/546.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 521f9605e0ab019ec9a493153ca0c8fe4267d665 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 17 Dec 2018 15:46:10 -0500 -Subject: [PATCH] spawn: add shebang line to script - -downstream tools get confused when the script is missing a shebang -line, and having a shebang line doesn't hurt, so add one. ---- - glib/tests/echo-script | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/glib/tests/echo-script b/glib/tests/echo-script -index c732ed910..b609f2d39 100755 ---- a/glib/tests/echo-script -+++ b/glib/tests/echo-script -@@ -1 +1,2 @@ -+#!/bin/sh - echo "echo" --- -2.20.0 - diff --git a/CVE-2019-12450.patch b/CVE-2019-12450.patch deleted file mode 100644 index 6c514e1f8e96ac60dd3b0ec9d69fc615438816fd..0000000000000000000000000000000000000000 --- a/CVE-2019-12450.patch +++ /dev/null @@ -1,53 +0,0 @@ -From d8f8f4d637ce43f8699ba94c9b7648beda0ca174 Mon Sep 17 00:00:00 2001 -From: Ondrej Holy -Date: Thu, 23 May 2019 10:41:53 +0200 -Subject: [PATCH] gfile: Limit access to files when copying - -file_copy_fallback creates new files with default permissions and -set the correct permissions after the operation is finished. This -might cause that the files can be accessible by more users during -the operation than expected. Use G_FILE_CREATE_PRIVATE for the new -files to limit access to those files. ---- - gio/gfile.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - -diff --git a/gio/gfile.c b/gio/gfile.c -index 24b136d80..74b58047c 100644 ---- a/gio/gfile.c -+++ b/gio/gfile.c -@@ -3284,12 +3284,12 @@ file_copy_fallback (GFile *source, - out = (GOutputStream*)_g_local_file_output_stream_replace (_g_local_file_get_filename (G_LOCAL_FILE (destination)), - FALSE, NULL, - flags & G_FILE_COPY_BACKUP, -- G_FILE_CREATE_REPLACE_DESTINATION, -- info, -+ G_FILE_CREATE_REPLACE_DESTINATION | -+ G_FILE_CREATE_PRIVATE, info, - cancellable, error); - else - out = (GOutputStream*)_g_local_file_output_stream_create (_g_local_file_get_filename (G_LOCAL_FILE (destination)), -- FALSE, 0, info, -+ FALSE, G_FILE_CREATE_PRIVATE, info, - cancellable, error); - } - else if (flags & G_FILE_COPY_OVERWRITE) -@@ -3297,12 +3297,13 @@ file_copy_fallback (GFile *source, - out = (GOutputStream *)g_file_replace (destination, - NULL, - flags & G_FILE_COPY_BACKUP, -- G_FILE_CREATE_REPLACE_DESTINATION, -+ G_FILE_CREATE_REPLACE_DESTINATION | -+ G_FILE_CREATE_PRIVATE, - cancellable, error); - } - else - { -- out = (GOutputStream *)g_file_create (destination, 0, cancellable, error); -+ out = (GOutputStream *)g_file_create (destination, G_FILE_CREATE_PRIVATE, cancellable, error); - } - - if (!out) --- -2.21.0 - diff --git a/CVE-2019-13012.patch b/CVE-2019-13012.patch deleted file mode 100644 index eb5908f45e24561602c156bb6ffcb6aed19477be..0000000000000000000000000000000000000000 --- a/CVE-2019-13012.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 32ed752130bcbccc008819a7f1ea27651c601ee2 Mon Sep 17 00:00:00 2001 -From: Matthias Clasen -Date: Tue, 22 Jan 2019 13:26:31 -0500 -Subject: [PATCH 9/9] keyfile settings: Use tighter permissions - -When creating directories, create them with 700 permissions, -instead of 777. - -Closes: #1658 ---- - gio/gkeyfilesettingsbackend.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c -index f5358818e..3d793f5a8 100644 ---- a/gio/gkeyfilesettingsbackend.c -+++ b/gio/gkeyfilesettingsbackend.c -@@ -113,7 +113,8 @@ g_keyfile_settings_backend_keyfile_write (GKeyfileSettingsBackend *kfsb) - - contents = g_key_file_to_data (kfsb->keyfile, &length, NULL); - g_file_replace_contents (kfsb->file, contents, length, NULL, FALSE, -- G_FILE_CREATE_REPLACE_DESTINATION, -+ G_FILE_CREATE_REPLACE_DESTINATION | -+ G_FILE_CREATE_PRIVATE, - NULL, NULL, NULL); - - compute_checksum (kfsb->digest, contents, length); -@@ -708,7 +709,7 @@ g_keyfile_settings_backend_constructed (GObject *object) - kfsb->permission = g_simple_permission_new (TRUE); - - kfsb->dir = g_file_get_parent (kfsb->file); -- g_file_make_directory_with_parents (kfsb->dir, NULL, NULL); -+ g_mkdir_with_parents (g_file_peek_path (kfsb->dir), 0700); - - kfsb->file_monitor = g_file_monitor (kfsb->file, G_FILE_MONITOR_NONE, NULL, NULL); - kfsb->dir_monitor = g_file_monitor (kfsb->dir, G_FILE_MONITOR_NONE, NULL, NULL); --- -2.28.0 diff --git a/CVE-2021-27218.patch b/CVE-2021-27218.patch deleted file mode 100644 index 15aa571ed3b7ceec36dbfbf1f4f7b4b38dd45d54..0000000000000000000000000000000000000000 --- a/CVE-2021-27218.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 89b522ed31837cb2ac107a8961fbb0f2c7fc7ccb Mon Sep 17 00:00:00 2001 -From: Krzesimir Nowak -Date: Wed, 10 Feb 2021 23:51:07 +0100 -Subject: [PATCH] gbytearray: Do not accept too large byte arrays - -GByteArray uses guint for storing the length of the byte array, but it -also has a constructor (g_byte_array_new_take) that takes length as a -gsize. gsize may be larger than guint (64 bits for gsize vs 32 bits -for guint). It is possible to call the function with a value greater -than G_MAXUINT, which will result in silent length truncation. This -may happen as a result of unreffing GBytes into GByteArray, so rather -be loud about it. - -(Test case tweaked by Philip Withnall.) ---- - glib/garray.c | 6 ++++++ - glib/gbytes.c | 4 ++++ - glib/tests/bytes.c | 37 +++++++++++++++++++++++++++++++++++-- - 3 files changed, 45 insertions(+), 2 deletions(-) - -diff --git a/glib/garray.c b/glib/garray.c -index aa3c04707..271d85ad8 100644 ---- a/glib/garray.c -+++ b/glib/garray.c -@@ -1666,6 +1666,10 @@ g_byte_array_new (void) - * Create byte array containing the data. The data will be owned by the array - * and will be freed with g_free(), i.e. it could be allocated using g_strdup(). - * -+ * Do not use it if @len is greater than %G_MAXUINT. #GByteArray -+ * stores the length of its data in #guint, which may be shorter than -+ * #gsize. -+ * - * Since: 2.32 - * - * Returns: (transfer full): a new #GByteArray -@@ -1677,6 +1681,8 @@ g_byte_array_new_take (guint8 *data, - GByteArray *array; - GRealArray *real; - -+ g_return_val_if_fail (len <= G_MAXUINT, NULL); -+ - array = g_byte_array_new (); - real = (GRealArray *)array; - g_assert (real->data == NULL); -diff --git a/glib/gbytes.c b/glib/gbytes.c -index 5141170d7..635b79535 100644 ---- a/glib/gbytes.c -+++ b/glib/gbytes.c -@@ -512,6 +512,10 @@ g_bytes_unref_to_data (GBytes *bytes, - * g_bytes_new(), g_bytes_new_take() or g_byte_array_free_to_bytes(). In all - * other cases the data is copied. - * -+ * Do not use it if @bytes contains more than %G_MAXUINT -+ * bytes. #GByteArray stores the length of its data in #guint, which -+ * may be shorter than #gsize, that @bytes is using. -+ * - * Returns: (transfer full): a new mutable #GByteArray containing the same byte data - * - * Since: 2.32 -diff --git a/glib/tests/bytes.c b/glib/tests/bytes.c -index 5ea5c2b35..42281307b 100644 ---- a/glib/tests/bytes.c -+++ b/glib/tests/bytes.c -@@ -10,12 +10,12 @@ - */ - - #undef G_DISABLE_ASSERT --#undef G_LOG_DOMAIN - - #include - #include - #include - #include "glib.h" -+#include "glib/gstrfuncsprivate.h" - - /* Keep in sync with glib/gbytes.c */ - struct _GBytes -@@ -333,6 +333,38 @@ test_to_array_transferred (void) - g_byte_array_unref (array); - } - -+static void -+test_to_array_transferred_oversize (void) -+{ -+ g_test_message ("g_bytes_unref_to_array() can only take GBytes up to " -+ "G_MAXUINT in length; test that longer ones are rejected"); -+ -+ if (sizeof (guint) >= sizeof (gsize)) -+ { -+ g_test_skip ("Skipping test as guint is not smaller than gsize"); -+ } -+ else if (g_test_undefined ()) -+ { -+ GByteArray *array = NULL; -+ GBytes *bytes = NULL; -+ gpointer data = g_memdup2 (NYAN, N_NYAN); -+ gsize len = ((gsize) G_MAXUINT) + 1; -+ -+ bytes = g_bytes_new_take (data, len); -+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, -+ "g_byte_array_new_take: assertion 'len <= G_MAXUINT' failed"); -+ array = g_bytes_unref_to_array (g_steal_pointer (&bytes)); -+ g_test_assert_expected_messages (); -+ g_assert_null (array); -+ -+ g_free (data); -+ } -+ else -+ { -+ g_test_skip ("Skipping test as testing undefined behaviour is disabled"); -+ } -+} -+ - static void - test_to_array_two_refs (void) - { -@@ -407,7 +439,8 @@ main (int argc, char *argv[]) - g_test_add_func ("/bytes/to-data/transfered", test_to_data_transferred); - g_test_add_func ("/bytes/to-data/two-refs", test_to_data_two_refs); - g_test_add_func ("/bytes/to-data/non-malloc", test_to_data_non_malloc); -- g_test_add_func ("/bytes/to-array/transfered", test_to_array_transferred); -+ g_test_add_func ("/bytes/to-array/transferred", test_to_array_transferred); -+ g_test_add_func ("/bytes/to-array/transferred-oversize", test_to_array_transferred_oversize); - g_test_add_func ("/bytes/to-array/two-refs", test_to_array_two_refs); - g_test_add_func ("/bytes/to-array/non-malloc", test_to_array_non_malloc); - g_test_add_func ("/bytes/null", test_null); --- -2.31.1 - diff --git a/CVE-2021-27219.patch b/CVE-2021-27219.patch deleted file mode 100644 index 8374e685d39e27e4c883acdcc8243036b1436cdb..0000000000000000000000000000000000000000 --- a/CVE-2021-27219.patch +++ /dev/null @@ -1,849 +0,0 @@ -From 7b46597384de916b4027ebaff662d06ff3ea2bc8 Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Thu, 4 Feb 2021 13:30:52 +0000 -Subject: [PATCH 1/6] gstrfuncs: Add internal g_memdup2() function -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This will replace the existing `g_memdup()` function for use within -GLib. It has an unavoidable security flaw of taking its `byte_size` -argument as a `guint` rather than as a `gsize`. Most callers will -expect it to be a `gsize`, and may pass in large values which could -silently be truncated, resulting in an undersize allocation compared -to what the caller expects. - -This could lead to a classic buffer overflow vulnerability for many -callers of `g_memdup()`. - -`g_memdup2()`, in comparison, takes its `byte_size` as a `gsize`. - -Spotted by Kevin Backhouse of GHSL. - -In GLib 2.68, `g_memdup2()` will be a new public API. In this version -for backport to older stable releases, it’s a new `static inline` API -in a private header, so that use of `g_memdup()` within GLib can be -fixed without adding a new API in a stable release series. - -Signed-off-by: Philip Withnall -Helps: CVE-2021-27219 -Helps: GHSL-2021-045 -Helps: #2319 -(cherry picked from commit 5e5f75a77e399c638be66d74e5daa8caeb433e00) ---- - docs/reference/glib/meson.build | 1 + - glib/gstrfuncsprivate.h | 55 +++++++++++++++++++++++++++++++++ - glib/meson.build | 1 + - glib/tests/strfuncs.c | 23 ++++++++++++++ - 4 files changed, 80 insertions(+) - create mode 100644 glib/gstrfuncsprivate.h - -diff --git a/docs/reference/glib/meson.build b/docs/reference/glib/meson.build -index f0f915e96..1a3680941 100644 ---- a/docs/reference/glib/meson.build -+++ b/docs/reference/glib/meson.build -@@ -20,6 +20,7 @@ if get_option('gtk_doc') - 'gprintfint.h', - 'gmirroringtable.h', - 'gscripttable.h', -+ 'gstrfuncsprivate.h', - 'glib-mirroring-tab', - 'gnulib', - 'pcre', -diff --git a/glib/gstrfuncsprivate.h b/glib/gstrfuncsprivate.h -new file mode 100644 -index 000000000..85c88328a ---- /dev/null -+++ b/glib/gstrfuncsprivate.h -@@ -0,0 +1,55 @@ -+/* GLIB - Library of useful routines for C programming -+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+ */ -+ -+#include -+#include -+ -+/* -+ * g_memdup2: -+ * @mem: (nullable): the memory to copy. -+ * @byte_size: the number of bytes to copy. -+ * -+ * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it -+ * from @mem. If @mem is %NULL it returns %NULL. -+ * -+ * This replaces g_memdup(), which was prone to integer overflows when -+ * converting the argument from a #gsize to a #guint. -+ * -+ * This static inline version is a backport of the new public API from -+ * GLib 2.68, kept internal to GLib for backport to older stable releases. -+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2319. -+ * -+ * Returns: (nullable): a pointer to the newly-allocated copy of the memory, -+ * or %NULL if @mem is %NULL. -+ * Since: 2.68 -+ */ -+static inline gpointer -+g_memdup2 (gconstpointer mem, -+ gsize byte_size) -+{ -+ gpointer new_mem; -+ -+ if (mem && byte_size != 0) -+ { -+ new_mem = g_malloc (byte_size); -+ memcpy (new_mem, mem, byte_size); -+ } -+ else -+ new_mem = NULL; -+ -+ return new_mem; -+} -diff --git a/glib/meson.build b/glib/meson.build -index a2f9da81c..481fd06ff 100644 ---- a/glib/meson.build -+++ b/glib/meson.build -@@ -167,6 +167,7 @@ glib_sources = files( - 'gslist.c', - 'gstdio.c', - 'gstrfuncs.c', -+ 'gstrfuncsprivate.h', - 'gstring.c', - 'gstringchunk.c', - 'gtestutils.c', -diff --git a/glib/tests/strfuncs.c b/glib/tests/strfuncs.c -index 7e031bdb1..2aa252946 100644 ---- a/glib/tests/strfuncs.c -+++ b/glib/tests/strfuncs.c -@@ -32,6 +32,8 @@ - #include - #include "glib.h" - -+#include "gstrfuncsprivate.h" -+ - #if defined (_MSC_VER) && (_MSC_VER <= 1800) - #define isnan(x) _isnan(x) - -@@ -199,6 +201,26 @@ test_is_to_digit (void) - #undef TEST_DIGIT - } - -+/* Testing g_memdup2() function with various positive and negative cases */ -+static void -+test_memdup2 (void) -+{ -+ gchar *str_dup = NULL; -+ const gchar *str = "The quick brown fox jumps over the lazy dog"; -+ -+ /* Testing negative cases */ -+ g_assert_null (g_memdup2 (NULL, 1024)); -+ g_assert_null (g_memdup2 (str, 0)); -+ g_assert_null (g_memdup2 (NULL, 0)); -+ -+ /* Testing normal usage cases */ -+ str_dup = g_memdup2 (str, strlen (str) + 1); -+ g_assert_nonnull (str_dup); -+ g_assert_cmpstr (str, ==, str_dup); -+ -+ g_free (str_dup); -+} -+ - static void - test_strdup (void) - { -@@ -1726,6 +1748,7 @@ main (int argc, - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/strfuncs/test-is-to-digit", test_is_to_digit); -+ g_test_add_func ("/strfuncs/memdup2", test_memdup2); - g_test_add_func ("/strfuncs/strdup", test_strdup); - g_test_add_func ("/strfuncs/strndup", test_strndup); - g_test_add_func ("/strfuncs/strdup-printf", test_strdup_printf); --- -2.31.1 - -From d6aab169954d9e6e77753dee68e1b3f5932f6dee Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Thu, 4 Feb 2021 13:41:21 +0000 -Subject: [PATCH 2/6] glib: Use g_memdup2() instead of g_memdup() in obvious - places -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Convert all the call sites which use `g_memdup()`’s length argument -trivially (for example, by passing a `sizeof()` or an existing `gsize` -variable), so that they use `g_memdup2()` instead. - -In almost all of these cases the use of `g_memdup()` would not have -caused problems, but it will soon be deprecated, so best port away from -it - -In particular, this fixes an overflow within `g_bytes_new()`, identified -as GHSL-2021-045 (aka CVE-2021-27219) by GHSL team member Kevin Backhouse. - -Adapted for GLib 2.58 by Simon McVittie. - -Signed-off-by: Philip Withnall -Fixes: CVE-2021-27219 -Fixes: GHSL-2021-045 -Helps: #2319 -(cherry picked from commit 0736b7c1e7cf4232c5d7eb2b0fbfe9be81bd3baa) -[Backport to 2.58: Omit changes to ghash.c, will be a separate commit] -[Backport to 2.58: Omit changes to giochannel.c, not needed in this branch] -[Backport to 2.58: Omit changes to uri test, not needed in this branch] -Signed-off-by: Simon McVittie ---- - glib/gbytes.c | 6 ++++-- - glib/gdir.c | 3 ++- - glib/gslice.c | 3 ++- - glib/gtestutils.c | 3 ++- - glib/gvariant.c | 7 ++++--- - glib/gvarianttype.c | 3 ++- - glib/tests/array-test.c | 2 +- - glib/tests/option-context.c | 6 ++++-- - 8 files changed, 21 insertions(+), 12 deletions(-) - -diff --git a/glib/gbytes.c b/glib/gbytes.c -index 3b14a51cd..5141170d7 100644 ---- a/glib/gbytes.c -+++ b/glib/gbytes.c -@@ -33,6 +33,8 @@ - - #include - -+#include "gstrfuncsprivate.h" -+ - /** - * GBytes: - * -@@ -94,7 +96,7 @@ g_bytes_new (gconstpointer data, - { - g_return_val_if_fail (data != NULL || size == 0, NULL); - -- return g_bytes_new_take (g_memdup (data, size), size); -+ return g_bytes_new_take (g_memdup2 (data, size), size); - } - - /** -@@ -490,7 +492,7 @@ g_bytes_unref_to_data (GBytes *bytes, - * Copy: Non g_malloc (or compatible) allocator, or static memory, - * so we have to copy, and then unref. - */ -- result = g_memdup (bytes->data, bytes->size); -+ result = g_memdup2 (bytes->data, bytes->size); - *size = bytes->size; - g_bytes_unref (bytes); - } -diff --git a/glib/gdir.c b/glib/gdir.c -index cb4ad0b2f..9d955d57f 100644 ---- a/glib/gdir.c -+++ b/glib/gdir.c -@@ -37,6 +37,7 @@ - #include "gconvert.h" - #include "gfileutils.h" - #include "gstrfuncs.h" -+#include "gstrfuncsprivate.h" - #include "gtestutils.h" - #include "glibintl.h" - -@@ -113,7 +114,7 @@ g_dir_open_with_errno (const gchar *path, - return NULL; - #endif - -- return g_memdup (&dir, sizeof dir); -+ return g_memdup2 (&dir, sizeof dir); - } - - /** -diff --git a/glib/gslice.c b/glib/gslice.c -index 454c8a602..8e2359515 100644 ---- a/glib/gslice.c -+++ b/glib/gslice.c -@@ -45,6 +45,7 @@ - #include "gmain.h" - #include "gmem.h" /* gslice.h */ - #include "gstrfuncs.h" -+#include "gstrfuncsprivate.h" - #include "gutils.h" - #include "gtrashstack.h" - #include "gtestutils.h" -@@ -352,7 +353,7 @@ g_slice_get_config_state (GSliceConfig ckey, - array[i++] = allocator->contention_counters[address]; - array[i++] = allocator_get_magazine_threshold (allocator, address); - *n_values = i; -- return g_memdup (array, sizeof (array[0]) * *n_values); -+ return g_memdup2 (array, sizeof (array[0]) * *n_values); - default: - return NULL; - } -diff --git a/glib/gtestutils.c b/glib/gtestutils.c -index 0447dcda5..14e071fce 100644 ---- a/glib/gtestutils.c -+++ b/glib/gtestutils.c -@@ -49,6 +49,7 @@ - #include "gpattern.h" - #include "grand.h" - #include "gstrfuncs.h" -+#include "gstrfuncsprivate.h" - #include "gtimer.h" - #include "gslice.h" - #include "gspawn.h" -@@ -3397,7 +3398,7 @@ g_test_log_extract (GTestLogBuffer *tbuffer) - if (p <= tbuffer->data->str + mlength) - { - g_string_erase (tbuffer->data, 0, mlength); -- tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup (&msg, sizeof (msg))); -+ tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup2 (&msg, sizeof (msg))); - return TRUE; - } - -diff --git a/glib/gvariant.c b/glib/gvariant.c -index 8be9ce798..45a1a73dc 100644 ---- a/glib/gvariant.c -+++ b/glib/gvariant.c -@@ -33,6 +33,7 @@ - - #include - -+#include "gstrfuncsprivate.h" - - /** - * SECTION:gvariant -@@ -720,7 +721,7 @@ g_variant_new_variant (GVariant *value) - g_variant_ref_sink (value); - - return g_variant_new_from_children (G_VARIANT_TYPE_VARIANT, -- g_memdup (&value, sizeof value), -+ g_memdup2 (&value, sizeof value), - 1, g_variant_is_trusted (value)); - } - -@@ -1224,7 +1225,7 @@ g_variant_new_fixed_array (const GVariantType *element_type, - return NULL; - } - -- data = g_memdup (elements, n_elements * element_size); -+ data = g_memdup2 (elements, n_elements * element_size); - value = g_variant_new_from_data (array_type, data, - n_elements * element_size, - FALSE, g_free, data); -@@ -1901,7 +1902,7 @@ g_variant_dup_bytestring (GVariant *value, - if (length) - *length = size; - -- return g_memdup (original, size + 1); -+ return g_memdup2 (original, size + 1); - } - - /** -diff --git a/glib/gvarianttype.c b/glib/gvarianttype.c -index c8433e65a..dbbf7d2d1 100644 ---- a/glib/gvarianttype.c -+++ b/glib/gvarianttype.c -@@ -28,6 +28,7 @@ - - #include - -+#include "gstrfuncsprivate.h" - - /** - * SECTION:gvarianttype -@@ -1174,7 +1175,7 @@ g_variant_type_new_tuple (const GVariantType * const *items, - g_assert (offset < sizeof buffer); - buffer[offset++] = ')'; - -- return (GVariantType *) g_memdup (buffer, offset); -+ return (GVariantType *) g_memdup2 (buffer, offset); - } - - /** --- -2.31.1 - -From 7e2c2a07508a97b9d75e402afe4749b02a34dd8b Mon Sep 17 00:00:00 2001 -From: Simon McVittie -Date: Thu, 18 Mar 2021 10:31:00 +0000 -Subject: [PATCH 3/6] ghash: Use g_memdup2() instead of g_memdup() - -Backport of part of commit 0736b7c1e7cf4232c5d7eb2b0fbfe9be81bd3baa -to the simpler structure of the GHashTable code in glib-2-58. - -Helps: #2319 -Signed-off-by: Simon McVittie ---- - glib/ghash.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/glib/ghash.c b/glib/ghash.c -index 6bb04a50d..608d136f4 100644 ---- a/glib/ghash.c -+++ b/glib/ghash.c -@@ -34,6 +34,7 @@ - - #include "glib-private.h" - #include "gstrfuncs.h" -+#include "gstrfuncsprivate.h" - #include "gatomic.h" - #include "gtestutils.h" - #include "gslice.h" -@@ -967,7 +968,7 @@ g_hash_table_insert_node (GHashTable *hash_table, - * split the table. - */ - if (G_UNLIKELY (hash_table->keys == hash_table->values && hash_table->keys[node_index] != new_value)) -- hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size); -+ hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size); - - /* Step 3: Actually do the write */ - hash_table->values[node_index] = new_value; --- -2.31.1 - -From 9e0c87610dccd1b0eaca28a3baa521ea6a24f46b Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Thu, 4 Feb 2021 13:39:25 +0000 -Subject: [PATCH 4/6] gobject: Use g_memdup2() instead of g_memdup() in obvious - places -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Convert all the call sites which use `g_memdup()`’s length argument -trivially (for example, by passing a `sizeof()`), so that they use -`g_memdup2()` instead. - -In almost all of these cases the use of `g_memdup()` would not have -caused problems, but it will soon be deprecated, so best port away from -it. - -Signed-off-by: Philip Withnall -Helps: #2319 -(cherry picked from commit 6110caea45b235420b98cd41d845cc92238f6781) ---- - gobject/gsignal.c | 3 ++- - gobject/gtype.c | 9 +++++---- - gobject/gtypemodule.c | 3 ++- - gobject/tests/param.c | 4 +++- - 4 files changed, 12 insertions(+), 7 deletions(-) - -diff --git a/gobject/gsignal.c b/gobject/gsignal.c -index b22dfcca8..92555eb60 100644 ---- a/gobject/gsignal.c -+++ b/gobject/gsignal.c -@@ -28,6 +28,7 @@ - #include - - #include "gsignal.h" -+#include "gstrfuncsprivate.h" - #include "gtype-private.h" - #include "gbsearcharray.h" - #include "gvaluecollector.h" -@@ -1724,7 +1725,7 @@ g_signal_newv (const gchar *signal_name, - node->single_va_closure_is_valid = FALSE; - node->flags = signal_flags & G_SIGNAL_FLAGS_MASK; - node->n_params = n_params; -- node->param_types = g_memdup (param_types, sizeof (GType) * n_params); -+ node->param_types = g_memdup2 (param_types, sizeof (GType) * n_params); - node->return_type = return_type; - node->class_closure_bsa = NULL; - if (accumulator) -diff --git a/gobject/gtype.c b/gobject/gtype.c -index 275a8b60b..9e663ce52 100644 ---- a/gobject/gtype.c -+++ b/gobject/gtype.c -@@ -33,6 +33,7 @@ - - #include "glib-private.h" - #include "gconstructor.h" -+#include "gstrfuncsprivate.h" - - #ifdef G_OS_WIN32 - #include -@@ -1471,7 +1472,7 @@ type_add_interface_Wm (TypeNode *node, - iholder->next = iface_node_get_holders_L (iface); - iface_node_set_holders_W (iface, iholder); - iholder->instance_type = NODE_TYPE (node); -- iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL; -+ iholder->info = info ? g_memdup2 (info, sizeof (*info)) : NULL; - iholder->plugin = plugin; - - /* create an iface entry for this type */ -@@ -1732,7 +1733,7 @@ type_iface_retrieve_holder_info_Wm (TypeNode *iface, - INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface)); - - check_interface_info_I (iface, instance_type, &tmp_info); -- iholder->info = g_memdup (&tmp_info, sizeof (tmp_info)); -+ iholder->info = g_memdup2 (&tmp_info, sizeof (tmp_info)); - } - - return iholder; /* we don't modify write lock upon returning NULL */ -@@ -2013,10 +2014,10 @@ type_iface_vtable_base_init_Wm (TypeNode *iface, - IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface); - - if (pentry) -- vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size); -+ vtable = g_memdup2 (pentry->vtable, iface->data->iface.vtable_size); - } - if (!vtable) -- vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size); -+ vtable = g_memdup2 (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size); - entry->vtable = vtable; - vtable->g_type = NODE_TYPE (iface); - vtable->g_instance_type = NODE_TYPE (node); -diff --git a/gobject/gtypemodule.c b/gobject/gtypemodule.c -index c67f789b1..cf877bc0b 100644 ---- a/gobject/gtypemodule.c -+++ b/gobject/gtypemodule.c -@@ -19,6 +19,7 @@ - - #include - -+#include "gstrfuncsprivate.h" - #include "gtypeplugin.h" - #include "gtypemodule.h" - -@@ -436,7 +437,7 @@ g_type_module_register_type (GTypeModule *module, - module_type_info->loaded = TRUE; - module_type_info->info = *type_info; - if (type_info->value_table) -- module_type_info->info.value_table = g_memdup (type_info->value_table, -+ module_type_info->info.value_table = g_memdup2 (type_info->value_table, - sizeof (GTypeValueTable)); - - return module_type_info->type; -diff --git a/gobject/tests/param.c b/gobject/tests/param.c -index 758289bf8..971cff162 100644 ---- a/gobject/tests/param.c -+++ b/gobject/tests/param.c -@@ -2,6 +2,8 @@ - #include - #include - -+#include "gstrfuncsprivate.h" -+ - static void - test_param_value (void) - { -@@ -851,7 +853,7 @@ main (int argc, char *argv[]) - test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d", - data.change_this_flag, data.change_this_type, - data.use_this_flag, data.use_this_type); -- test_data = g_memdup (&data, sizeof (TestParamImplementData)); -+ test_data = g_memdup2 (&data, sizeof (TestParamImplementData)); - g_test_add_data_func_full (test_path, test_data, test_param_implement_child, g_free); - g_free (test_path); - } --- -2.31.1 - -From d3f7a79540fc1e85eb82c2987e9f7e2dbd93ff74 Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Thu, 4 Feb 2021 13:37:56 +0000 -Subject: [PATCH 5/6] gio: Use g_memdup2() instead of g_memdup() in obvious - places -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Convert all the call sites which use `g_memdup()`’s length argument -trivially (for example, by passing a `sizeof()`), so that they use -`g_memdup2()` instead. - -In almost all of these cases the use of `g_memdup()` would not have -caused problems, but it will soon be deprecated, so best port away from -it. - -Signed-off-by: Philip Withnall -Helps: #2319 -(cherry picked from commit be8834340a2d928ece82025463ae23dee2c333d0) ---- - gio/gdbusconnection.c | 5 +++-- - gio/gdbusinterfaceskeleton.c | 3 ++- - gio/gfile.c | 7 ++++--- - gio/gsettingsschema.c | 5 +++-- - gio/gwin32registrykey.c | 8 +++++--- - gio/tests/async-close-output-stream.c | 6 ++++-- - gio/tests/gdbus-export.c | 5 +++-- - gio/win32/gwinhttpfile.c | 9 +++++---- - 8 files changed, 29 insertions(+), 19 deletions(-) - -diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c -index 6f7e5fefc..117c8df35 100644 ---- a/gio/gdbusconnection.c -+++ b/gio/gdbusconnection.c -@@ -119,6 +119,7 @@ - #include "gasyncinitable.h" - #include "giostream.h" - #include "gasyncresult.h" -+#include "gstrfuncsprivate.h" - #include "gtask.h" - - #ifdef G_OS_UNIX -@@ -3970,7 +3971,7 @@ _g_dbus_interface_vtable_copy (const GDBusInterfaceVTable *vtable) - /* Don't waste memory by copying padding - remember to update this - * when changing struct _GDBusInterfaceVTable in gdbusconnection.h - */ -- return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer)); -+ return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer)); - } - - static void -@@ -3987,7 +3988,7 @@ _g_dbus_subtree_vtable_copy (const GDBusSubtreeVTable *vtable) - /* Don't waste memory by copying padding - remember to update this - * when changing struct _GDBusSubtreeVTable in gdbusconnection.h - */ -- return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer)); -+ return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer)); - } - - static void -diff --git a/gio/gdbusinterfaceskeleton.c b/gio/gdbusinterfaceskeleton.c -index 96bd520aa..672604c49 100644 ---- a/gio/gdbusinterfaceskeleton.c -+++ b/gio/gdbusinterfaceskeleton.c -@@ -27,6 +27,7 @@ - #include "gdbusprivate.h" - #include "gdbusmethodinvocation.h" - #include "gdbusconnection.h" -+#include "gstrfuncsprivate.h" - #include "gtask.h" - #include "gioerror.h" - -@@ -697,7 +698,7 @@ add_connection_locked (GDBusInterfaceSkeleton *interface_, - * properly before building the hooked_vtable, so we create it - * once at the last minute. - */ -- interface_->priv->hooked_vtable = g_memdup (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable)); -+ interface_->priv->hooked_vtable = g_memdup2 (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable)); - interface_->priv->hooked_vtable->method_call = skeleton_intercept_handle_method_call; - } - -diff --git a/gio/gfile.c b/gio/gfile.c -index ff313ebf8..29ebaaa62 100644 ---- a/gio/gfile.c -+++ b/gio/gfile.c -@@ -60,6 +60,7 @@ - #include "gasyncresult.h" - #include "gioerror.h" - #include "glibintl.h" -+#include "gstrfuncsprivate.h" - - - /** -@@ -7734,7 +7735,7 @@ measure_disk_usage_progress (gboolean reporting, - g_main_context_invoke_full (g_task_get_context (task), - g_task_get_priority (task), - measure_disk_usage_invoke_progress, -- g_memdup (&progress, sizeof progress), -+ g_memdup2 (&progress, sizeof progress), - g_free); - } - -@@ -7752,7 +7753,7 @@ measure_disk_usage_thread (GTask *task, - data->progress_callback ? measure_disk_usage_progress : NULL, task, - &result.disk_usage, &result.num_dirs, &result.num_files, - &error)) -- g_task_return_pointer (task, g_memdup (&result, sizeof result), g_free); -+ g_task_return_pointer (task, g_memdup2 (&result, sizeof result), g_free); - else - g_task_return_error (task, error); - } -@@ -7776,7 +7777,7 @@ g_file_real_measure_disk_usage_async (GFile *file, - - task = g_task_new (file, cancellable, callback, user_data); - g_task_set_source_tag (task, g_file_real_measure_disk_usage_async); -- g_task_set_task_data (task, g_memdup (&data, sizeof data), g_free); -+ g_task_set_task_data (task, g_memdup2 (&data, sizeof data), g_free); - g_task_set_priority (task, io_priority); - - g_task_run_in_thread (task, measure_disk_usage_thread); -diff --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c -index 17b7e3b01..499944395 100644 ---- a/gio/gsettingsschema.c -+++ b/gio/gsettingsschema.c -@@ -20,6 +20,7 @@ - - #include "gsettingsschema-internal.h" - #include "gsettings.h" -+#include "gstrfuncsprivate.h" - - #include "gvdb/gvdb-reader.h" - #include "strinfo.c" -@@ -1054,9 +1055,9 @@ g_settings_schema_list_children (GSettingsSchema *schema) - - if (g_str_has_suffix (key, "/")) - { -- gint length = strlen (key); -+ gsize length = strlen (key); - -- strv[j] = g_memdup (key, length); -+ strv[j] = g_memdup2 (key, length); - strv[j][length - 1] = '\0'; - j++; - } -diff --git a/gio/gwin32registrykey.c b/gio/gwin32registrykey.c -index c19fede4e..619fd48af 100644 ---- a/gio/gwin32registrykey.c -+++ b/gio/gwin32registrykey.c -@@ -28,6 +28,8 @@ - #include - #include - -+#include "gstrfuncsprivate.h" -+ - #ifndef _WDMDDK_ - typedef enum _KEY_INFORMATION_CLASS { - KeyBasicInformation, -@@ -247,7 +249,7 @@ g_win32_registry_value_iter_copy (const GWin32RegistryValueIter *iter) - new_iter->value_name_size = iter->value_name_size; - - if (iter->value_data != NULL) -- new_iter->value_data = g_memdup (iter->value_data, iter->value_data_size); -+ new_iter->value_data = g_memdup2 (iter->value_data, iter->value_data_size); - - new_iter->value_data_size = iter->value_data_size; - -@@ -268,8 +270,8 @@ g_win32_registry_value_iter_copy (const GWin32RegistryValueIter *iter) - new_iter->value_data_expanded_charsize = iter->value_data_expanded_charsize; - - if (iter->value_data_expanded_u8 != NULL) -- new_iter->value_data_expanded_u8 = g_memdup (iter->value_data_expanded_u8, -- iter->value_data_expanded_charsize); -+ new_iter->value_data_expanded_u8 = g_memdup2 (iter->value_data_expanded_u8, -+ iter->value_data_expanded_charsize); - - new_iter->value_data_expanded_u8_size = iter->value_data_expanded_charsize; - -diff --git a/gio/tests/async-close-output-stream.c b/gio/tests/async-close-output-stream.c -index 5f6620275..d3f97a119 100644 ---- a/gio/tests/async-close-output-stream.c -+++ b/gio/tests/async-close-output-stream.c -@@ -24,6 +24,8 @@ - #include - #include - -+#include "gstrfuncsprivate.h" -+ - #define DATA_TO_WRITE "Hello world\n" - - typedef struct -@@ -147,9 +149,9 @@ prepare_data (SetupData *data, - - data->expected_size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (data->data_stream)); - -- g_assert_cmpint (data->expected_size, >, 0); -+ g_assert_cmpuint (data->expected_size, >, 0); - -- data->expected_output = g_memdup (written, (guint)data->expected_size); -+ data->expected_output = g_memdup2 (written, data->expected_size); - - /* then recreate the streams and prepare them for the asynchronous close */ - destroy_streams (data); -diff --git a/gio/tests/gdbus-export.c b/gio/tests/gdbus-export.c -index ef0dddeee..a3c842360 100644 ---- a/gio/tests/gdbus-export.c -+++ b/gio/tests/gdbus-export.c -@@ -23,6 +23,7 @@ - #include - - #include "gdbus-tests.h" -+#include "gstrfuncsprivate.h" - - /* all tests rely on a shared mainloop */ - static GMainLoop *loop = NULL; -@@ -652,7 +653,7 @@ subtree_introspect (GDBusConnection *connection, - g_assert_not_reached (); - } - -- return g_memdup (interfaces, 2 * sizeof (void *)); -+ return g_memdup2 (interfaces, 2 * sizeof (void *)); - } - - static const GDBusInterfaceVTable * -@@ -708,7 +709,7 @@ dynamic_subtree_introspect (GDBusConnection *connection, - { - const GDBusInterfaceInfo *interfaces[2] = { &dyna_interface_info, NULL }; - -- return g_memdup (interfaces, 2 * sizeof (void *)); -+ return g_memdup2 (interfaces, 2 * sizeof (void *)); - } - - static const GDBusInterfaceVTable * -diff --git a/gio/win32/gwinhttpfile.c b/gio/win32/gwinhttpfile.c -index d5df16d91..f424d21cc 100644 ---- a/gio/win32/gwinhttpfile.c -+++ b/gio/win32/gwinhttpfile.c -@@ -29,6 +29,7 @@ - #include "gio/gfile.h" - #include "gio/gfileattribute.h" - #include "gio/gfileinfo.h" -+#include "gstrfuncsprivate.h" - #include "gwinhttpfile.h" - #include "gwinhttpfileinputstream.h" - #include "gwinhttpfileoutputstream.h" -@@ -393,10 +394,10 @@ g_winhttp_file_resolve_relative_path (GFile *file, - child = g_object_new (G_TYPE_WINHTTP_FILE, NULL); - child->vfs = winhttp_file->vfs; - child->url = winhttp_file->url; -- child->url.lpszScheme = g_memdup (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2); -- child->url.lpszHostName = g_memdup (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2); -- child->url.lpszUserName = g_memdup (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2); -- child->url.lpszPassword = g_memdup (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2); -+ child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2); -+ child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2); -+ child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2); -+ child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2); - child->url.lpszUrlPath = wnew_path; - child->url.dwUrlPathLength = wcslen (wnew_path); - child->url.lpszExtraInfo = NULL; --- -2.31.1 - -From 661f5edc901219a1a99bb51f171be13063878bd6 Mon Sep 17 00:00:00 2001 -From: Michael Catanzaro -Date: Thu, 20 May 2021 15:58:53 -0500 -Subject: [PATCH 6/6] gdatainputstream: replace easy use of g_memdup() - -This code is passing a gsize, so might as well switch this to g_memdup2(). - -This is the only use of g_memdup() in GLib 2.56 that is not part of GLib -2.58. All other uses analyzed in glib!2000. ---- - gio/gdatainputstream.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/gio/gdatainputstream.c b/gio/gdatainputstream.c -index 9f207b158..ebef7c797 100644 ---- a/gio/gdatainputstream.c -+++ b/gio/gdatainputstream.c -@@ -27,6 +27,7 @@ - #include "gioenumtypes.h" - #include "gioerror.h" - #include "glibintl.h" -+#include "gstrfuncsprivate.h" - - #include - -@@ -1082,7 +1083,7 @@ g_data_input_stream_read_async (GDataInputStream *stream, - data = g_slice_new0 (GDataInputStreamReadData); - if (stop_chars_len == -1) - stop_chars_len = strlen (stop_chars); -- data->stop_chars = g_memdup (stop_chars, stop_chars_len); -+ data->stop_chars = g_memdup2 (stop_chars, stop_chars_len); - data->stop_chars_len = stop_chars_len; - data->last_saw_cr = FALSE; - --- -2.31.1 diff --git a/CVE-2021-28153.patch b/CVE-2021-28153.patch deleted file mode 100644 index 93974631d7857a52bf66913d31a834c658b92947..0000000000000000000000000000000000000000 --- a/CVE-2021-28153.patch +++ /dev/null @@ -1,388 +0,0 @@ -From 8fef6abe1131da0c8a7211c740a12ebe11cbcc51 Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Wed, 10 Mar 2021 16:05:55 +0000 -Subject: [PATCH 1/3] glocalfileoutputstream: Factor out a flag check - -This clarifies the code a little. It introduces no functional changes. - -Signed-off-by: Philip Withnall ---- - gio/glocalfileoutputstream.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/gio/glocalfileoutputstream.c b/gio/glocalfileoutputstream.c -index 57d2d5dfe..6a70b2a04 100644 ---- a/gio/glocalfileoutputstream.c -+++ b/gio/glocalfileoutputstream.c -@@ -751,6 +751,7 @@ handle_overwrite_open (const char *filename, - int res; - int mode; - int errsv; -+ gboolean replace_destination_set = (flags & G_FILE_CREATE_REPLACE_DESTINATION); - - mode = mode_from_flags_or_info (flags, reference_info); - -@@ -857,8 +858,8 @@ handle_overwrite_open (const char *filename, - * The second strategy consist simply in copying the old file - * to a backup file and rewrite the contents of the file. - */ -- -- if ((flags & G_FILE_CREATE_REPLACE_DESTINATION) || -+ -+ if (replace_destination_set || - (!(original_stat.st_nlink > 1) && !is_symlink)) - { - char *dirname, *tmp_filename; -@@ -877,7 +878,7 @@ handle_overwrite_open (const char *filename, - - /* try to keep permissions (unless replacing) */ - -- if ( ! (flags & G_FILE_CREATE_REPLACE_DESTINATION) && -+ if (!replace_destination_set && - ( - #ifdef HAVE_FCHOWN - fchown (tmpfd, original_stat.st_uid, original_stat.st_gid) == -1 || -@@ -1016,7 +1017,7 @@ handle_overwrite_open (const char *filename, - } - } - -- if (flags & G_FILE_CREATE_REPLACE_DESTINATION) -+ if (replace_destination_set) - { - g_close (fd, NULL); - --- -2.31.1 - -From 6c10e8ce6905e8fcc3466eb8af707b5d0d3bdb85 Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Wed, 24 Feb 2021 17:36:07 +0000 -Subject: [PATCH 2/3] glocalfileoutputstream: Fix CREATE_REPLACE_DESTINATION - with symlinks -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The `G_FILE_CREATE_REPLACE_DESTINATION` flag is equivalent to unlinking -the destination file and re-creating it from scratch. That did -previously work, but in the process the code would call `open(O_CREAT)` -on the file. If the file was a dangling symlink, this would create the -destination file (empty). That’s not an intended side-effect, and has -security implications if the symlink is controlled by a lower-privileged -process. - -Fix that by not opening the destination file if it’s a symlink, and -adjusting the rest of the code to cope with - - the fact that `fd == -1` is not an error iff `is_symlink` is true, - - and that `original_stat` will contain the `lstat()` results for the - symlink now, rather than the `stat()` results for its target (again, - iff `is_symlink` is true). - -This means that the target of the dangling symlink is no longer created, -which was the bug. The symlink itself continues to be replaced (as -before) with the new file — this is the intended behaviour of -`g_file_replace()`. - -The behaviour for non-symlink cases, or cases where the symlink was not -dangling, should be unchanged. - -Includes a unit test. - -Signed-off-by: Philip Withnall - -Fixes: #2325 ---- - gio/glocalfileoutputstream.c | 63 ++++++++++++++------- - gio/tests/file.c | 107 ++++++++++++++++++++++++++++++++++- - 2 files changed, 149 insertions(+), 21 deletions(-) - -diff --git a/gio/glocalfileoutputstream.c b/gio/glocalfileoutputstream.c -index 6a70b2a04..4a7766f68 100644 ---- a/gio/glocalfileoutputstream.c -+++ b/gio/glocalfileoutputstream.c -@@ -779,16 +779,22 @@ handle_overwrite_open (const char *filename, - /* Could be a symlink, or it could be a regular ELOOP error, - * but then the next open will fail too. */ - is_symlink = TRUE; -- fd = g_open (filename, open_flags, mode); -+ if (!replace_destination_set) -+ fd = g_open (filename, open_flags, mode); - } --#else -- fd = g_open (filename, open_flags, mode); -- errsv = errno; -+#else /* if !O_NOFOLLOW */ - /* This is racy, but we do it as soon as possible to minimize the race */ - is_symlink = g_file_test (filename, G_FILE_TEST_IS_SYMLINK); -+ -+ if (!is_symlink || !replace_destination_set) -+ { -+ fd = g_open (filename, open_flags, mode); -+ errsv = errno; -+ } - #endif - -- if (fd == -1) -+ if (fd == -1 && -+ (!is_symlink || !replace_destination_set)) - { - char *display_name = g_filename_display_name (filename); - g_set_error (error, G_IO_ERROR, -@@ -800,10 +806,17 @@ handle_overwrite_open (const char *filename, - } - - #ifdef G_OS_WIN32 -- res = GLIB_PRIVATE_CALL (g_win32_fstat) (fd, &original_stat); --#else -- res = fstat (fd, &original_stat); -+#error This patch has not been ported to Windows, sorry - #endif -+ -+ if (!is_symlink) -+ { -+ res = fstat (fd, &original_stat); -+ } -+ else -+ { -+ res = lstat (filename, &original_stat); -+ } - errsv = errno; - - if (res != 0) -@@ -821,16 +834,27 @@ handle_overwrite_open (const char *filename, - if (!S_ISREG (original_stat.st_mode)) - { - if (S_ISDIR (original_stat.st_mode)) -- g_set_error_literal (error, -- G_IO_ERROR, -- G_IO_ERROR_IS_DIRECTORY, -- _("Target file is a directory")); -- else -- g_set_error_literal (error, -- G_IO_ERROR, -- G_IO_ERROR_NOT_REGULAR_FILE, -- _("Target file is not a regular file")); -- goto err_out; -+ { -+ g_set_error_literal (error, -+ G_IO_ERROR, -+ G_IO_ERROR_IS_DIRECTORY, -+ _("Target file is a directory")); -+ goto err_out; -+ } -+ else if (!is_symlink || -+#ifdef S_ISLNK -+ !S_ISLNK (original_stat.st_mode) -+#else -+ FALSE -+#endif -+ ) -+ { -+ g_set_error_literal (error, -+ G_IO_ERROR, -+ G_IO_ERROR_NOT_REGULAR_FILE, -+ _("Target file is not a regular file")); -+ goto err_out; -+ } - } - - if (etag != NULL) -@@ -911,7 +935,8 @@ handle_overwrite_open (const char *filename, - } - } - -- g_close (fd, NULL); -+ if (fd >= 0) -+ g_close (fd, NULL); - *temp_filename = tmp_filename; - return tmpfd; - } -diff --git a/gio/tests/file.c b/gio/tests/file.c -index 98eeb85d4..44db6e295 100644 ---- a/gio/tests/file.c -+++ b/gio/tests/file.c -@@ -671,8 +671,6 @@ test_replace_cancel (void) - guint count; - GError *error = NULL; - -- g_test_bug ("629301"); -- - path = g_dir_make_tmp ("g_file_replace_cancel_XXXXXX", &error); - g_assert_no_error (error); - tmpdir = g_file_new_for_path (path); -@@ -779,6 +777,110 @@ test_replace_cancel (void) - g_object_unref (tmpdir); - } - -+static void -+test_replace_symlink (void) -+{ -+#ifdef G_OS_UNIX -+ gchar *tmpdir_path = NULL; -+ GFile *tmpdir = NULL, *source_file = NULL, *target_file = NULL; -+ GFileOutputStream *stream = NULL; -+ const gchar *new_contents = "this is a test message which should be written to source and not target"; -+ gsize n_written; -+ GFileEnumerator *enumerator = NULL; -+ GFileInfo *info = NULL; -+ gchar *contents = NULL; -+ gsize length = 0; -+ GError *local_error = NULL; -+ -+ /* Create a fresh, empty working directory. */ -+ tmpdir_path = g_dir_make_tmp ("g_file_replace_symlink_XXXXXX", &local_error); -+ g_assert_no_error (local_error); -+ tmpdir = g_file_new_for_path (tmpdir_path); -+ -+ g_test_message ("Using temporary directory %s", tmpdir_path); -+ g_free (tmpdir_path); -+ -+ /* Create symlink `source` which points to `target`. */ -+ source_file = g_file_get_child (tmpdir, "source"); -+ target_file = g_file_get_child (tmpdir, "target"); -+ g_file_make_symbolic_link (source_file, "target", NULL, &local_error); -+ g_assert_no_error (local_error); -+ -+ /* Ensure that `target` doesn’t exist */ -+ g_assert_false (g_file_query_exists (target_file, NULL)); -+ -+ /* Replace the `source` symlink with a regular file using -+ * %G_FILE_CREATE_REPLACE_DESTINATION, which should replace it *without* -+ * following the symlink */ -+ stream = g_file_replace (source_file, NULL, FALSE /* no backup */, -+ G_FILE_CREATE_REPLACE_DESTINATION, NULL, &local_error); -+ g_assert_no_error (local_error); -+ -+ g_output_stream_write_all (G_OUTPUT_STREAM (stream), new_contents, strlen (new_contents), -+ &n_written, NULL, &local_error); -+ g_assert_no_error (local_error); -+ g_assert_cmpint (n_written, ==, strlen (new_contents)); -+ -+ g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, &local_error); -+ g_assert_no_error (local_error); -+ -+ g_clear_object (&stream); -+ -+ /* At this point, there should still only be one file: `source`. It should -+ * now be a regular file. `target` should not exist. */ -+ enumerator = g_file_enumerate_children (tmpdir, -+ G_FILE_ATTRIBUTE_STANDARD_NAME "," -+ G_FILE_ATTRIBUTE_STANDARD_TYPE, -+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error); -+ g_assert_no_error (local_error); -+ -+ info = g_file_enumerator_next_file (enumerator, NULL, &local_error); -+ g_assert_no_error (local_error); -+ g_assert_nonnull (info); -+ -+ g_assert_cmpstr (g_file_info_get_name (info), ==, "source"); -+ g_assert_cmpint (g_file_info_get_file_type (info), ==, G_FILE_TYPE_REGULAR); -+ -+ g_clear_object (&info); -+ -+ info = g_file_enumerator_next_file (enumerator, NULL, &local_error); -+ g_assert_no_error (local_error); -+ g_assert_null (info); -+ -+ g_file_enumerator_close (enumerator, NULL, &local_error); -+ g_assert_no_error (local_error); -+ g_clear_object (&enumerator); -+ -+ /* Double-check that `target` doesn’t exist */ -+ g_assert_false (g_file_query_exists (target_file, NULL)); -+ -+ /* Check the content of `source`. */ -+ g_file_load_contents (source_file, -+ NULL, -+ &contents, -+ &length, -+ NULL, -+ &local_error); -+ g_assert_no_error (local_error); -+ g_assert_cmpstr (contents, ==, new_contents); -+ g_assert_cmpuint (length, ==, strlen (new_contents)); -+ g_free (contents); -+ -+ /* Tidy up. */ -+ g_file_delete (source_file, NULL, &local_error); -+ g_assert_no_error (local_error); -+ -+ g_file_delete (tmpdir, NULL, &local_error); -+ g_assert_no_error (local_error); -+ -+ g_clear_object (&target_file); -+ g_clear_object (&source_file); -+ g_clear_object (&tmpdir); -+#else /* if !G_OS_UNIX */ -+ g_test_skip ("Symlink replacement tests can only be run on Unix") -+#endif -+} -+ - static void - on_file_deleted (GObject *object, - GAsyncResult *result, -@@ -1170,6 +1272,7 @@ main (int argc, char *argv[]) - g_test_add_data_func ("/file/async-create-delete/4096", GINT_TO_POINTER (4096), test_create_delete); - g_test_add_func ("/file/replace-load", test_replace_load); - g_test_add_func ("/file/replace-cancel", test_replace_cancel); -+ g_test_add_func ("/file/replace-symlink", test_replace_symlink); - g_test_add_func ("/file/async-delete", test_async_delete); - #ifdef G_OS_UNIX - g_test_add_func ("/file/copy-preserve-mode", test_copy_preserve_mode); --- -2.31.1 - -From 7f0b0d7fd744ad2f51236444005db49c80a0293d Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Wed, 24 Feb 2021 17:42:24 +0000 -Subject: [PATCH 3/3] glocalfileoutputstream: Add a missing O_CLOEXEC flag to - replace() - -Signed-off-by: Philip Withnall ---- - gio/glocalfileoutputstream.c | 15 ++++++++++++--- - 1 file changed, 12 insertions(+), 3 deletions(-) - -diff --git a/gio/glocalfileoutputstream.c b/gio/glocalfileoutputstream.c -index 4a7766f68..275770fa4 100644 ---- a/gio/glocalfileoutputstream.c -+++ b/gio/glocalfileoutputstream.c -@@ -56,6 +56,12 @@ - #define O_BINARY 0 - #endif - -+#ifndef O_CLOEXEC -+#define O_CLOEXEC 0 -+#else -+#define HAVE_O_CLOEXEC 1 -+#endif -+ - struct _GLocalFileOutputStreamPrivate { - char *tmp_filename; - char *original_filename; -@@ -1127,7 +1133,7 @@ _g_local_file_output_stream_replace (const char *filename, - sync_on_close = FALSE; - - /* If the file doesn't exist, create it */ -- open_flags = O_CREAT | O_EXCL | O_BINARY; -+ open_flags = O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC; - if (readable) - open_flags |= O_RDWR; - else -@@ -1157,8 +1163,11 @@ _g_local_file_output_stream_replace (const char *filename, - set_error_from_open_errno (filename, error); - return NULL; - } -- -- -+#if !defined(HAVE_O_CLOEXEC) && defined(F_SETFD) -+ else -+ fcntl (fd, F_SETFD, FD_CLOEXEC); -+#endif -+ - stream = g_object_new (G_TYPE_LOCAL_FILE_OUTPUT_STREAM, NULL); - stream->priv->fd = fd; - stream->priv->sync_on_close = sync_on_close; --- -2.31.1 - diff --git a/dist b/dist deleted file mode 100644 index 9c0e36ec42a2d9bfefacb21ac6354c9ddd910533..0000000000000000000000000000000000000000 --- a/dist +++ /dev/null @@ -1 +0,0 @@ -an8 diff --git a/download b/download deleted file mode 100644 index ad7fb081f3e6bbd2ade778462ef94d9c8e7c1a2e..0000000000000000000000000000000000000000 --- a/download +++ /dev/null @@ -1 +0,0 @@ -17c3dca43d99a4882384f1a7b530b80b glib-2.56.4.tar.xz diff --git a/glib-2.68.4.tar.xz b/glib-2.68.4.tar.xz new file mode 100644 index 0000000000000000000000000000000000000000..612b0d45b11e25ca2f295a6cb58dbec33db83542 Binary files /dev/null and b/glib-2.68.4.tar.xz differ diff --git a/glib2.spec b/glib2.spec index 938f985e1e939c01b60e55f830abb31304529a42..f6f0553f8ab0660170071c118c6b92344eda165a 100644 --- a/glib2.spec +++ b/glib2.spec @@ -1,121 +1,82 @@ %define anolis_release .0.1 -%global _changelog_trimtime %(date +%s -d "1 year ago") - -# See https://fedoraproject.org/wiki/Packaging:Python_Appendix#Manual_byte_compilation -%global __python %{__python3} - Name: glib2 -Version: 2.56.4 -Release: 159%{anolis_release}%{?dist} +Version: 2.68.4 +Release: 5%{anolis_release}%{?dist} Summary: A library of handy utility functions License: LGPLv2+ URL: http://www.gtk.org -Source0: http://download.gnome.org/sources/glib/2.56/glib-%{version}.tar.xz +Source0: http://download.gnome.org/sources/glib/2.68/glib-%{version}.tar.xz -# For ghmac-gnutls.patch -BuildRequires: pkgconfig(gnutls) +# Required for RHEL core crypto components policy. Good for Fedora too. +# https://bugzilla.redhat.com/show_bug.cgi?id=1630260 +# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/903 +Patch0: gnutls-hmac.patch + +# Add patches to move applications into systemd scopes in compliance with +# https://systemd.io/DESKTOP_ENVIRONMENTS/ +# Proposed upstream at https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1596 +Patch1: 1596.patch + +# Add GPowerProfileMonitor +# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1965 +# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2194 +# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2222 +Patch2: 1965.patch +Patch3: 2194.patch +Patch4: 2222.patch + +# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2244 +Patch5: 2244.patch + +# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2291 +Patch6: 2291.patch + +# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1968 +Patch7: 1968.patch +# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2435 +Patch8: 2435.patch BuildRequires: chrpath +BuildRequires: gcc +BuildRequires: gcc-c++ BuildRequires: gettext +BuildRequires: gtk-doc BuildRequires: perl-interpreter # for sys/inotify.h BuildRequires: glibc-devel BuildRequires: libattr-devel BuildRequires: libselinux-devel +BuildRequires: meson # for sys/sdt.h BuildRequires: systemtap-sdt-devel BuildRequires: pkgconfig(libelf) BuildRequires: pkgconfig(libffi) BuildRequires: pkgconfig(libpcre) BuildRequires: pkgconfig(mount) +BuildRequires: pkgconfig(sysprof-capture-4) BuildRequires: pkgconfig(zlib) -# Bootstrap build requirements -BuildRequires: automake autoconf libtool -BuildRequires: gtk-doc BuildRequires: python3-devel -# for GIO content-type support -Recommends: shared-mime-info - -# Implement RHEL 8 core crypto components policy -# https://bugzilla.redhat.com/show_bug.cgi?id=1630260 -# https://gitlab.gnome.org/GNOME/glib/merge_requests/903 -Patch0: ghmac-gnutls.patch - -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/50 -Patch1: 50.patch - -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/309 -Patch2: 309.patch - -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/403 -Patch3: 409.patch - -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/546 -Patch4: 546.patch - -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/876 -Patch5: CVE-2019-12450.patch +# For gnutls-hmac.patch. We now dlopen libgnutls.so.30 so that we can build a +# static glib2 without depending on a static build of GnuTLS as well. This will +# ensure we notice if the GnuTLS soname bumps, so that we can update our patch. +%if 0%{?__isa_bits} == 64 +Requires: libgnutls.so.30()(64bit) +%else +Requires: libgnutls.so.30 +%endif -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/552 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/569 -Patch6: gvariant-tests.patch +# Remove gamin dependency +Obsoletes: glib2-fam < 2.67.1-3 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/105 -Patch7: 105.patch +# glib 2.59.0 hash table changes broke older gcr versions / password prompts in gnome-shell +Conflicts: gcr < 3.28.1 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/532 -Patch8: 532.patch - -# Backported from git -Patch41: 0001-gdbus-Avoid-printing-null-strings.patch - -# https://bugzilla.redhat.com/show_bug.cgi?id=1777213 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1176 -Patch9: 1176.patch - -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/450 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/603 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/974 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/984 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/985 -Patch10: keyfile-backend.patch -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/604 -Patch11: CVE-2019-13012.patch - -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1942 -Patch12: CVE-2021-27218.patch - -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1927 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2000 -Patch13: CVE-2021-27219.patch - -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1981 -Patch14: CVE-2021-28153.patch - -# https://bugzilla.redhat.com/show_bug.cgi?id=1938284 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1369 -Patch15: 1369.patch - -# https://bugzilla.redhat.com/show_bug.cgi?id=1948988 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/873 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1353 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1691 -Patch16: gmain-corruption.patch - -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1713 -Patch17: 1713.patch - -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2244 -Patch18: 2244.patch - -# https://bugzilla.redhat.com/show_bug.cgi?id=2014652 -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2291 -Patch19: gnetworkmonitornm.patch - -# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/13 -Patch20: 13.patch +Provides: bundled(gnulib) +Provides: bundled(gvdb) +Provides: bundled(libcharset) +Provides: bundled(xdgmime) %description GLib is the low-level core library that forms the basis for projects @@ -139,14 +100,6 @@ BuildArch: noarch %description doc The glib2-doc package includes documentation for the GLib library. -%package fam -Summary: FAM monitoring module for GIO -Requires: %{name}%{?_isa} = %{version}-%{release} -BuildRequires: gamin-devel - -%description fam -The glib2-fam package contains the FAM (File Alteration Monitor) module for GIO. - %package static Summary: glib static Requires: %{name}-devel = %{version}-%{release} @@ -165,57 +118,45 @@ the functionality of the installed glib2 package. %prep %autosetup -n glib-%{version} -p1 -# restore timestamps after patching to appease multilib for .pyc files -tar vtf %{SOURCE0} | while read mode user size date time name; do touch -d "$date $time" ../$name; done - %build -autoreconf -f -i - # Bug 1324770: Also explicitly remove PCRE sources since we use --with-pcre=system rm glib/pcre/*.[ch] -# Support builds of both git snapshots and tarballs packed with autogoo -(if ! test -x configure; then NOCONFIGURE=1 ./autogen.sh; CONFIGFLAGS=--enable-gtk-doc; fi; - %configure $CONFIGFLAGS \ - --with-python=%{__python3} \ - --with-pcre=system \ - --enable-systemtap \ - --enable-static \ - --enable-installed-tests -) - -%make_build + +%meson \ + -Dman=true \ + -Ddtrace=true \ + -Dsystemtap=true \ + -Dsysprof=enabled \ + -Dglib_debug=disabled \ + -Dgtk_doc=true \ + -Dinstalled_tests=true \ + -Dgnutls=true \ + --default-library=both \ + %{nil} + +%meson_build %install -# Use -p to preserve timestamps on .py files to ensure -# they're not recompiled with different timestamps -# to help multilib: https://bugzilla.redhat.com/show_bug.cgi?id=718404 -%make_install INSTALL="install -p" -# Also since this is a generated .py file, set it to a known timestamp, -# otherwise it will vary by build time, and thus break multilib -devel -# installs. -touch -r gio/gdbus-2.0/codegen/config.py.in $RPM_BUILD_ROOT/%{_datadir}/glib-2.0/codegen/config.py -# patch0 changes the timestamp of codegen.py; reset it to a known value to not -# break multilib -touch -r gio/gdbus-2.0/codegen/config.py.in $RPM_BUILD_ROOT/%{_datadir}/glib-2.0/codegen/codegen.py -chrpath --delete $RPM_BUILD_ROOT%{_libdir}/*.so - -rm -f $RPM_BUILD_ROOT%{_libdir}/*.la -rm -f $RPM_BUILD_ROOT%{_libdir}/gio/modules/*.{a,la} -rm -f $RPM_BUILD_ROOT%{_libexecdir}/installed-tests/glib/*.{a,la} -rm -f $RPM_BUILD_ROOT%{_libexecdir}/installed-tests/glib/modules/*.{a,la} -# Remove python files bytecompiled by the build system. rpmbuild regenerates -# them again later in a brp script using the timestamps set above. -rm -f $RPM_BUILD_ROOT%{_datadir}/glib-2.0/gdb/*.{pyc,pyo} -rm -rf $RPM_BUILD_ROOT%{_datadir}/glib-2.0/gdb/__pycache__/ -rm -f $RPM_BUILD_ROOT%{_datadir}/glib-2.0/codegen/*.{pyc,pyo} -rm -rf $RPM_BUILD_ROOT%{_datadir}/glib-2.0/codegen/__pycache__/ - -mv $RPM_BUILD_ROOT%{_bindir}/gio-querymodules $RPM_BUILD_ROOT%{_bindir}/gio-querymodules-%{__isa_bits} - -touch $RPM_BUILD_ROOT%{_libdir}/gio/modules/giomodule.cache - -# bash-completion scripts need not be executable -chmod 644 $RPM_BUILD_ROOT%{_datadir}/bash-completion/completions/* +%meson_install +# Since this is a generated .py file, set it to a known timestamp for +# better reproducibility. +# Also copy the timestamp for other .py files, because meson doesn't +# do this, see https://github.com/mesonbuild/meson/issues/5027. +touch -r gio/gdbus-2.0/codegen/config.py.in %{buildroot}%{_datadir}/glib-2.0/codegen/*.py +chrpath --delete %{buildroot}%{_libdir}/*.so + +# Perform byte compilation manually to avoid issues with +# irreproducibility of the default invalidation mode, see +# https://www.python.org/dev/peps/pep-0552/ and +# https://bugzilla.redhat.com/show_bug.cgi?id=1686078 +export PYTHONHASHSEED=0 +%py_byte_compile %{__python3} %{buildroot}%{_datadir} + +mv %{buildroot}%{_bindir}/gio-querymodules %{buildroot}%{_bindir}/gio-querymodules-%{__isa_bits} +sed -i -e "/^gio_querymodules=/s/gio-querymodules/gio-querymodules-%{__isa_bits}/" %{buildroot}%{_libdir}/pkgconfig/gio-2.0.pc + +mkdir -p %{buildroot}%{_libdir}/gio/modules +touch %{buildroot}%{_libdir}/gio/modules/giomodule.cache %find_lang glib20 @@ -241,9 +182,10 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : %{_libdir}/libgio-2.0.so.* %dir %{_datadir}/bash-completion %dir %{_datadir}/bash-completion/completions +%{_datadir}/bash-completion/completions/gapplication %{_datadir}/bash-completion/completions/gdbus +%{_datadir}/bash-completion/completions/gio %{_datadir}/bash-completion/completions/gsettings -%{_datadir}/bash-completion/completions/gapplication %dir %{_datadir}/glib-2.0 %dir %{_datadir}/glib-2.0/schemas %dir %{_libdir}/gio @@ -297,10 +239,7 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : %{_datadir}/systemtap/ %files doc -%doc %{_datadir}/gtk-doc/html/* - -%files fam -%{_libdir}/gio/modules/libgiofam.so +%{_datadir}/gtk-doc/ %files static %{_libdir}/libgio-2.0.a @@ -314,112 +253,332 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : %{_datadir}/installed-tests %changelog -* Wed Sep 21 2022 Weitao Zhou 2.56.4-159.0.1 -- gdbus: Avoid printing null strings to fix build failed with gcc9.2 +* Tue Nov 29 2022 Chang Gao - 2.68.4-5.0.1 +- Rebuild for anolis -* Fri Apr 22 2022 Michael Catanzaro - 2.56.4-159 -- Add --interface-info-[body|header] modes to gdbus-codegen -- Related: #2061994 +* Fri Jan 21 2022 Michael Catanzaro - 2.68.4-5 +- Add one more upstream patch to gspawn patchset +- Related: #1910092 -* Wed Dec 01 2021 Michael Catanzaro - 2.56.4-158 +* Fri Jan 21 2022 Michael Catanzaro - 2.68.4-4 +- Add gspawn patchset +- Resolves: #1910092 + +* Wed Dec 01 2021 Michael Catanzaro - 2.68.4-3 - Fix GNetworkMonitor after NetworkManager D-Bus API changes -- Resolves: #2014652 +- Resolves: #2014624 -* Wed Sep 15 2021 Michael Catanzaro - 2.56.4-157 +* Wed Sep 15 2021 Michael Catanzaro - 2.68.4-2 - Fix g_get_user_database_entry() crash when used with nss-systemd -- Resolves: #2002126 - -* Thu Jul 01 2021 Michael Catanzaro - 2.56.4-156 -- Fix test failure introduced in previous update -- Related: #1971533 - -* Wed Jun 23 2021 Michael Catanzaro - 2.56.4-14 -- Refresh GHmac patchset -- Resolves: #1971533 - -* Thu May 20 2021 Michael Catanzaro - 2.56.4-13 -- Rename and consolidate existing patches for better maintainability -- Refresh CVE-2021-27219 patcheset, using better-targeted fixes - Resolves: #1939108 - -* Wed May 05 2021 Michael Catanzaro - 2.56.4-12 -- Fix various problems in GMainContext - Resolves: #1948988 - -* Tue May 04 2021 Michael Catanzaro - 2.56.4-11 -- Remove CHARSETALIASDIR environment variable - Resolves: #1938284 - -* Wed Mar 31 2021 Michael Catanzaro - 2.56.4-10 -- Fix CVE-2021-27218 - Resolves: #1939072 -- Fix CVE-2021-27219 - Resolves: #1939108 -- Fix CVE-2021-28153 - Resolves: #1939118 - -* Tue Nov 10 2020 Michael Catanzaro - 2.56.4-9 -- Update GHmac patch to implement g_hmac_copy() - Resolves: #1786538 -- Update keyfile settings backend - Resolves: #1728896 -- Fix CVE-2019-13012 - Resolves: #1728632 - -* Mon Dec 02 2019 Colin Walters - 2.56.4-8 -- Backport patches for GDBus auth - Resolves: #1777213 - -* Sat Jul 13 2019 Colin Walters - 2.56.4-7 -- Backport patch for CVE-2019-12450 - Resolves: #1722101 - -* Mon Jun 17 2019 Ray Strode - 2.56.4-5 -- Backport glib2 change needed for accountsservice dbus - codegen fix - Resolves: #1713081 - -* Mon Jun 10 2019 Colin Walters - 2.56.4-4 -- Back GHmac with GnuTLS for FIPS -- Resolves: #1630260 - -* Fri May 31 2019 Florian Müllner - 2.56.4-3 -- Backport per-desktop overrides -- Resolves: #1715951 - -* Tue Apr 02 2019 Colin Walters - 2.56.4-2 -- Add system LDFLAGS -- Resolves: #1630566 - -* Mon Jan 14 2019 Kalev Lember - 2.56.4-1 -- Update to 2.56.4 -- Resolves: #1660859 - -* Mon Jan 14 2019 Kalev Lember - 2.56.1-7 -- Remove .la files from -tests subpackage - -* Mon Jan 14 2019 Kalev Lember - 2.56.1-6 -- Fix multilib -devel installs -- Related: #1639428 - -* Mon Jan 14 2019 Kalev Lember - 2.56.1-5 -- Fix gdbus codegen generated proxies breaking strict aliasing rules -- Resolves: #1639428 - -* Mon Dec 17 2018 Ray Strode - 2.56.1-4 -- Ensure shared-mime-info is installed during testing -- Ensure test suite runs as unprivileged user -- Ensure test suite works when debugging is enabled -- Ensure echo-script from spawn test is marked executable - Related: #1625683 - -* Fri Dec 14 2018 Ray Strode - 2.56.1-3 -- rebuild - Related: #1625683 - -* Mon Dec 10 2018 Josh Boyer - 2.56.1-2 -- Rebuild for CET note fixes - Resolves: #1657311 +- Resolves: #2004711 + +* Sat Aug 21 2021 Kalev Lember - 2.68.4-1 +- Update to 2.68.4 + +* Wed Aug 18 2021 DJ Delorie - 2.68.3-6 +- Rebuilt for libffi 3.4.2 SONAME transition. + Related: rhbz#1891914 + +* Tue Aug 17 2021 Michael Catanzaro - 2.68.3-5 +- Backport GPowerProfileMonitor +- Resolves: #1994466 + +* Mon Aug 09 2021 Mohan Boddu - 2.68.3-4 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Tue Jul 27 2021 Michael Catanzaro - 2.68.3-3 +- Fix build with glibc 2.34 +- Resolves: #1984626 + +* Thu Jul 01 2021 Michael Catanzaro - 2.68.3-2 +- Refresh gnutls-hmac patchset to fix leaks in error path +- Related: #1971823 + +* Mon Jun 28 2021 Michael Catanzaro - 2.68.3-1 +- Update to 2.68.3 +- Resolves: #1976713 +- Remove Recommends: shared-mime-info +- Resolves: #1947897 + +* Wed Jun 23 2021 Michael Catanzaro - 2.68.2-2 +- Update GHmac patchset and reenable glib2-static +- Resolves: #1971823 + +* Wed May 19 2021 Michael Catanzaro - 2.68.2-1 +- Update to 2.68.2 +- Resolves: #1961039 + +* Tue May 11 2021 Michael Catanzaro - 2.68.1-4 +- No changes, bump revision to retry gating +- Related: #1951126 + +* Fri May 07 2021 Michael Catanzaro - 2.68.1-3 +- Add missing bundled provides +- Add rpminspect gating configuration +- Consolidate GDesktopAppInfo patchset +- Resolves: #1951126 + +* Wed Apr 28 2021 Michael Catanzaro - 2.68.1-2 +- Refresh GDesktopAppInfo patchset +- Related: #1951126 + +* Thu Apr 22 2021 Kalev Lember - 2.68.1-1 +- Update to 2.68.1 + +* Thu Apr 15 2021 Mohan Boddu - 2.68.0-3 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Fri Mar 26 2021 Kalev Lember - 2.68.0-2 +- Rebuild to fix sysprof-capture symbols leaking into libraries consuming it + +* Thu Mar 18 2021 Kalev Lember - 2.68.0-1 +- Update to 2.68.0 + +* Thu Mar 18 2021 Petr Pisar - 2.67.6-2 +- Disable debugging glib (bug #1936339) + +* Thu Mar 11 2021 Kalev Lember - 2.67.6-1 +- Update to 2.67.6 + +* Tue Mar 02 2021 Kalev Lember - 2.67.5-1 +- Update to 2.67.5 + +* Wed Feb 24 2021 Kalev Lember - 2.67.4-3 +- Enable sysprof capture support + +* Fri Feb 19 2021 Kalev Lember - 2.67.4-2 +- Backport a fix for gsubprocesslauncher regression + +* Tue Feb 16 2021 Kalev Lember - 2.67.4-1 +- Update to 2.67.4 + +* Tue Feb 09 2021 Benjamin Berg - 2.67.3-2 +- Add patches to move applications into systemd scopes + +* Thu Feb 04 2021 Kalev Lember - 2.67.3-1 +- Update to 2.67.3 +- Fix gtk-doc directory ownership + +* Tue Jan 26 2021 Fedora Release Engineering - 2.67.1-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Fri Jan 22 2021 Peter Robinson - 2.67.1-3 +- Drop dependency on gamin + +* Sat Dec 19 2020 Kevin Fenzi - 2.67.1-2 +- Add already upstream patch to fix gdm crasher. + +* Sat Dec 19 2020 Kalev Lember - 2.67.1-1 +- Update to 2.67.1 + +* Fri Dec 04 2020 Ondrej Holy - 2.67.0-7 +- Explicitly create modules dir to fix ELN build + +* Tue Dec 01 2020 Ondrej Holy and Michael Catanzaro - 2.67.0-6 +- Disable glib2-fam in RHEL + +* Tue Nov 24 2020 Kalev Lember - 2.67.0-5 +- Backport upstream patches to fix invalid use of volatile objects + (gcc 11 support) + +* Wed Nov 11 2020 Michael Catanzaro - 2.67.0-4 +- Make GnuTLS patch RHEL-specific, and make glib2-static subpackage Fedora-specific + +* Tue Nov 10 2020 Michael Catanzaro - 2.67.0-3 +- Use GnuTLS to implement GHmac (thanks to Colin Walters) + +* Wed Nov 04 2020 Michael Catanzaro - 2.67.0-2 +- Backport fix for GSocketClient crash + +* Thu Oct 29 2020 Kalev Lember - 2.67.0-1 +- Update to 2.67.0 + +* Mon Oct 19 2020 Kalev Lember - 2.66.2-1 +- Update to 2.66.2 +- Drop gtk-doc patch as we finally have a new enough gtk-doc + +* Wed Oct 14 2020 Michael Catanzaro - 2.66.1-3 +- Fix yet another timezone bug + +* Wed Oct 14 2020 Michael Catanzaro - 2.66.1-2 +- Fix timezone-related bugs in many applications caused by new glib timezone cache + +* Thu Oct 1 2020 Kalev Lember - 2.66.1-1 +- Update to 2.66.1 + +* Thu Sep 10 2020 Kalev Lember - 2.66.0-1 +- Update to 2.66.0 + +* Wed Sep 02 2020 Kalev Lember - 2.65.3-1 +- Update to 2.65.3 + +* Tue Aug 25 2020 Adam Williamson - 2.65.2-3 +- Backport fix for GGO #2189 (error accessing some filesystems) + +* Thu Aug 20 2020 Jeff Law - 2.65.2-2 +- Re-enable LTO + +* Tue Aug 18 2020 Kalev Lember - 2.65.2-1 +- Update to 2.65.2 + +* Mon Aug 17 2020 Kalev Lember - 2.65.1-1 +- Update to 2.65.1 + +* Sat Aug 01 2020 Fedora Release Engineering - 2.65.0-5 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 27 2020 Fedora Release Engineering - 2.65.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue Jun 30 2020 Jeff Law - 2.65.0-3 +Disable LTO + +* Mon Jun 22 2020 Kalev Lember - 2.65.0-2 +- Update gio-2.0.pc with correct gio-querymodules name when renaming it + (#1849441) + +* Mon Jun 22 2020 Kalev Lember - 2.65.0-1 +- Update to 2.65.0 + +* Wed May 20 2020 Kalev Lember - 2.64.3-1 +- Update to 2.64.3 + +* Tue Apr 28 2020 Tomas Popela - 2.64.2-2 +- Backport fix for a race condition in GCancellable (rhbz#1825230) + +* Fri Apr 10 2020 Kalev Lember - 2.64.2-1 +- Update to 2.64.2 + +* Wed Mar 11 2020 Kalev Lember - 2.64.1-1 +- Update to 2.64.1 + +* Mon Mar 02 2020 Kalev Lember - 2.64.0-1 +- Update to 2.64.0 + +* Mon Feb 24 2020 Kalev Lember - 2.63.6-1 +- Update to 2.63.6 + +* Wed Feb 12 2020 Kalev Lember - 2.63.5-3 +- Backport a patch to work around SELinux policies not allowing + SYS_sched_setattr (#1795524) + +* Fri Feb 07 2020 Michael Catanzaro - 2.63.5-2 +- Add patch for CVE-2020-6750 and related issues. + +* Mon Feb 03 2020 Kalev Lember - 2.63.5-1 +- Update to 2.63.5 + +* Wed Jan 29 2020 Stephen Gallagher - 2.63.4-3 +- Fix GThreadPool initialization that is breaking createrepo_c (BZ #1795052) + +* Tue Jan 28 2020 Fedora Release Engineering - 2.63.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Fri Jan 24 2020 Kalev Lember - 2.63.4-1 +- Update to 2.63.4 + +* Mon Dec 16 2019 Kalev Lember - 2.63.3-1 +- Update to 2.63.3 + +* Mon Dec 02 2019 Kalev Lember - 2.63.2-1 +- Update to 2.63.2 + +* Fri Oct 04 2019 Kalev Lember - 2.63.0-1 +- Update to 2.63.0 + +* Fri Oct 04 2019 Kalev Lember - 2.62.1-1 +- Update to 2.62.1 + +* Fri Sep 06 2019 Kalev Lember - 2.62.0-1 +- Update to 2.62.0 + +* Tue Sep 03 2019 Kalev Lember - 2.61.3-1 +- Update to 2.61.3 + +* Mon Aug 12 2019 Kalev Lember - 2.61.2-1 +- Update to 2.61.2 + +* Thu Jul 25 2019 Fedora Release Engineering - 2.61.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Tue Jun 11 2019 David King - 2.61.1-2 +- Fix CVE-2019-12450 (#1719142) +- Consistently use buildroot macro + +* Fri May 24 2019 Kalev Lember - 2.61.1-1 +- Update to 2.61.1 + +* Tue Apr 16 2019 Adam Williamson - 2.61.0-2 +- Rebuild with Meson fix for #1699099 + +* Mon Apr 15 2019 Kalev Lember - 2.61.0-1 +- Update to 2.61.0 + +* Mon Apr 15 2019 Kalev Lember - 2.60.1-1 +- Update to 2.60.1 + +* Wed Mar 13 2019 Zbigniew Jędrzejewski-Szmek - 2.60.0-3 +- Switch back to timestamp-based pyc invalidation mode + +* Wed Mar 6 2019 Zbigniew Jędrzejewski-Szmek - 2.60.0-2 +- Make sure all .py files have fixed timestamps (fixes issue with + parallel installability of i686 and amd64 -devel packages) +- Switch to explicit byte compilation to override invalidation mode + +* Mon Mar 04 2019 Kalev Lember - 2.60.0-1 +- Update to 2.60.0 + +* Mon Feb 18 2019 Kalev Lember - 2.59.3-1 +- Update to 2.59.3 + +* Mon Feb 04 2019 Kalev Lember - 2.59.2-1 +- Update to 2.59.2 + +* Thu Jan 31 2019 Fedora Release Engineering - 2.59.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Sat Jan 26 2019 Kalev Lember - 2.59.1-1 +- Update to 2.59.1 + +* Thu Jan 03 2019 Kalev Lember - 2.59.0-1 +- Update to 2.59.0 +- Switch to the meson build system + +* Tue Dec 18 2018 Kalev Lember - 2.58.2-1 +- Update to 2.58.2 + +* Fri Oct 05 2018 Kalev Lember - 2.58.1-2 +- Fix multilib -devel installs (#1634778) + +* Fri Sep 21 2018 Kalev Lember - 2.58.1-1 +- Update to 2.58.1 + +* Wed Sep 05 2018 Kalev Lember - 2.58.0-1 +- Update to 2.58.0 + +* Thu Aug 2 2018 Ondrej Holy - 2.57.2-1 +- Update to 2.57.2 + +* Fri Jul 20 2018 Ondrej Holy - 2.57.1-1 +- Update to 2.57.1 + +* Fri Jul 13 2018 Fedora Release Engineering - 2.56.1-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Tue Jun 19 2018 Miro Hrončok - 2.56.1-5 +- Rebuilt for Python 3.7 + +* Thu Jun 14 2018 Debarshi Ray - 2.56.1-4 +- Backport patch to fix possible invalid pointer in dbus callback in the FD.o + notification backend (RH #1584916) + +* Sun May 27 2018 Kalev Lember - 2.56.1-3 +- Fix multilib -devel installs (#1581067) + +* Sun May 13 2018 Fabio Valentini - 2.56.1-2 +- Include upstream patch to fix gdbus-codegen with meson 0.46. * Sun Apr 08 2018 Kalev Lember - 2.56.1-1 - Update to 2.56.1 diff --git a/gmain-corruption.patch b/gmain-corruption.patch deleted file mode 100644 index 0aa509da9b1acd0c98495c9795e2fb016e17ef20..0000000000000000000000000000000000000000 --- a/gmain-corruption.patch +++ /dev/null @@ -1,386 +0,0 @@ -From 2bad3cb3bf8f0cc3f45057061f9a538ecf7742b6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= -Date: Thu, 14 Feb 2019 17:46:33 +0200 -Subject: [PATCH 1/5] Use atomic reference counting for GSource - -If attached to a context already it would use a mutex instead but at -least before that the reference counting is not thread-safe currently. ---- - glib/gmain.c | 50 +++++++++++++++----------------------------------- - 1 file changed, 15 insertions(+), 35 deletions(-) - -diff --git a/glib/gmain.c b/glib/gmain.c -index 26e68823d..5b91c3117 100644 ---- a/glib/gmain.c -+++ b/glib/gmain.c -@@ -374,15 +374,6 @@ typedef struct _GSourceIter - #define SOURCE_DESTROYED(source) (((source)->flags & G_HOOK_FLAG_ACTIVE) == 0) - #define SOURCE_BLOCKED(source) (((source)->flags & G_SOURCE_BLOCKED) != 0) - --#define SOURCE_UNREF(source, context) \ -- G_STMT_START { \ -- if ((source)->ref_count > 1) \ -- (source)->ref_count--; \ -- else \ -- g_source_unref_internal ((source), (context), TRUE); \ -- } G_STMT_END -- -- - /* Forward declarations */ - - static void g_source_unref_internal (GSource *source, -@@ -977,10 +968,10 @@ g_source_iter_next (GSourceIter *iter, GSource **source) - */ - - if (iter->source && iter->may_modify) -- SOURCE_UNREF (iter->source, iter->context); -+ g_source_unref_internal (iter->source, iter->context, TRUE); - iter->source = next_source; - if (iter->source && iter->may_modify) -- iter->source->ref_count++; -+ g_source_ref (iter->source); - - *source = iter->source; - return *source != NULL; -@@ -994,7 +985,7 @@ g_source_iter_clear (GSourceIter *iter) - { - if (iter->source && iter->may_modify) - { -- SOURCE_UNREF (iter->source, iter->context); -+ g_source_unref_internal (iter->source, iter->context, TRUE); - iter->source = NULL; - } - } -@@ -1135,7 +1126,7 @@ g_source_attach_unlocked (GSource *source, - - source->context = context; - source->source_id = id; -- source->ref_count++; -+ g_source_ref (source); - - g_hash_table_insert (context->sources, GUINT_TO_POINTER (id), source); - -@@ -1675,7 +1666,7 @@ g_source_set_funcs (GSource *source, - { - g_return_if_fail (source != NULL); - g_return_if_fail (source->context == NULL); -- g_return_if_fail (source->ref_count > 0); -+ g_return_if_fail (g_atomic_int_get (&source->ref_count) > 0); - g_return_if_fail (funcs != NULL); - - source->source_funcs = funcs; -@@ -2050,19 +2041,9 @@ g_source_set_name_by_id (guint tag, - GSource * - g_source_ref (GSource *source) - { -- GMainContext *context; -- - g_return_val_if_fail (source != NULL, NULL); - -- context = source->context; -- -- if (context) -- LOCK_CONTEXT (context); -- -- source->ref_count++; -- -- if (context) -- UNLOCK_CONTEXT (context); -+ g_atomic_int_inc (&source->ref_count); - - return source; - } -@@ -2078,12 +2059,11 @@ g_source_unref_internal (GSource *source, - GSourceCallbackFuncs *old_cb_funcs = NULL; - - g_return_if_fail (source != NULL); -- -+ - if (!have_lock && context) - LOCK_CONTEXT (context); - -- source->ref_count--; -- if (source->ref_count == 0) -+ if (g_atomic_int_dec_and_test (&source->ref_count)) - { - TRACE (GLIB_SOURCE_BEFORE_FREE (source, context, - source->source_funcs->finalize)); -@@ -2107,20 +2087,20 @@ g_source_unref_internal (GSource *source, - { - /* Temporarily increase the ref count again so that GSource methods - * can be called from finalize(). */ -- source->ref_count++; -+ g_atomic_int_inc (&source->ref_count); - if (context) - UNLOCK_CONTEXT (context); - source->source_funcs->finalize (source); - if (context) - LOCK_CONTEXT (context); -- source->ref_count--; -+ g_atomic_int_add (&source->ref_count, -1); - } - - if (old_cb_funcs) - { - /* Temporarily increase the ref count again so that GSource methods - * can be called from callback_funcs.unref(). */ -- source->ref_count++; -+ g_atomic_int_inc (&source->ref_count); - if (context) - UNLOCK_CONTEXT (context); - -@@ -2128,7 +2108,7 @@ g_source_unref_internal (GSource *source, - - if (context) - LOCK_CONTEXT (context); -- source->ref_count--; -+ g_atomic_int_add (&source->ref_count, -1); - } - - g_free (source->name); -@@ -3201,7 +3181,7 @@ g_main_dispatch (GMainContext *context) - } - } - -- SOURCE_UNREF (source, context); -+ g_source_unref_internal (source, context, TRUE); - } - - g_ptr_array_set_size (context->pending_dispatches, 0); -@@ -3440,7 +3420,7 @@ g_main_context_prepare (GMainContext *context, - for (i = 0; i < context->pending_dispatches->len; i++) - { - if (context->pending_dispatches->pdata[i]) -- SOURCE_UNREF ((GSource *)context->pending_dispatches->pdata[i], context); -+ g_source_unref_internal ((GSource *)context->pending_dispatches->pdata[i], context, TRUE); - } - g_ptr_array_set_size (context->pending_dispatches, 0); - -@@ -3788,7 +3768,7 @@ g_main_context_check (GMainContext *context, - - if (source->flags & G_SOURCE_READY) - { -- source->ref_count++; -+ g_source_ref (source); - g_ptr_array_add (context->pending_dispatches, source); - - n_ready++; --- -2.31.1 - -From 323d0c7658a9a44efc327840c0667044a4b98f89 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= -Date: Mon, 3 Feb 2020 15:38:28 +0200 -Subject: [PATCH 2/5] GMainContext - Fix GSource iterator if iteration can - modify the list - -We first have to ref the next source and then unref the previous one. -This might be the last reference to the previous source, and freeing the -previous source might unref and free the next one which would then leave -use with a dangling pointer here. - -Fixes https://gitlab.gnome.org/GNOME/glib/issues/2031 ---- - glib/gmain.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/glib/gmain.c b/glib/gmain.c -index 5b91c3117..a3ea1d36c 100644 ---- a/glib/gmain.c -+++ b/glib/gmain.c -@@ -965,13 +965,17 @@ g_source_iter_next (GSourceIter *iter, GSource **source) - * GSourceList to be removed from source_lists (if iter->source is - * the only source in its list, and it is destroyed), so we have to - * keep it reffed until after we advance iter->current_list, above. -+ * -+ * Also we first have to ref the next source before unreffing the -+ * previous one as unreffing the previous source can potentially -+ * free the next one. - */ -+ if (next_source && iter->may_modify) -+ g_source_ref (next_source); - - if (iter->source && iter->may_modify) - g_source_unref_internal (iter->source, iter->context, TRUE); - iter->source = next_source; -- if (iter->source && iter->may_modify) -- g_source_ref (iter->source); - - *source = iter->source; - return *source != NULL; --- -2.31.1 - -From fc051ec83d8894dd754bf364562ba9be9ff999fc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= -Date: Mon, 3 Feb 2020 15:35:51 +0200 -Subject: [PATCH 3/5] GMainContext - Fix memory leaks and memory corruption - when freeing sources while freeing a context - -Instead of destroying sources directly while freeing the context, and -potentially freeing them if this was the last reference to them, collect -new references of all sources in a separate list before and at the same -time invalidate their context so that they can't access it anymore. Only -once all sources have their context invalidated, destroy them while -still keeping a reference to them. Once all sources are destroyed we get -rid of the additional references and free them if nothing else keeps a -reference to them anymore. - -This fixes a regression introduced by 26056558be in 2012. - -The previous code that invalidated the context of each source and then -destroyed it before going to the next source without keeping an -additional reference caused memory leaks or memory corruption depending -on the order of the sources in the sources lists. - -If a source was destroyed it might happen that this was the last -reference to this source, and it would then be freed. This would cause -the finalize function to be called, which might destroy and unref -another source and potentially free it. This other source would then -either -- go through the normal free logic and change the intern linked list - between the sources, while other sources that are unreffed as part of - the main context freeing would not. As such the list would be in an - inconsistent state and we might dereference freed memory. -- go through the normal destroy and free logic but because the context - pointer was already invalidated it would simply mark the source as - destroyed without actually removing it from the context. This would - then cause a memory leak because the reference owned by the context is - not freed. - -Fixes https://github.com/gtk-rs/glib/issues/583 while still keeping -https://bugzilla.gnome.org/show_bug.cgi?id=661767 fixes. ---- - glib/gmain.c | 35 ++++++++++++++++++++++++++++++++++- - 1 file changed, 34 insertions(+), 1 deletion(-) - -diff --git a/glib/gmain.c b/glib/gmain.c -index a3ea1d36c..1c249ad02 100644 ---- a/glib/gmain.c -+++ b/glib/gmain.c -@@ -534,6 +534,7 @@ g_main_context_unref (GMainContext *context) - GSourceIter iter; - GSource *source; - GList *sl_iter; -+ GSList *s_iter, *remaining_sources = NULL; - GSourceList *list; - guint i; - -@@ -553,10 +554,30 @@ g_main_context_unref (GMainContext *context) - - /* g_source_iter_next() assumes the context is locked. */ - LOCK_CONTEXT (context); -- g_source_iter_init (&iter, context, TRUE); -+ -+ /* First collect all remaining sources from the sources lists and store a -+ * new reference in a separate list. Also set the context of the sources -+ * to NULL so that they can't access a partially destroyed context anymore. -+ * -+ * We have to do this first so that we have a strong reference to all -+ * sources and destroying them below does not also free them, and so that -+ * none of the sources can access the context from their finalize/dispose -+ * functions. */ -+ g_source_iter_init (&iter, context, FALSE); - while (g_source_iter_next (&iter, &source)) - { - source->context = NULL; -+ remaining_sources = g_slist_prepend (remaining_sources, g_source_ref (source)); -+ } -+ g_source_iter_clear (&iter); -+ -+ /* Next destroy all sources. As we still hold a reference to all of them, -+ * this won't cause any of them to be freed yet and especially prevents any -+ * source that unrefs another source from its finalize function to be freed. -+ */ -+ for (s_iter = remaining_sources; s_iter; s_iter = s_iter->next) -+ { -+ source = s_iter->data; - g_source_destroy_internal (source, context, TRUE); - } - UNLOCK_CONTEXT (context); -@@ -581,6 +602,18 @@ g_main_context_unref (GMainContext *context) - g_cond_clear (&context->cond); - - g_free (context); -+ -+ /* And now finally get rid of our references to the sources. This will cause -+ * them to be freed unless something else still has a reference to them. Due -+ * to setting the context pointers in the sources to NULL above, this won't -+ * ever access the context or the internal linked list inside the GSource. -+ * We already removed the sources completely from the context above. */ -+ for (s_iter = remaining_sources; s_iter; s_iter = s_iter->next) -+ { -+ source = s_iter->data; -+ g_source_unref_internal (source, NULL, FALSE); -+ } -+ g_slist_free (remaining_sources); - } - - /* Helper function used by mainloop/overflow test. --- -2.31.1 - -From 1d16e92028f235ed9cd786070832d5bd71017661 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= -Date: Tue, 11 Feb 2020 09:34:38 +0200 -Subject: [PATCH 4/5] GMainContext - Move mutex unlocking in destructor right - before freeing the mutex - -This does not have any behaviour changes but is cleaner. The mutex is -only unlocked now after all operations on the context are done and right -before freeing the mutex and the context itself. ---- - glib/gmain.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/glib/gmain.c b/glib/gmain.c -index 1c249ad02..44e6ed0c3 100644 ---- a/glib/gmain.c -+++ b/glib/gmain.c -@@ -580,7 +580,6 @@ g_main_context_unref (GMainContext *context) - source = s_iter->data; - g_source_destroy_internal (source, context, TRUE); - } -- UNLOCK_CONTEXT (context); - - for (sl_iter = context->source_lists; sl_iter; sl_iter = sl_iter->next) - { -@@ -591,6 +590,7 @@ g_main_context_unref (GMainContext *context) - - g_hash_table_destroy (context->sources); - -+ UNLOCK_CONTEXT (context); - g_mutex_clear (&context->mutex); - - g_ptr_array_free (context->pending_dispatches, TRUE); --- -2.31.1 - -From 02ad7294ad5895178df73a6cd8546c6e67097493 Mon Sep 17 00:00:00 2001 -From: Benjamin Berg -Date: Tue, 13 Oct 2020 15:09:43 +0200 -Subject: [PATCH 5/5] gmain: Fix possible locking issue in source unref - -When unref'ing child sources, the lock is already held. But instead of -passing TRUE to g_source_unref_internal it currently passes whether the -lock was already held outside of the current invocation. Just pass TRUE -to fix this possible issue. ---- - glib/gmain.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/glib/gmain.c b/glib/gmain.c -index 44e6ed0c3..95992253d 100644 ---- a/glib/gmain.c -+++ b/glib/gmain.c -@@ -2164,7 +2164,7 @@ g_source_unref_internal (GSource *source, - g_slist_remove (source->priv->child_sources, child_source); - child_source->priv->parent_source = NULL; - -- g_source_unref_internal (child_source, context, have_lock); -+ g_source_unref_internal (child_source, context, TRUE); - } - - g_slice_free (GSourcePrivate, source->priv); --- -2.31.1 diff --git a/gnetworkmonitornm.patch b/gnetworkmonitornm.patch deleted file mode 100644 index 977fc6351118b9393f20e0718ffbc575ed361ebe..0000000000000000000000000000000000000000 --- a/gnetworkmonitornm.patch +++ /dev/null @@ -1,431 +0,0 @@ -From c48c984d39afeae84b0cad515f08f83c711fd9c4 Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Thu, 13 Sep 2018 10:25:05 +0100 -Subject: [PATCH 1/9] gnetworkmonitornm: Set a GError properly on an error - handling path -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -All the other initialisation failure paths set a GError, but this one -didn’t. Set a GError to avoid breaking the invariant that returning -FALSE should always have a GError set. - -Signed-off-by: Philip Withnall - -https://gitlab.gnome.org/GNOME/glib/issues/1523 ---- - gio/gnetworkmonitornm.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/gio/gnetworkmonitornm.c b/gio/gnetworkmonitornm.c -index 20a86571f..5bc8c925a 100644 ---- a/gio/gnetworkmonitornm.c -+++ b/gio/gnetworkmonitornm.c -@@ -309,6 +309,8 @@ g_network_monitor_nm_initable_init (GInitable *initable, - - if (!name_owner) - { -+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, -+ _("NetworkManager not running")); - g_object_unref (proxy); - return FALSE; - } --- -2.33.1 - -From d139986b1f213a7e1c1e3968ad2d8270f820bd57 Mon Sep 17 00:00:00 2001 -From: Antonio Larrosa -Date: Tue, 12 Mar 2019 18:35:10 +0100 -Subject: [PATCH 2/9] Handle an UNKNOWN NetworkManager connectivity as NONE - -nm_conn_to_g_conn already handles UNKNOWN like NONE (returning -G_NETWORK_CONNECTIVITY_LOCAL in both cases). So in sync_properties -we should also set new_connectivity to G_NETWORK_CONNECTIVITY_LOCAL -for both NM_CONNECTIVITY_UNKNOWN and NM_CONNECTIVITY_NONE. - -This has the added benefit that when NetworkManager returns the network -connectivity is UNKNOWN, we set network_available to FALSE as it should -be. Previously, there were cases in a laptop with no network access, -that g_network_monitor_get_network_available returned true, which was -wrong and is also fixed with this commit. ---- - gio/gnetworkmonitornm.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/gio/gnetworkmonitornm.c b/gio/gnetworkmonitornm.c -index 5bc8c925a..4e2a35e8a 100644 ---- a/gio/gnetworkmonitornm.c -+++ b/gio/gnetworkmonitornm.c -@@ -167,7 +167,8 @@ sync_properties (GNetworkMonitorNM *nm, - nm_connectivity = g_variant_get_uint32 (v); - g_variant_unref (v); - -- if (nm_connectivity == NM_CONNECTIVITY_NONE) -+ if (nm_connectivity == NM_CONNECTIVITY_UNKNOWN || -+ nm_connectivity == NM_CONNECTIVITY_NONE) - { - new_network_available = FALSE; - new_network_metered = FALSE; --- -2.33.1 - -From 5b4e6f9813cf90c690d8974635b0aeff8f5d2c5d Mon Sep 17 00:00:00 2001 -From: Fabrice Bellet -Date: Mon, 29 Apr 2019 12:05:54 +0000 -Subject: [PATCH 3/9] gnetworkmonitornm: Fix network available detection - -The network-available property can be asserted by querying the NMState -describing the current overval network state, instead of the -NMConnectivityState. The advantage of the NMState is that is reflects -immediately the network state modification, while the connectivity -state is tested at a fixed frequency. ---- - gio/gnetworkmonitornm.c | 39 ++++++++++++++++++++++++++++++++++++--- - 1 file changed, 36 insertions(+), 3 deletions(-) - -diff --git a/gio/gnetworkmonitornm.c b/gio/gnetworkmonitornm.c -index 4e2a35e8a..7bb480f54 100644 ---- a/gio/gnetworkmonitornm.c -+++ b/gio/gnetworkmonitornm.c -@@ -52,6 +52,19 @@ typedef enum { - NM_CONNECTIVITY_FULL - } NMConnectivityState; - -+/* Copied from https://developer.gnome.org/libnm-util/stable/libnm-util-NetworkManager.html#NMState; -+ * used inline to avoid a NetworkManager dependency from GLib. */ -+typedef enum { -+ NM_STATE_UNKNOWN = 0, -+ NM_STATE_ASLEEP = 10, -+ NM_STATE_DISCONNECTED = 20, -+ NM_STATE_DISCONNECTING = 30, -+ NM_STATE_CONNECTING = 40, -+ NM_STATE_CONNECTED_LOCAL = 50, -+ NM_STATE_CONNECTED_SITE = 60, -+ NM_STATE_CONNECTED_GLOBAL = 70, -+} NMState; -+ - struct _GNetworkMonitorNMPrivate - { - GDBusProxy *proxy; -@@ -155,11 +168,19 @@ sync_properties (GNetworkMonitorNM *nm, - gboolean emit_signals) - { - GVariant *v; -+ NMState nm_state; - NMConnectivityState nm_connectivity; - gboolean new_network_available; - gboolean new_network_metered; - GNetworkConnectivity new_connectivity; - -+ v = g_dbus_proxy_get_cached_property (nm->priv->proxy, "State"); -+ if (!v) -+ return; -+ -+ nm_state = g_variant_get_uint32 (v); -+ g_variant_unref (v); -+ - v = g_dbus_proxy_get_cached_property (nm->priv->proxy, "Connectivity"); - if (!v) - return; -@@ -167,14 +188,26 @@ sync_properties (GNetworkMonitorNM *nm, - nm_connectivity = g_variant_get_uint32 (v); - g_variant_unref (v); - -- if (nm_connectivity == NM_CONNECTIVITY_UNKNOWN || -- nm_connectivity == NM_CONNECTIVITY_NONE) -+ if (nm_state <= NM_STATE_CONNECTED_LOCAL) - { - new_network_available = FALSE; - new_network_metered = FALSE; - new_connectivity = G_NETWORK_CONNECTIVITY_LOCAL; - } -- else -+ else if (nm_state <= NM_STATE_CONNECTED_SITE) -+ { -+ new_network_available = FALSE; -+ new_network_metered = FALSE; -+ if (nm_connectivity == NM_CONNECTIVITY_PORTAL) -+ { -+ new_connectivity = G_NETWORK_CONNECTIVITY_PORTAL; -+ } -+ else -+ { -+ new_connectivity = G_NETWORK_CONNECTIVITY_LIMITED; -+ } -+ } -+ else /* nm_state == NM_STATE_CONNECTED_FULL */ - { - - /* this is only available post NM 1.0 */ --- -2.33.1 - -From 96fba295771d600e4f0f522400b2fb9b1ff42cee Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Fri, 31 May 2019 11:19:07 +0100 -Subject: [PATCH 4/9] gnetworkmonitornm: Consider NM_STATE_CONNECTED_SITE to be - available - -`NM_STATE_CONNECTED_SITE` is documented to mean that a default route is -available, but that the internet connectivity check failed. A default -route being available is compatible with the documentation for -GNetworkMonitor:network-available, which should be true if the system -has a default route for at least one of IPv4 and IPv6. - -https://developer.gnome.org/NetworkManager/stable/nm-dbus-types.html - -Signed-off-by: Philip Withnall - -Fixes: #1788 ---- - gio/gnetworkmonitornm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/gio/gnetworkmonitornm.c b/gio/gnetworkmonitornm.c -index 7bb480f54..9013fd49c 100644 ---- a/gio/gnetworkmonitornm.c -+++ b/gio/gnetworkmonitornm.c -@@ -196,7 +196,7 @@ sync_properties (GNetworkMonitorNM *nm, - } - else if (nm_state <= NM_STATE_CONNECTED_SITE) - { -- new_network_available = FALSE; -+ new_network_available = TRUE; - new_network_metered = FALSE; - if (nm_connectivity == NM_CONNECTIVITY_PORTAL) - { --- -2.33.1 - -From 74e5f472c838115f0ba19ac501805cb5b2ca837f Mon Sep 17 00:00:00 2001 -From: Bastien Nocera -Date: Mon, 29 Jul 2019 17:25:21 +0200 -Subject: [PATCH 5/9] gnetworkmonitornm: Disconnect g-signal from proxy - -So that we're sure never to receive a signal if something is keeping the -proxy alive. ---- - gio/gnetworkmonitornm.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/gio/gnetworkmonitornm.c b/gio/gnetworkmonitornm.c -index 9013fd49c..52073fac9 100644 ---- a/gio/gnetworkmonitornm.c -+++ b/gio/gnetworkmonitornm.c -@@ -68,6 +68,7 @@ typedef enum { - struct _GNetworkMonitorNMPrivate - { - GDBusProxy *proxy; -+ guint signal_id; - - GNetworkConnectivity connectivity; - gboolean network_available; -@@ -360,8 +361,8 @@ g_network_monitor_nm_initable_init (GInitable *initable, - return FALSE; - } - -- g_signal_connect (G_OBJECT (proxy), "g-signal", -- G_CALLBACK (proxy_signal_cb), nm); -+ nm->priv->signal_id = g_signal_connect (G_OBJECT (proxy), "g-signal", -+ G_CALLBACK (proxy_signal_cb), nm); - nm->priv->proxy = proxy; - sync_properties (nm, FALSE); - -@@ -373,6 +374,13 @@ g_network_monitor_nm_finalize (GObject *object) - { - GNetworkMonitorNM *nm = G_NETWORK_MONITOR_NM (object); - -+ if (nm->priv->proxy != NULL && -+ nm->priv->signal_id != 0) -+ { -+ g_signal_handler_disconnect (nm->priv->proxy, -+ nm->priv->signal_id); -+ nm->priv->signal_id = 0; -+ } - g_clear_object (&nm->priv->proxy); - - G_OBJECT_CLASS (g_network_monitor_nm_parent_class)->finalize (object); --- -2.33.1 - -From eeaf1de6e695afd971d67137caa8e39e1c1267df Mon Sep 17 00:00:00 2001 -From: Bastien Nocera -Date: Mon, 29 Jul 2019 17:26:20 +0200 -Subject: [PATCH 6/9] gnetworkmonitornm: Arguments to g-signal's callback are - const - ---- - gio/gnetworkmonitornm.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/gio/gnetworkmonitornm.c b/gio/gnetworkmonitornm.c -index 52073fac9..479653a51 100644 ---- a/gio/gnetworkmonitornm.c -+++ b/gio/gnetworkmonitornm.c -@@ -268,8 +268,8 @@ update_cached_property (GDBusProxy *proxy, - - static void - proxy_signal_cb (GDBusProxy *proxy, -- gchar *sender_name, -- gchar *signal_name, -+ const gchar *sender_name, -+ const gchar *signal_name, - GVariant *parameters, - GNetworkMonitorNM *nm) - { --- -2.33.1 - -From 46d70700c85e4419942c8a3d08bd0bf842702c4a Mon Sep 17 00:00:00 2001 -From: Bastien Nocera -Date: Mon, 29 Jul 2019 17:26:47 +0200 -Subject: [PATCH 7/9] gnetworkmonitornm: Remove double-space - ---- - gio/gnetworkmonitornm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/gio/gnetworkmonitornm.c b/gio/gnetworkmonitornm.c -index 479653a51..5a36a0ba1 100644 ---- a/gio/gnetworkmonitornm.c -+++ b/gio/gnetworkmonitornm.c -@@ -391,7 +391,7 @@ g_network_monitor_nm_class_init (GNetworkMonitorNMClass *nl_class) - { - GObjectClass *gobject_class = G_OBJECT_CLASS (nl_class); - -- gobject_class->finalize = g_network_monitor_nm_finalize; -+ gobject_class->finalize = g_network_monitor_nm_finalize; - gobject_class->get_property = g_network_monitor_nm_get_property; - - g_object_class_override_property (gobject_class, PROP_NETWORK_AVAILABLE, "network-available"); --- -2.33.1 - -From 72291aac3dac7a8ed4c85eb41608f3f5f9ad7681 Mon Sep 17 00:00:00 2001 -From: Julian Andres Klode -Date: Tue, 12 Oct 2021 12:01:50 +0200 -Subject: [PATCH 8/9] gnetworkmonitornm: Stop using removed PropertiesChanged - signal - -Use the org.freedesktop.DBus.Properties interface to listen -to PropertiesChanged signals on /org/freedesktop/NetworkManager. - -NetworkManager used to provide its own legacy PropertiesChanged -signal, but that was dropped in -https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/853 - -This requires NetworkManager >= 1.2 (2016) - -Fixes: #2505 -Bug-Ubuntu: https://bugs.launchpad.net/bugs/1946196 ---- - gio/gnetworkmonitornm.c | 29 +++++++---------------------- - 1 file changed, 7 insertions(+), 22 deletions(-) - -diff --git a/gio/gnetworkmonitornm.c b/gio/gnetworkmonitornm.c -index 5a36a0ba1..6a6d1d666 100644 ---- a/gio/gnetworkmonitornm.c -+++ b/gio/gnetworkmonitornm.c -@@ -267,29 +267,14 @@ update_cached_property (GDBusProxy *proxy, - } - - static void --proxy_signal_cb (GDBusProxy *proxy, -- const gchar *sender_name, -- const gchar *signal_name, -- GVariant *parameters, -- GNetworkMonitorNM *nm) -+proxy_properties_changed_cb (GDBusProxy *proxy, -+ GVariant *changed_properties, -+ GStrv invalidated_properties, -+ GNetworkMonitorNM *nm) - { -- GVariant *asv; - GVariantDict *dict; - -- if (g_strcmp0 (signal_name, "PropertiesChanged") != 0) -- return; -- -- g_variant_get (parameters, "(@a{sv})", &asv); -- if (!asv) -- return; -- -- dict = g_variant_dict_new (asv); -- g_variant_unref (asv); -- if (!dict) -- { -- g_warning ("Failed to handle PropertiesChanged signal from NetworkManager"); -- return; -- } -+ dict = g_variant_dict_new (changed_properties); - - update_cached_property (nm->priv->proxy, "Connectivity", dict); - -@@ -361,8 +346,8 @@ g_network_monitor_nm_initable_init (GInitable *initable, - return FALSE; - } - -- nm->priv->signal_id = g_signal_connect (G_OBJECT (proxy), "g-signal", -- G_CALLBACK (proxy_signal_cb), nm); -+ nm->priv->signal_id = g_signal_connect (G_OBJECT (proxy), "g-properties-changed", -+ G_CALLBACK (proxy_properties_changed_cb), nm); - nm->priv->proxy = proxy; - sync_properties (nm, FALSE); - --- -2.33.1 - -From 3bafff71d7588285763f603b23c830722a2169d1 Mon Sep 17 00:00:00 2001 -From: Julian Andres Klode -Date: Tue, 12 Oct 2021 17:31:42 +0200 -Subject: [PATCH 9/9] gnetworkmonitornm: Do not re-update cached property - -GDBusProxy already takes care of updating the cached property -before emitting the signal, so there is no need to do this -a second time ourselves. ---- - gio/gnetworkmonitornm.c | 22 ---------------------- - 1 file changed, 22 deletions(-) - -diff --git a/gio/gnetworkmonitornm.c b/gio/gnetworkmonitornm.c -index 6a6d1d666..a8040fb36 100644 ---- a/gio/gnetworkmonitornm.c -+++ b/gio/gnetworkmonitornm.c -@@ -252,34 +252,12 @@ sync_properties (GNetworkMonitorNM *nm, - } - } - --static void --update_cached_property (GDBusProxy *proxy, -- const char *property_name, -- GVariantDict *dict) --{ -- GVariant *v; -- -- v = g_variant_dict_lookup_value (dict, property_name, NULL); -- if (!v) -- return; -- g_dbus_proxy_set_cached_property (proxy, property_name, v); -- g_variant_unref (v); --} -- - static void - proxy_properties_changed_cb (GDBusProxy *proxy, - GVariant *changed_properties, - GStrv invalidated_properties, - GNetworkMonitorNM *nm) - { -- GVariantDict *dict; -- -- dict = g_variant_dict_new (changed_properties); -- -- update_cached_property (nm->priv->proxy, "Connectivity", dict); -- -- g_variant_dict_unref (dict); -- - sync_properties (nm, TRUE); - } - --- -2.33.1 diff --git a/ghmac-gnutls.patch b/gnutls-hmac.patch similarity index 64% rename from ghmac-gnutls.patch rename to gnutls-hmac.patch index 8b5babb2d114513018b8544f0fe3b4356a01d6e1..4b1ba0e19bbe3ffc76ee22f3d173ee146c482080 100644 --- a/ghmac-gnutls.patch +++ b/gnutls-hmac.patch @@ -1,30 +1,17 @@ -From c5cc0bb6f2d6e468c7402915a0a4e6799f0febdf Mon Sep 17 00:00:00 2001 +From ff90bb8474b1e724727f4014b446e7c851e609bd Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 7 Jun 2019 18:44:43 +0000 -Subject: [PATCH 1/3] ghmac: Split off wrapper functions into ghmac-utils.c +Subject: [PATCH 1/4] ghmac: Split off wrapper functions into ghmac-utils.c Prep for adding a GnuTLS HMAC implementation; these are just utility functions that call the "core" API. --- - glib/Makefile.am | 1 + glib/ghmac-utils.c | 145 +++++++++++++++++++++++++++++++++++++++++++++ glib/ghmac.c | 112 ---------------------------------- glib/meson.build | 1 + - 4 files changed, 147 insertions(+), 112 deletions(-) + 3 files changed, 146 insertions(+), 112 deletions(-) create mode 100644 glib/ghmac-utils.c -diff --git a/glib/Makefile.am b/glib/Makefile.am -index c0c3b92f0..43fa17051 100644 ---- a/glib/Makefile.am -+++ b/glib/Makefile.am -@@ -126,6 +126,7 @@ libglib_2_0_la_SOURCES = \ - ggettext.c \ - ghash.c \ - ghmac.c \ -+ ghmac-utils.c \ - ghook.c \ - ghostutils.c \ - giochannel.c \ diff --git a/glib/ghmac-utils.c b/glib/ghmac-utils.c new file mode 100644 index 000000000..a17359ff1 @@ -177,7 +164,7 @@ index 000000000..a17359ff1 + (const guchar *) str, length); +} diff --git a/glib/ghmac.c b/glib/ghmac.c -index 9b58fd81c..7db38e34a 100644 +index 49fd272f0..4f181f21f 100644 --- a/glib/ghmac.c +++ b/glib/ghmac.c @@ -329,115 +329,3 @@ g_hmac_get_digest (GHmac *hmac, @@ -297,10 +284,10 @@ index 9b58fd81c..7db38e34a 100644 - (const guchar *) str, length); -} diff --git a/glib/meson.build b/glib/meson.build -index c81e99f9c..306a67f13 100644 +index 8c18e6de4..329b8d197 100644 --- a/glib/meson.build +++ b/glib/meson.build -@@ -138,6 +138,7 @@ glib_sources = files( +@@ -253,6 +253,7 @@ glib_sources = files( 'ggettext.c', 'ghash.c', 'ghmac.c', @@ -311,10 +298,10 @@ index c81e99f9c..306a67f13 100644 -- 2.31.1 -From 3befcf1eb31e0fa7a988b22a9c24240218cd4744 Mon Sep 17 00:00:00 2001 +From 5395d36e6685e0b7377794c59c5820970bb472ef Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 7 Jun 2019 19:36:54 +0000 -Subject: [PATCH 2/3] Add a gnutls backend for GHmac +Subject: [PATCH 2/4] Add a gnutls backend for GHmac For RHEL we want apps to use FIPS-certified crypto libraries, and HMAC apparently counts as "keyed" and hence needs to @@ -361,50 +348,19 @@ don't think this error should actually be hit in practice. https://gitlab.gnome.org/GNOME/glib/-/merge_requests/903 --- - glib/Makefile.am | 8 +- glib/gchecksum.c | 9 +- glib/gchecksumprivate.h | 32 +++++++ - glib/ghmac-gnutls.c | 182 ++++++++++++++++++++++++++++++++++++++++ - glib/ghmac.c | 13 +++ + glib/ghmac-gnutls.c | 187 ++++++++++++++++++++++++++++++++++++++++ + glib/ghmac.c | 15 ++++ glib/meson.build | 10 ++- meson.build | 7 ++ - meson_options.txt | 5 ++ - 8 files changed, 258 insertions(+), 8 deletions(-) + meson_options.txt | 7 +- + 7 files changed, 260 insertions(+), 7 deletions(-) create mode 100644 glib/gchecksumprivate.h create mode 100644 glib/ghmac-gnutls.c -diff --git a/glib/Makefile.am b/glib/Makefile.am -index 43fa17051..1175bbe40 100644 ---- a/glib/Makefile.am -+++ b/glib/Makefile.am -@@ -125,7 +125,7 @@ libglib_2_0_la_SOURCES = \ - gfileutils.c \ - ggettext.c \ - ghash.c \ -- ghmac.c \ -+ ghmac-gnutls.c \ - ghmac-utils.c \ - ghook.c \ - ghostutils.c \ -@@ -352,11 +352,15 @@ pcre_lib = pcre/libpcre.la - pcre_inc = - endif - --libglib_2_0_la_CFLAGS = $(AM_CFLAGS) $(GLIB_HIDDEN_VISIBILITY_CFLAGS) $(LIBSYSTEMD_CFLAGS) -+gnutls_libs = $(shell pkg-config --libs gnutls) -+gnutls_cflags = $(shell pkg-config --cflags gnutls) -+ -+libglib_2_0_la_CFLAGS = $(AM_CFLAGS) $(GLIB_HIDDEN_VISIBILITY_CFLAGS) $(LIBSYSTEMD_CFLAGS) $(gnutls_cflags) - libglib_2_0_la_LIBADD = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ @ICONV_LIBS@ @G_LIBS_EXTRA@ $(pcre_lib) $(G_THREAD_LIBS_EXTRA) $(G_THREAD_LIBS_FOR_GTHREAD) $(LIBSYSTEMD_LIBS) - libglib_2_0_la_DEPENDENCIES = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ $(glib_win32_res) $(glib_def) - - libglib_2_0_la_LDFLAGS = $(GLIB_LINK_FLAGS) \ -+ $(gnutls_libs) \ - $(glib_win32_res_ldflag) \ - -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ - -export-dynamic $(no_undefined) diff --git a/glib/gchecksum.c b/glib/gchecksum.c -index 40b1d50e2..2f59d4a66 100644 +index 29b479bc6..929958c3a 100644 --- a/glib/gchecksum.c +++ b/glib/gchecksum.c @@ -20,7 +20,7 @@ @@ -427,9 +383,9 @@ index 40b1d50e2..2f59d4a66 100644 +gchecksum_digest_to_string (guint8 *digest, + gsize digest_len) { - gint len = digest_len * 2; - gint i; -@@ -195,6 +195,7 @@ digest_to_string (guint8 *digest, + gsize i, len = digest_len * 2; + gchar *retval; +@@ -194,6 +194,7 @@ digest_to_string (guint8 *digest, return retval; } @@ -478,10 +434,10 @@ index 000000000..86c7a3b61 \ No newline at end of file diff --git a/glib/ghmac-gnutls.c b/glib/ghmac-gnutls.c new file mode 100644 -index 000000000..522b9b302 +index 000000000..9fb775f89 --- /dev/null +++ b/glib/ghmac-gnutls.c -@@ -0,0 +1,182 @@ +@@ -0,0 +1,187 @@ +/* ghmac.h - data hashing functions + * + * Copyright (C) 2011 Collabora Ltd. @@ -518,6 +474,10 @@ index 000000000..522b9b302 +#include "gtypes.h" +#include "glibintl.h" + ++#ifndef HAVE_GNUTLS ++#error "build configuration error" ++#endif ++ +struct _GHmac +{ + int ref_count; @@ -556,6 +516,7 @@ index 000000000..522b9b302 + algo = GNUTLS_MAC_SHA512; + break; + default: ++ g_free (hmac); + g_return_val_if_reached (NULL); + } + @@ -565,7 +526,7 @@ index 000000000..522b9b302 + /* There is no way to report an error here, but one possible cause of + * failure is that the requested digest may be disabled by FIPS mode. + */ -+ g_free (hmac->hmac); ++ g_free (hmac); + return NULL; + } + @@ -665,18 +626,20 @@ index 000000000..522b9b302 + *digest_len = g_checksum_type_get_length (hmac->digest_type); +} diff --git a/glib/ghmac.c b/glib/ghmac.c -index 7db38e34a..b03a5aea7 100644 +index 4f181f21f..0e39ea40a 100644 --- a/glib/ghmac.c +++ b/glib/ghmac.c -@@ -33,6 +33,7 @@ +@@ -33,6 +33,9 @@ #include "gtypes.h" #include "glibintl.h" ++#ifdef HAVE_GNUTLS +#error "build configuration error" ++#endif /** * SECTION:hmac -@@ -84,6 +85,18 @@ struct _GHmac +@@ -84,6 +87,18 @@ struct _GHmac * Support for digests of type %G_CHECKSUM_SHA512 has been added in GLib 2.42. * Support for %G_CHECKSUM_SHA384 was added in GLib 2.52. * @@ -696,18 +659,10 @@ index 7db38e34a..b03a5aea7 100644 * Use g_hmac_unref() to free the memory allocated by it. * diff --git a/glib/meson.build b/glib/meson.build -index 306a67f13..07d41456d 100644 +index 329b8d197..2417de53d 100644 --- a/glib/meson.build +++ b/glib/meson.build -@@ -127,6 +127,7 @@ glib_sources = files( - 'gbytes.c', - 'gcharset.c', - 'gchecksum.c', -+ 'gchecksumprivate.h', - 'gconvert.c', - 'gdataset.c', - 'gdate.c', -@@ -137,7 +138,6 @@ glib_sources = files( +@@ -252,7 +252,6 @@ glib_sources = files( 'gfileutils.c', 'ggettext.c', 'ghash.c', @@ -715,7 +670,15 @@ index 306a67f13..07d41456d 100644 'ghmac-utils.c', 'ghook.c', 'ghostutils.c', -@@ -223,6 +223,12 @@ else +@@ -308,6 +307,7 @@ glib_sources = files( + 'guriprivate.h', + 'gutils.c', + 'gutilsprivate.h', ++ 'gchecksumprivate.h', + 'guuid.c', + 'gvariant.c', + 'gvariant-core.c', +@@ -352,6 +352,12 @@ else glib_dtrace_hdr = [] endif @@ -728,21 +691,21 @@ index 306a67f13..07d41456d 100644 pcre_static_args = [] if use_pcre_static_flag -@@ -239,7 +245,7 @@ libglib = library('glib-2.0', - link_args : platform_ldflags + noseh_link_args, +@@ -378,7 +384,7 @@ libglib = library('glib-2.0', + # intl.lib is not compatible with SAFESEH + link_args : [noseh_link_args, glib_link_flags, win32_ldflags], include_directories : configinc, - link_with : [charset_lib, gnulib_lib], -- dependencies : [pcre, thread_dep, libintl, librt] + libiconv + platform_deps, -+ dependencies : [pcre, thread_dep, libintl, librt] + libgnutls_dep + libiconv + platform_deps, - c_args : ['-DG_LOG_DOMAIN="GLib"', '-DGLIB_COMPILATION'] + pcre_static_args + glib_hidden_visibility_args +- dependencies : pcre_deps + [thread_dep, librt] + libintl_deps + libiconv + platform_deps + [gnulib_libm_dependency, libm] + [libsysprof_capture_dep], ++ dependencies : pcre_deps + [thread_dep, librt] + libgnutls_dep + libintl_deps + libiconv + platform_deps + [gnulib_libm_dependency, libm] + [libsysprof_capture_dep], + c_args : glib_c_args, + objc_args : glib_c_args, ) - diff --git a/meson.build b/meson.build -index 0cefee51d..eaf8d3900 100644 +index e2eba1871..cca15f653 100644 --- a/meson.build +++ b/meson.build -@@ -1596,6 +1596,13 @@ if host_system == 'linux' and get_option('libmount') - libmount_dep = [dependency('mount', version : '>=2.23', required : true)] +@@ -2090,6 +2090,13 @@ if host_system == 'linux' + glib_conf.set('HAVE_LIBMOUNT', libmount_dep.found()) endif +# gnutls is used optionally by ghmac @@ -756,28 +719,243 @@ index 0cefee51d..eaf8d3900 100644 winsock2 = cc.find_library('ws2_32') endif diff --git a/meson_options.txt b/meson_options.txt -index 4504c6858..d18c42a36 100644 +index 072765361..c8f26ac02 100644 --- a/meson_options.txt +++ b/meson_options.txt -@@ -34,6 +34,11 @@ option('libmount', - value : true, - description : 'build with libmount support') +@@ -39,6 +39,11 @@ option('internal_pcre', + value : false, + description : 'whether to use internal PCRE') +option('gnutls', + type : 'boolean', + value : false, + description : 'build with gnutls support') + - option('internal_pcre', + option('man', type : 'boolean', value : false, -- 2.31.1 -From 87280b23902290dcf843a42d06cedeef571a673f Mon Sep 17 00:00:00 2001 +From 61c175277acb8d1e080305acd444201c5ad1fb81 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Wed, 16 Jun 2021 20:35:00 -0500 +Subject: [PATCH 3/4] dlopen GnuTLS instead of linking directly + +I'd like to enable our GnuTLS GHmac patchset in Fedora in order to +ensure it is receiving sufficient real-world testing, since we've +discovered several bugs thus far. Problem is Fedora has one requirement +that RHEL does not: it needs to build glib as a static lib. This is +needed by QEMU in Fedora for complicated technical reasons that I don't +understand. However, nothing in RHEL needs it. This means we failed to +notice that glib2-static is broken in RHEL, because there is no +gnutls-static! We could fix this by adding a gnutls-static package, but +that seems like overkill, and adding more static libraries where they're +not truly necessary is not the direction we want to move in anyway. So +instead, let's just dlopen GnuTLS to sidestep this problem entirely. + +This would not be a good solution for upstream, but upstream has made +clear that this patchset is already non-upstreamable, so it will be fine +for our purposes. +--- + glib/ghmac-gnutls.c | 101 ++++++++++++++++++++++++++++++++++++++++++-- + glib/ghmac.c | 2 +- + glib/meson.build | 2 +- + meson.build | 6 +-- + 4 files changed, 102 insertions(+), 9 deletions(-) + +diff --git a/glib/ghmac-gnutls.c b/glib/ghmac-gnutls.c +index 9fb775f89..1800fc2e0 100644 +--- a/glib/ghmac-gnutls.c ++++ b/glib/ghmac-gnutls.c +@@ -19,8 +19,8 @@ + + #include "config.h" + ++#include + #include +-#include + + #include "ghmac.h" + +@@ -31,13 +31,16 @@ + #include "gstrfuncs.h" + #include "gchecksumprivate.h" + #include "gtestutils.h" ++#include "gthread.h" + #include "gtypes.h" + #include "glibintl.h" + +-#ifndef HAVE_GNUTLS ++#ifndef USE_GNUTLS + #error "build configuration error" + #endif + ++typedef gpointer gnutls_hmac_hd_t; ++ + struct _GHmac + { + int ref_count; +@@ -46,15 +49,107 @@ struct _GHmac + gchar *digest_str; + }; + ++typedef enum ++{ ++ GNUTLS_MAC_MD5 = 2, ++ GNUTLS_MAC_SHA1 = 3, ++ GNUTLS_MAC_SHA256 = 6, ++ GNUTLS_MAC_SHA384 = 7, ++ GNUTLS_MAC_SHA512 = 8, ++} gnutls_mac_algorithm_t; ++ ++/* Why are we dlopening GnuTLS instead of linking to it directly? Because we ++ * want to be able to build GLib as a static library without depending on a ++ * static build of GnuTLS. QEMU depends on static linking with GLib, but Fedora ++ * does not ship a static build of GnuTLS, and this allows us to avoid changing ++ * that. ++ */ ++static int (*gnutls_hmac_init) (gnutls_hmac_hd_t *dig, gnutls_mac_algorithm_t algorithm, const void *key, size_t keylen); ++static gnutls_hmac_hd_t (*gnutls_hmac_copy) (gnutls_hmac_hd_t handle); ++static void (*gnutls_hmac_deinit) (gnutls_hmac_hd_t handle, void *digest); ++static int (*gnutls_hmac) (gnutls_hmac_hd_t handle, const void *ptext, size_t ptext_len); ++static void (*gnutls_hmac_output) (gnutls_hmac_hd_t handle, void *digest); ++static const char * (*gnutls_strerror) (int error); ++ ++static gsize gnutls_initialize_attempted = 0; ++static gboolean gnutls_initialize_successful = FALSE; ++ ++static void ++initialize_gnutls (void) ++{ ++ gpointer libgnutls; ++ ++ libgnutls = dlopen ("libgnutls.so.30", RTLD_LAZY | RTLD_GLOBAL); ++ if (!libgnutls) ++ { ++ g_warning ("Cannot use GHmac: failed to load libgnutls.so.30: %s", dlerror ()); ++ return; ++ } ++ ++ gnutls_hmac_init = dlsym (libgnutls, "gnutls_hmac_init"); ++ if (!gnutls_hmac_init) ++ { ++ g_warning ("Cannot use GHmac: failed to load gnutls_hmac_init: %s", dlerror ()); ++ return; ++ } ++ ++ gnutls_hmac_copy = dlsym (libgnutls, "gnutls_hmac_copy"); ++ if (!gnutls_hmac_copy) ++ { ++ g_warning ("Cannot use GHmac: failed to load gnutls_hmac_copy: %s", dlerror ()); ++ return; ++ } ++ ++ gnutls_hmac_deinit = dlsym (libgnutls, "gnutls_hmac_deinit"); ++ if (!gnutls_hmac_deinit) ++ { ++ g_warning ("Cannot use GHmac: failed to load gnutls_hmac_deinit: %s", dlerror ()); ++ return; ++ } ++ ++ gnutls_hmac = dlsym (libgnutls, "gnutls_hmac"); ++ if (!gnutls_hmac) ++ { ++ g_warning ("Cannot use GHmac: failed to load gnutls_hmac: %s", dlerror ()); ++ return; ++ } ++ ++ gnutls_hmac_output = dlsym (libgnutls, "gnutls_hmac_output"); ++ if (!gnutls_hmac_output) ++ { ++ g_warning ("Cannot use GHmac: failed to load gnutls_hmac_output: %s", dlerror ()); ++ return; ++ } ++ ++ gnutls_strerror = dlsym (libgnutls, "gnutls_strerror"); ++ if (!gnutls_strerror) ++ { ++ g_warning ("Cannot use GHmac: failed to load gnutls_strerror: %s", dlerror ()); ++ return; ++ } ++ ++ gnutls_initialize_successful = TRUE; ++} ++ + GHmac * + g_hmac_new (GChecksumType digest_type, + const guchar *key, + gsize key_len) + { + gnutls_mac_algorithm_t algo; +- GHmac *hmac = g_new0 (GHmac, 1); ++ GHmac *hmac; + int ret; + ++ if (g_once_init_enter (&gnutls_initialize_attempted)) ++ { ++ initialize_gnutls (); ++ g_once_init_leave (&gnutls_initialize_attempted, 1); ++ } ++ ++ if (!gnutls_initialize_successful) ++ return NULL; ++ ++ hmac = g_new0 (GHmac, 1); + hmac->ref_count = 1; + hmac->digest_type = digest_type; + +diff --git a/glib/ghmac.c b/glib/ghmac.c +index 0e39ea40a..2d9be91b8 100644 +--- a/glib/ghmac.c ++++ b/glib/ghmac.c +@@ -33,7 +33,7 @@ + #include "gtypes.h" + #include "glibintl.h" + +-#ifdef HAVE_GNUTLS ++#ifdef USE_GNUTLS + #error "build configuration error" + #endif + +diff --git a/glib/meson.build b/glib/meson.build +index 2417de53d..ba42951aa 100644 +--- a/glib/meson.build ++++ b/glib/meson.build +@@ -384,7 +384,7 @@ libglib = library('glib-2.0', + # intl.lib is not compatible with SAFESEH + link_args : [noseh_link_args, glib_link_flags, win32_ldflags], + include_directories : configinc, +- dependencies : pcre_deps + [thread_dep, librt] + libgnutls_dep + libintl_deps + libiconv + platform_deps + [gnulib_libm_dependency, libm] + [libsysprof_capture_dep], ++ dependencies : pcre_deps + [thread_dep, librt] + libintl_deps + libiconv + platform_deps + [gnulib_libm_dependency, libm] + [libsysprof_capture_dep] + [libdl_dep], + c_args : glib_c_args, + objc_args : glib_c_args, + ) +diff --git a/meson.build b/meson.build +index cca15f653..404ef1790 100644 +--- a/meson.build ++++ b/meson.build +@@ -2090,11 +2090,9 @@ if host_system == 'linux' + glib_conf.set('HAVE_LIBMOUNT', libmount_dep.found()) + endif + +-# gnutls is used optionally by ghmac +-libgnutls_dep = [] ++# gnutls is used optionally by GHmac + if get_option('gnutls') +- libgnutls_dep = [dependency('gnutls', version : '>=3.6.9', required : true)] +- glib_conf.set('HAVE_GNUTLS', 1) ++ glib_conf.set('USE_GNUTLS', 1) + endif + + if host_system == 'windows' +-- +2.31.1 + +From 7d1d96311b6ecd4f90ebbdd6fc58d28e06a86887 Mon Sep 17 00:00:00 2001 From: Michael Catanzaro -Date: Thu, 1 Jul 2021 15:51:26 -0500 -Subject: [PATCH 3/3] Add more tests for GHmac +Date: Wed, 16 Jun 2021 20:46:24 -0500 +Subject: [PATCH 4/4] Add test for GHmac in FIPS mode This will test a few problems that we hit recently: @@ -786,29 +964,73 @@ g_hmac_copy() is broken, https://bugzilla.redhat.com/show_bug.cgi?id=1786538 Crash in g_hmac_update() in FIPS mode, https://bugzilla.redhat.com/show_bug.cgi?id=1971533 Crash when passing -1 length to g_hmac_update() (discovered in #1971533) + +We'll also test to ensure MD5 fails, and stop compiling the other MD5 +tests. --- - glib/tests/hmac.c | 22 ++++++++++++++++++++++ - 1 file changed, 22 insertions(+) + glib/tests/hmac.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) diff --git a/glib/tests/hmac.c b/glib/tests/hmac.c -index 3ac3206df..16b2fac9c 100644 +index 3ac3206df..2fa447984 100644 --- a/glib/tests/hmac.c +++ b/glib/tests/hmac.c -@@ -493,6 +493,27 @@ test_hmac_for_bytes (void) +@@ -1,7 +1,10 @@ ++#include "config.h" ++ + #include + #include + #include + ++#ifndef USE_GNUTLS + /* HMAC-MD5 test vectors as per RFC 2202 */ + + /* Test 1 */ +@@ -81,6 +84,7 @@ guint8 key_md5_test7[] = { + guint8 result_md5_test7[] = { + 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, 0x1f, 0xb1, + 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e }; ++#endif + + /* HMAC-SHA1, HMAC-SHA256, HMAC-SHA384 and HMAC-SHA512 test vectors + * as per RFCs 2202 and 4868. +@@ -299,6 +303,7 @@ typedef struct { + gconstpointer result; + } HmacCase; + ++#ifndef USE_GNUTLS + HmacCase hmac_md5_tests[] = { + { G_CHECKSUM_MD5, key_md5_test1, 16, "Hi There", 8, result_md5_test1 }, + { G_CHECKSUM_MD5, "Jefe", 4, "what do ya want for nothing?", 28, +@@ -317,6 +322,7 @@ HmacCase hmac_md5_tests[] = { + 73, result_md5_test7 }, + { -1, NULL, 0, NULL, 0, NULL }, + }; ++#endif + + HmacCase hmac_sha1_tests[] = { + { G_CHECKSUM_SHA1, key_sha_test1, 20, "Hi There", 8, result_sha1_test1 }, +@@ -493,11 +499,45 @@ test_hmac_for_bytes (void) g_bytes_unref (data); } ++#ifdef USE_GNUTLS +static void -+test_ghmac_gnutls_regressions (void) ++test_gnutls_fips_mode (void) +{ + GHmac *hmac; + GHmac *copy; + -+ hmac = g_hmac_new (G_CHECKSUM_SHA256, (const guchar *)"abc123", sizeof ("abc123")); ++ /* No MD5 in FIPS mode. */ ++ hmac = g_hmac_new (G_CHECKSUM_MD5, "abc123", sizeof ("abc123")); ++ g_assert_null (hmac); ++ ++ /* SHA-256 should be good. */ ++ hmac = g_hmac_new (G_CHECKSUM_SHA256, "abc123", sizeof ("abc123")); + g_assert_nonnull (hmac); + + /* Ensure g_hmac_update() does not crash when called with -1. */ -+ g_hmac_update (hmac, (const guchar *)"You win again, gravity!", -1); ++ g_hmac_update (hmac, "You win again, gravity!", -1); + + /* Ensure g_hmac_copy() does not crash. */ + copy = g_hmac_copy (hmac); @@ -818,16 +1040,46 @@ index 3ac3206df..16b2fac9c 100644 + g_assert_cmpstr (g_hmac_get_string (copy), ==, "795ba6900bcb22e8ce65c2ec02db4e85697da921deb960ee3143bf88a4a60f83"); + g_hmac_unref (copy); +} ++#endif + int main (int argc, char **argv) -@@ -545,6 +566,7 @@ main (int argc, - g_test_add_func ("/hmac/for-data", test_hmac_for_data); + { + int i; ++ ++#ifdef USE_GNUTLS ++ /* This has to happen before GnuTLS is dlopened. */ ++ g_setenv ("GNUTLS_FORCE_FIPS_MODE", "1", FALSE); ++#endif ++ + g_test_init (&argc, &argv, NULL); + + for (i = 0 ; hmac_sha1_tests[i].key_len > 0 ; i++) +@@ -532,6 +572,7 @@ main (int argc, + g_free (name); + } + ++#ifndef USE_GNUTLS + for (i = 0 ; hmac_md5_tests[i].key_len > 0 ; i++) + { + gchar *name = g_strdup_printf ("/hmac/md5-%d", i + 1); +@@ -539,6 +580,7 @@ main (int argc, + (void (*)(const void *)) test_hmac); + g_free (name); + } ++#endif + + g_test_add_func ("/hmac/ref-unref", test_hmac_ref_unref); + g_test_add_func ("/hmac/copy", test_hmac_copy); +@@ -546,5 +588,9 @@ main (int argc, g_test_add_func ("/hmac/for-string", test_hmac_for_string); g_test_add_func ("/hmac/for-bytes", test_hmac_for_bytes); -+ g_test_add_func ("/hmac/ghmac-gnutls-regressions", test_ghmac_gnutls_regressions); ++#ifdef USE_GNUTLS ++ g_test_add_func ("/hmac/gnutls-fips-mode", test_gnutls_fips_mode); ++#endif ++ return g_test_run (); } -- diff --git a/gvariant-tests.patch b/gvariant-tests.patch deleted file mode 100644 index 5381817a2a6e1bb074a3a00c51a152c187c42609..0000000000000000000000000000000000000000 --- a/gvariant-tests.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 85c4031696add9797e2334ced20678edcd96c869 Mon Sep 17 00:00:00 2001 -From: Mart Raudsepp -Date: Wed, 19 Dec 2018 16:22:21 +0200 -Subject: [PATCH 1/2] tests: Allocate gvariant data from the heap to guarantee - alignment - -On glib-2-58 branch we don't have !455, thus we need aligned data -for the gvariant tests to not fail on i686. - -Fixes #1626 ---- - glib/tests/gvariant.c | 15 ++++++++++++--- - 1 file changed, 12 insertions(+), 3 deletions(-) - -diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c -index 6e417f6c1..a7b19826d 100644 ---- a/glib/tests/gvariant.c -+++ b/glib/tests/gvariant.c -@@ -4664,6 +4664,7 @@ test_stack_dict_init (void) - static void - test_normal_checking_tuples (void) - { -+ gpointer aligned_data; - const guint8 data[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 'a', '(', 'a', 'o', 'a', 'o', 'a', 'a', 'o', 'a', 'a', 'o', ')' -@@ -4672,13 +4673,15 @@ test_normal_checking_tuples (void) - GVariant *variant = NULL; - GVariant *normal_variant = NULL; - -- variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size, -+ aligned_data = g_memdup (data, size); /* guarantee alignment */ -+ variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, aligned_data, size, - FALSE, NULL, NULL); - g_assert_nonnull (variant); - - normal_variant = g_variant_get_normal_form (variant); - g_assert_nonnull (normal_variant); - -+ g_free (aligned_data); - g_variant_unref (normal_variant); - g_variant_unref (variant); - } -@@ -4790,6 +4793,7 @@ test_recursion_limits_array_in_variant (void) - static void - test_normal_checking_array_offsets (void) - { -+ gpointer aligned_data; - const guint8 data[] = { - 0x07, 0xe5, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, - 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'g', -@@ -4798,13 +4802,15 @@ test_normal_checking_array_offsets (void) - GVariant *variant = NULL; - GVariant *normal_variant = NULL; - -- variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size, -+ aligned_data = g_memdup (data, size); /* guarantee alignment */ -+ variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, aligned_data, size, - FALSE, NULL, NULL); - g_assert_nonnull (variant); - - normal_variant = g_variant_get_normal_form (variant); - g_assert_nonnull (normal_variant); - -+ g_free (aligned_data); - g_variant_unref (normal_variant); - g_variant_unref (variant); - } -@@ -4838,6 +4844,7 @@ test_normal_checking_tuple_offsets (void) - static void - test_normal_checking_empty_object_path (void) - { -+ gpointer aligned_data; - const guint8 data[] = { - 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, - '(', 'h', '(', 'a', 'i', 'a', 'b', 'i', 'o', ')', ')', -@@ -4846,13 +4853,15 @@ test_normal_checking_empty_object_path (void) - GVariant *variant = NULL; - GVariant *normal_variant = NULL; - -- variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size, -+ aligned_data = g_memdup (data, size); /* guarantee alignment */ -+ variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, aligned_data, size, - FALSE, NULL, NULL); - g_assert_nonnull (variant); - - normal_variant = g_variant_get_normal_form (variant); - g_assert_nonnull (normal_variant); - -+ g_free (aligned_data); - g_variant_unref (normal_variant); - g_variant_unref (variant); - } --- -2.19.1 - -From 4ef58e5661849317a1110c9b93957f2c608677dd Mon Sep 17 00:00:00 2001 -From: Simon McVittie -Date: Thu, 3 Jan 2019 08:21:40 +0000 -Subject: [PATCH 2/2] gvariant test: Also force alignment for tuple test data - -glib!552 (commit 9eed22b3) fixed this for the tests that failed on i686, -but this additional test failed on Debian's s390x port -(IBM z/Architecture, 64-bit big-endian). - -Signed-off-by: Simon McVittie ---- - glib/tests/gvariant.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c -index a7b19826d..c4a996c1f 100644 ---- a/glib/tests/gvariant.c -+++ b/glib/tests/gvariant.c -@@ -4820,6 +4820,7 @@ test_normal_checking_array_offsets (void) - static void - test_normal_checking_tuple_offsets (void) - { -+ gpointer aligned_data; - const guint8 data[] = { - 0x07, 0xe5, 0x00, 0x07, 0x00, 0x07, - '(', 'a', 's', 'a', 's', 'a', 's', 'a', 's', 'a', 's', 'a', 's', ')', -@@ -4828,13 +4829,15 @@ test_normal_checking_tuple_offsets (void) - GVariant *variant = NULL; - GVariant *normal_variant = NULL; - -- variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size, -- FALSE, NULL, NULL); -+ aligned_data = g_memdup (data, size); /* guarantee alignment */ -+ variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, aligned_data, -+ size, FALSE, NULL, NULL); - g_assert_nonnull (variant); - - normal_variant = g_variant_get_normal_form (variant); - g_assert_nonnull (normal_variant); - -+ g_free (aligned_data); - g_variant_unref (normal_variant); - g_variant_unref (variant); - } --- -2.19.1 diff --git a/keyfile-backend.patch b/keyfile-backend.patch deleted file mode 100644 index 31e6a0ed4ecbb7339203f98569afaafcfff3e1e7..0000000000000000000000000000000000000000 --- a/keyfile-backend.patch +++ /dev/null @@ -1,1021 +0,0 @@ -From 6edc7e0cfc672fe4c2331ac8131ea1aa82881b63 Mon Sep 17 00:00:00 2001 -From: Matthias Clasen -Date: Wed, 19 Dec 2018 19:58:16 -0500 -Subject: [PATCH 1/9] settings: Make the keyfile backend parameterless - -Make it possible to instantiate a keyfile settings backend -without specifying parameters, by turning the arguments to -the new() function into construct-only properties. If no -filename is specified, default to -$XDG_CONFIG_HOME/glib-2.0/settings/keyfile ---- - gio/gkeyfilesettingsbackend.c | 252 ++++++++++++++++++++++++++------- - gio/gsettingsbackendinternal.h | 2 + - 2 files changed, 199 insertions(+), 55 deletions(-) - -diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c -index a37978e83..e8e9f44a5 100644 ---- a/gio/gkeyfilesettingsbackend.c -+++ b/gio/gkeyfilesettingsbackend.c -@@ -21,6 +21,9 @@ - - #include "config.h" - -+#include -+#include -+ - #include - #include - -@@ -28,7 +31,8 @@ - #include "gfileinfo.h" - #include "gfilemonitor.h" - #include "gsimplepermission.h" --#include "gsettingsbackend.h" -+#include "gsettingsbackendinternal.h" -+#include "giomodule.h" - - - #define G_TYPE_KEYFILE_SETTINGS_BACKEND (g_keyfile_settings_backend_get_type ()) -@@ -41,6 +45,12 @@ - - typedef GSettingsBackendClass GKeyfileSettingsBackendClass; - -+enum { -+ PROP_FILENAME = 1, -+ PROP_ROOT_PATH, -+ PROP_ROOT_GROUP -+}; -+ - typedef struct - { - GSettingsBackend parent_instance; -@@ -61,7 +71,6 @@ typedef struct - GFileMonitor *dir_monitor; - } GKeyfileSettingsBackend; - --static GType g_keyfile_settings_backend_get_type (void); - G_DEFINE_TYPE (GKeyfileSettingsBackend, - g_keyfile_settings_backend, - G_TYPE_SETTINGS_BACKEND) -@@ -287,7 +296,8 @@ g_keyfile_settings_backend_check_one (gpointer key, - { - WriteManyData *data = user_data; - -- return data->failed = !path_is_valid (data->kfsb, key); -+ return data->failed = g_hash_table_contains (data->kfsb->system_locks, key) || -+ !path_is_valid (data->kfsb, key); - } - - static gboolean -@@ -522,25 +532,6 @@ g_keyfile_settings_backend_init (GKeyfileSettingsBackend *kfsb) - { - } - --static void --g_keyfile_settings_backend_class_init (GKeyfileSettingsBackendClass *class) --{ -- GObjectClass *object_class = G_OBJECT_CLASS (class); -- -- object_class->finalize = g_keyfile_settings_backend_finalize; -- -- class->read = g_keyfile_settings_backend_read; -- class->write = g_keyfile_settings_backend_write; -- class->write_tree = g_keyfile_settings_backend_write_tree; -- class->reset = g_keyfile_settings_backend_reset; -- class->get_writable = g_keyfile_settings_backend_get_writable; -- class->get_permission = g_keyfile_settings_backend_get_permission; -- /* No need to implement subscribed/unsubscribe: the only point would be to -- * stop monitoring the file when there's no GSettings anymore, which is no -- * big win. -- */ --} -- - static void - file_changed (GFileMonitor *monitor, - GFile *file, -@@ -567,6 +558,185 @@ dir_changed (GFileMonitor *monitor, - g_keyfile_settings_backend_keyfile_writable (kfsb); - } - -+static void -+g_keyfile_settings_backend_constructed (GObject *object) -+{ -+ GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object); -+ -+ if (kfsb->file == NULL) -+ { -+ char *filename = g_build_filename (g_get_user_config_dir (), -+ "glib-2.0", "settings", "keyfile", -+ NULL); -+ kfsb->file = g_file_new_for_path (filename); -+ g_free (filename); -+ } -+ -+ if (kfsb->prefix == NULL) -+ { -+ kfsb->prefix = g_strdup ("/"); -+ kfsb->prefix_len = 1; -+ } -+ -+ kfsb->keyfile = g_key_file_new (); -+ kfsb->permission = g_simple_permission_new (TRUE); -+ -+ kfsb->dir = g_file_get_parent (kfsb->file); -+ g_file_make_directory_with_parents (kfsb->dir, NULL, NULL); -+ -+ kfsb->file_monitor = g_file_monitor (kfsb->file, G_FILE_MONITOR_NONE, NULL, NULL); -+ kfsb->dir_monitor = g_file_monitor (kfsb->dir, G_FILE_MONITOR_NONE, NULL, NULL); -+ -+ compute_checksum (kfsb->digest, NULL, 0); -+ -+ g_signal_connect (kfsb->file_monitor, "changed", -+ G_CALLBACK (file_changed), kfsb); -+ g_signal_connect (kfsb->dir_monitor, "changed", -+ G_CALLBACK (dir_changed), kfsb); -+ -+ g_keyfile_settings_backend_keyfile_writable (kfsb); -+ g_keyfile_settings_backend_keyfile_reload (kfsb); -+} -+ -+static void -+g_keyfile_settings_backend_set_property (GObject *object, -+ guint prop_id, -+ const GValue *value, -+ GParamSpec *pspec) -+{ -+ GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object); -+ -+ switch (prop_id) -+ { -+ case PROP_FILENAME: -+ /* Construct only. */ -+ g_assert (kfsb->file == NULL); -+ kfsb->file = g_file_new_for_path (g_value_get_string (value)); -+ break; -+ -+ case PROP_ROOT_PATH: -+ /* Construct only. */ -+ g_assert (kfsb->prefix == NULL); -+ kfsb->prefix = g_value_dup_string (value); -+ if (kfsb->prefix) -+ kfsb->prefix_len = strlen (kfsb->prefix); -+ break; -+ -+ case PROP_ROOT_GROUP: -+ /* Construct only. */ -+ g_assert (kfsb->root_group == NULL); -+ kfsb->root_group = g_value_dup_string (value); -+ if (kfsb->root_group) -+ kfsb->root_group_len = strlen (kfsb->root_group); -+ break; -+ -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ break; -+ } -+} -+ -+static void -+g_keyfile_settings_backend_get_property (GObject *object, -+ guint prop_id, -+ GValue *value, -+ GParamSpec *pspec) -+{ -+ GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object); -+ -+ switch (prop_id) -+ { -+ case PROP_FILENAME: -+ g_value_set_string (value, g_file_peek_path (kfsb->file)); -+ break; -+ -+ case PROP_ROOT_PATH: -+ g_value_set_string (value, kfsb->prefix); -+ break; -+ -+ case PROP_ROOT_GROUP: -+ g_value_set_string (value, kfsb->root_group); -+ break; -+ -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ break; -+ } -+} -+ -+static void -+g_keyfile_settings_backend_class_init (GKeyfileSettingsBackendClass *class) -+{ -+ GObjectClass *object_class = G_OBJECT_CLASS (class); -+ -+ object_class->finalize = g_keyfile_settings_backend_finalize; -+ object_class->constructed = g_keyfile_settings_backend_constructed; -+ object_class->get_property = g_keyfile_settings_backend_get_property; -+ object_class->set_property = g_keyfile_settings_backend_set_property; -+ -+ class->read = g_keyfile_settings_backend_read; -+ class->write = g_keyfile_settings_backend_write; -+ class->write_tree = g_keyfile_settings_backend_write_tree; -+ class->reset = g_keyfile_settings_backend_reset; -+ class->get_writable = g_keyfile_settings_backend_get_writable; -+ class->get_permission = g_keyfile_settings_backend_get_permission; -+ /* No need to implement subscribed/unsubscribe: the only point would be to -+ * stop monitoring the file when there's no GSettings anymore, which is no -+ * big win. -+ */ -+ -+ /** -+ * GKeyfileSettingsBackend:filename: -+ * -+ * The location where the settings are stored on disk. -+ * -+ * Defaults to `$XDG_CONFIG_HOME/glib-2.0/settings/keyfile`. -+ */ -+ g_object_class_install_property (object_class, -+ PROP_FILENAME, -+ g_param_spec_string ("filename", -+ P_("Filename"), -+ P_("The filename"), -+ NULL, -+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | -+ G_PARAM_STATIC_STRINGS)); -+ -+ /** -+ * GKeyfileSettingsBackend:root-path: -+ * -+ * All settings read to or written from the backend must fall under the -+ * path given in @root_path (which must start and end with a slash and -+ * not contain two consecutive slashes). @root_path may be "/". -+ * -+ * Defaults to "/". -+ */ -+ g_object_class_install_property (object_class, -+ PROP_ROOT_PATH, -+ g_param_spec_string ("root-path", -+ P_("Root path"), -+ P_("The root path"), -+ NULL, -+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | -+ G_PARAM_STATIC_STRINGS)); -+ -+ /** -+ * GKeyfileSettingsBackend:root-group: -+ * -+ * If @root_group is non-%NULL then it specifies the name of the keyfile -+ * group used for keys that are written directly below the root path. -+ * -+ * Defaults to NULL. -+ */ -+ g_object_class_install_property (object_class, -+ PROP_ROOT_GROUP, -+ g_param_spec_string ("root-group", -+ P_("Root group"), -+ P_("The root group"), -+ NULL, -+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | -+ G_PARAM_STATIC_STRINGS)); -+} -+ - /** - * g_keyfile_settings_backend_new: - * @filename: the filename of the keyfile -@@ -626,43 +796,15 @@ g_keyfile_settings_backend_new (const gchar *filename, - const gchar *root_path, - const gchar *root_group) - { -- GKeyfileSettingsBackend *kfsb; -- - g_return_val_if_fail (filename != NULL, NULL); - g_return_val_if_fail (root_path != NULL, NULL); - g_return_val_if_fail (g_str_has_prefix (root_path, "/"), NULL); - g_return_val_if_fail (g_str_has_suffix (root_path, "/"), NULL); - g_return_val_if_fail (strstr (root_path, "//") == NULL, NULL); - -- kfsb = g_object_new (G_TYPE_KEYFILE_SETTINGS_BACKEND, NULL); -- kfsb->keyfile = g_key_file_new (); -- kfsb->permission = g_simple_permission_new (TRUE); -- -- kfsb->file = g_file_new_for_path (filename); -- kfsb->dir = g_file_get_parent (kfsb->file); -- g_file_make_directory_with_parents (kfsb->dir, NULL, NULL); -- -- kfsb->file_monitor = g_file_monitor (kfsb->file, 0, NULL, NULL); -- kfsb->dir_monitor = g_file_monitor (kfsb->dir, 0, NULL, NULL); -- -- kfsb->prefix_len = strlen (root_path); -- kfsb->prefix = g_strdup (root_path); -- -- if (root_group) -- { -- kfsb->root_group_len = strlen (root_group); -- kfsb->root_group = g_strdup (root_group); -- } -- -- compute_checksum (kfsb->digest, NULL, 0); -- -- g_signal_connect (kfsb->file_monitor, "changed", -- G_CALLBACK (file_changed), kfsb); -- g_signal_connect (kfsb->dir_monitor, "changed", -- G_CALLBACK (dir_changed), kfsb); -- -- g_keyfile_settings_backend_keyfile_writable (kfsb); -- g_keyfile_settings_backend_keyfile_reload (kfsb); -- -- return G_SETTINGS_BACKEND (kfsb); -+ return G_SETTINGS_BACKEND (g_object_new (G_TYPE_KEYFILE_SETTINGS_BACKEND, -+ "filename", filename, -+ "root-path", root_path, -+ "root-group", root_group, -+ NULL)); - } -diff --git a/gio/gsettingsbackendinternal.h b/gio/gsettingsbackendinternal.h -index 2a76a80bc..9e1d51dba 100644 ---- a/gio/gsettingsbackendinternal.h -+++ b/gio/gsettingsbackendinternal.h -@@ -87,6 +87,8 @@ GType g_null_settings_backend_get_type (void); - - GType g_memory_settings_backend_get_type (void); - -+GType g_keyfile_settings_backend_get_type (void); -+ - #ifdef HAVE_COCOA - GType g_nextstep_settings_backend_get_type (void); - #endif --- -2.28.0 - - -From cd448d51f610f1e6a701ac8a1146d3b2048427a0 Mon Sep 17 00:00:00 2001 -From: Matthias Clasen -Date: Wed, 19 Dec 2018 20:03:29 -0500 -Subject: [PATCH 2/9] settings: Register the keyfile backend as extension - -This was not done previously because the backend -could not be instantiated without parameters. ---- - gio/gkeyfilesettingsbackend.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - -diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c -index e8e9f44a5..0e9789cde 100644 ---- a/gio/gkeyfilesettingsbackend.c -+++ b/gio/gkeyfilesettingsbackend.c -@@ -32,7 +32,7 @@ - #include "gfilemonitor.h" - #include "gsimplepermission.h" - #include "gsettingsbackendinternal.h" --#include "giomodule.h" -+#include "giomodule-priv.h" - - - #define G_TYPE_KEYFILE_SETTINGS_BACKEND (g_keyfile_settings_backend_get_type ()) -@@ -71,9 +71,12 @@ typedef struct - GFileMonitor *dir_monitor; - } GKeyfileSettingsBackend; - --G_DEFINE_TYPE (GKeyfileSettingsBackend, -- g_keyfile_settings_backend, -- G_TYPE_SETTINGS_BACKEND) -+G_DEFINE_TYPE_WITH_CODE (GKeyfileSettingsBackend, -+ g_keyfile_settings_backend, -+ G_TYPE_SETTINGS_BACKEND, -+ _g_io_modules_ensure_extension_points_registered (); -+ g_io_extension_point_implement (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME, -+ g_define_type_id, "keyfile", 10)) - - static void - compute_checksum (guint8 *digest, --- -2.28.0 - - -From 8cbdb7dd496f6c2361eb46ca4c0848d7210fe27a Mon Sep 17 00:00:00 2001 -From: Matthias Clasen -Date: Mon, 5 Nov 2018 16:07:55 -0500 -Subject: [PATCH 3/9] settings: Add support for defaults to keyfile backend - -Stacked databases and locks are dconf features that allow -management software like Fleet Commander to set system-wide -defaults and overrides centrally for applications. - -This patch adds minimal support for the same to the keyfile -backend. We look for a keyfile named 'defaults' and a -lock-list named 'locks'. - -Suitable files can be produced from a dconf database with -dconf dump and dconf list-locks, respectively. - -The default location for these files is /etc/glib-2.0/settings/. -For test purposes, this can be overwritten with the -GSETTINGS_DEFAULTS_DIR environment variable. - -Writes always go to the per-user keyfile. ---- - gio/gkeyfilesettingsbackend.c | 138 ++++++++++++++++++++++++++++++++-- - 1 file changed, 132 insertions(+), 6 deletions(-) - -diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c -index 0e9789cde..0a4e81511 100644 ---- a/gio/gkeyfilesettingsbackend.c -+++ b/gio/gkeyfilesettingsbackend.c -@@ -29,6 +29,7 @@ - - #include "gfile.h" - #include "gfileinfo.h" -+#include "gfileenumerator.h" - #include "gfilemonitor.h" - #include "gsimplepermission.h" - #include "gsettingsbackendinternal.h" -@@ -45,11 +46,12 @@ - - typedef GSettingsBackendClass GKeyfileSettingsBackendClass; - --enum { -+typedef enum { - PROP_FILENAME = 1, - PROP_ROOT_PATH, -- PROP_ROOT_GROUP --}; -+ PROP_ROOT_GROUP, -+ PROP_DEFAULTS_DIR -+} GKeyfileSettingsBackendProperty; - - typedef struct - { -@@ -58,6 +60,9 @@ typedef struct - GKeyFile *keyfile; - GPermission *permission; - gboolean writable; -+ char *defaults_dir; -+ GKeyFile *system_keyfile; -+ GHashTable *system_locks; /* Used as a set, owning the strings it contains */ - - gchar *prefix; - gint prefix_len; -@@ -196,10 +201,19 @@ get_from_keyfile (GKeyfileSettingsBackend *kfsb, - if (convert_path (kfsb, key, &group, &name)) - { - gchar *str; -+ gchar *sysstr; - - g_assert (*name); - -+ sysstr = g_key_file_get_value (kfsb->system_keyfile, group, name, NULL); - str = g_key_file_get_value (kfsb->keyfile, group, name, NULL); -+ if (sysstr && -+ (g_hash_table_contains (kfsb->system_locks, key) || -+ str == NULL)) -+ { -+ g_free (str); -+ str = g_steal_pointer (&sysstr); -+ } - - if (str) - { -@@ -207,6 +221,8 @@ get_from_keyfile (GKeyfileSettingsBackend *kfsb, - g_free (str); - } - -+ g_free (sysstr); -+ - g_free (group); - g_free (name); - } -@@ -221,6 +237,9 @@ set_to_keyfile (GKeyfileSettingsBackend *kfsb, - { - gchar *group, *name; - -+ if (g_hash_table_contains (kfsb->system_locks, key)) -+ return FALSE; -+ - if (convert_path (kfsb, key, &group, &name)) - { - if (value) -@@ -368,7 +387,9 @@ g_keyfile_settings_backend_get_writable (GSettingsBackend *backend, - { - GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (backend); - -- return kfsb->writable && path_is_valid (kfsb, name); -+ return kfsb->writable && -+ !g_hash_table_contains (kfsb->system_locks, name) && -+ path_is_valid (kfsb, name); - } - - static GPermission * -@@ -514,6 +535,9 @@ g_keyfile_settings_backend_finalize (GObject *object) - - g_key_file_free (kfsb->keyfile); - g_object_unref (kfsb->permission); -+ g_key_file_unref (kfsb->system_keyfile); -+ g_hash_table_unref (kfsb->system_locks); -+ g_free (kfsb->defaults_dir); - - g_file_monitor_cancel (kfsb->file_monitor); - g_object_unref (kfsb->file_monitor); -@@ -561,6 +585,75 @@ dir_changed (GFileMonitor *monitor, - g_keyfile_settings_backend_keyfile_writable (kfsb); - } - -+static void -+load_system_settings (GKeyfileSettingsBackend *kfsb) -+{ -+ GError *error = NULL; -+ const char *dir = "/etc/glib-2.0/settings"; -+ char *path; -+ char *contents; -+ -+ kfsb->system_keyfile = g_key_file_new (); -+ kfsb->system_locks = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); -+ -+ if (kfsb->defaults_dir) -+ dir = kfsb->defaults_dir; -+ -+ path = g_build_filename (dir, "defaults", NULL); -+ -+ /* The defaults are in the same keyfile format that we use for the settings. -+ * It can be produced from a dconf database using: dconf dump -+ */ -+ if (!g_key_file_load_from_file (kfsb->system_keyfile, path, G_KEY_FILE_NONE, &error)) -+ { -+ if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) -+ g_warning ("Failed to read %s: %s", path, error->message); -+ g_clear_error (&error); -+ } -+ else -+ g_debug ("Loading default settings from %s", path); -+ -+ g_free (path); -+ -+ path = g_build_filename (dir, "locks", NULL); -+ -+ /* The locks file is a text file containing a list paths to lock, one per line. -+ * It can be produced from a dconf database using: dconf list-locks -+ */ -+ if (!g_file_get_contents (path, &contents, NULL, &error)) -+ { -+ if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) -+ g_warning ("Failed to read %s: %s", path, error->message); -+ g_clear_error (&error); -+ } -+ else -+ { -+ char **lines; -+ gsize i; -+ -+ g_debug ("Loading locks from %s", path); -+ -+ lines = g_strsplit (contents, "\n", 0); -+ for (i = 0; lines[i]; i++) -+ { -+ char *line = lines[i]; -+ if (line[0] == '#' || line[0] == '\0') -+ { -+ g_free (line); -+ continue; -+ } -+ -+ g_debug ("Locking key %s", line); -+ g_hash_table_add (kfsb->system_locks, g_steal_pointer (&line)); -+ } -+ -+ g_free (lines); -+ } -+ g_free (contents); -+ -+ g_free (path); -+} -+ - static void - g_keyfile_settings_backend_constructed (GObject *object) - { -@@ -599,6 +692,8 @@ g_keyfile_settings_backend_constructed (GObject *object) - - g_keyfile_settings_backend_keyfile_writable (kfsb); - g_keyfile_settings_backend_keyfile_reload (kfsb); -+ -+ load_system_settings (kfsb); - } - - static void -@@ -609,7 +704,7 @@ g_keyfile_settings_backend_set_property (GObject *object, - { - GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object); - -- switch (prop_id) -+ switch ((GKeyfileSettingsBackendProperty)prop_id) - { - case PROP_FILENAME: - /* Construct only. */ -@@ -633,6 +728,12 @@ g_keyfile_settings_backend_set_property (GObject *object, - kfsb->root_group_len = strlen (kfsb->root_group); - break; - -+ case PROP_DEFAULTS_DIR: -+ /* Construct only. */ -+ g_assert (kfsb->defaults_dir == NULL); -+ kfsb->defaults_dir = g_value_dup_string (value); -+ break; -+ - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; -@@ -647,7 +748,7 @@ g_keyfile_settings_backend_get_property (GObject *object, - { - GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object); - -- switch (prop_id) -+ switch ((GKeyfileSettingsBackendProperty)prop_id) - { - case PROP_FILENAME: - g_value_set_string (value, g_file_peek_path (kfsb->file)); -@@ -661,6 +762,10 @@ g_keyfile_settings_backend_get_property (GObject *object, - g_value_set_string (value, kfsb->root_group); - break; - -+ case PROP_DEFAULTS_DIR: -+ g_value_set_string (value, kfsb->defaults_dir); -+ break; -+ - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; -@@ -738,6 +843,22 @@ g_keyfile_settings_backend_class_init (GKeyfileSettingsBackendClass *class) - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); -+ -+ /** -+ * GKeyfileSettingsBackend:default-dir: -+ * -+ * The directory where the system defaults and locks are located. -+ * -+ * Defaults to `/etc/glib-2.0/settings`. -+ */ -+ g_object_class_install_property (object_class, -+ PROP_DEFAULTS_DIR, -+ g_param_spec_string ("defaults-dir", -+ P_("Default dir"), -+ P_("Defaults dir"), -+ NULL, -+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | -+ G_PARAM_STATIC_STRINGS)); - } - - /** -@@ -792,6 +913,11 @@ g_keyfile_settings_backend_class_init (GKeyfileSettingsBackendClass *class) - * characters in your path names or '=' in your key names you may be in - * trouble. - * -+ * The backend reads default values from a keyfile called `defaults` in -+ * the directory specified by the #GKeyfileSettingsBackend:defaults-dir property, -+ * and a list of locked keys from a text file with the name `locks` in -+ * the same location. -+ * - * Returns: (transfer full): a keyfile-backed #GSettingsBackend - **/ - GSettingsBackend * --- -2.28.0 - - -From 93dceb39fe2de23aeffe40ff02c824393c749270 Mon Sep 17 00:00:00 2001 -From: Matthias Clasen -Date: Fri, 2 Nov 2018 23:00:49 -0400 -Subject: [PATCH 4/9] settings: Prefer the keyfile backend when sandboxed - -When we are in a sandboxed situation, bump the priority -of the keyfile settings backend above the dconf one, -so we use a keyfile inside the sandbox instead of requiring -holes in the sandbox for dconf. ---- - gio/gkeyfilesettingsbackend.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c -index 0a4e81511..398cb053a 100644 ---- a/gio/gkeyfilesettingsbackend.c -+++ b/gio/gkeyfilesettingsbackend.c -@@ -34,6 +34,7 @@ - #include "gsimplepermission.h" - #include "gsettingsbackendinternal.h" - #include "giomodule-priv.h" -+#include "gportalsupport.h" - - - #define G_TYPE_KEYFILE_SETTINGS_BACKEND (g_keyfile_settings_backend_get_type ()) -@@ -76,12 +77,18 @@ typedef struct - GFileMonitor *dir_monitor; - } GKeyfileSettingsBackend; - -+#ifdef G_OS_WIN32 -+#define EXTENSION_PRIORITY 10 -+#else -+#define EXTENSION_PRIORITY (glib_should_use_portal () ? 110 : 10) -+#endif -+ - G_DEFINE_TYPE_WITH_CODE (GKeyfileSettingsBackend, - g_keyfile_settings_backend, - G_TYPE_SETTINGS_BACKEND, - _g_io_modules_ensure_extension_points_registered (); - g_io_extension_point_implement (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME, -- g_define_type_id, "keyfile", 10)) -+ g_define_type_id, "keyfile", EXTENSION_PRIORITY)) - - static void - compute_checksum (guint8 *digest, --- -2.28.0 - - -From 5d0d49750564aa7fd9e7d0d58c08a08847570921 Mon Sep 17 00:00:00 2001 -From: Matthias Clasen -Date: Mon, 21 Jan 2019 22:55:45 -0500 -Subject: [PATCH 5/9] keyfile settings: Accept unquoted strings - -It is hard for users to remember that strings have to be explicitly -quoted in the keyfile. Be lenient and accept strings that lack those -quotes. ---- - gio/gkeyfilesettingsbackend.c | 19 +++++++++++++++++++ - gio/tests/gsettings.c | 17 +++++++++++++++++ - 2 files changed, 36 insertions(+) - -diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c -index 398cb053a..d5796b706 100644 ---- a/gio/gkeyfilesettingsbackend.c -+++ b/gio/gkeyfilesettingsbackend.c -@@ -225,6 +225,25 @@ get_from_keyfile (GKeyfileSettingsBackend *kfsb, - if (str) - { - return_value = g_variant_parse (type, str, NULL, NULL, NULL); -+ if (return_value == NULL && -+ g_variant_type_equal (type, G_VARIANT_TYPE_STRING) && -+ str[0] != '\"') -+ { -+ GString *s = g_string_sized_new (strlen (str) + 2); -+ char *p = str; -+ -+ g_string_append_c (s, '\"'); -+ while (*p) -+ { -+ if (*p == '\"') -+ g_string_append_c (s, '\\'); -+ g_string_append_c (s, *p); -+ p++; -+ } -+ g_string_append_c (s, '\"'); -+ return_value = g_variant_parse (type, s->str, NULL, NULL, NULL); -+ g_string_free (s, TRUE); -+ } - g_free (str); - } - -diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c -index 2be4122fe..6eb49f124 100644 ---- a/gio/tests/gsettings.c -+++ b/gio/tests/gsettings.c -@@ -1716,6 +1716,23 @@ test_keyfile (void) - g_assert_cmpstr (str, ==, "howdy"); - g_free (str); - -+ /* Now check setting a string without quotes */ -+ called = FALSE; -+ g_signal_connect (settings, "changed::greeting", G_CALLBACK (key_changed_cb), &called); -+ -+ g_key_file_set_string (keyfile, "tests", "greeting", "he\"l🤗uń"); -+ g_free (data); -+ data = g_key_file_to_data (keyfile, &len, NULL); -+ g_file_set_contents ("keyfile/gsettings.store", data, len, &error); -+ g_assert_no_error (error); -+ while (!called) -+ g_main_context_iteration (NULL, FALSE); -+ g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called); -+ -+ str = g_settings_get_string (settings, "greeting"); -+ g_assert_cmpstr (str, ==, "he\"l🤗uń"); -+ g_free (str); -+ - g_settings_set (settings, "farewell", "s", "cheerio"); - - called = FALSE; --- -2.28.0 - - -From 3765e73f9a2dbbc6863bcffdee85ffb18530c89b Mon Sep 17 00:00:00 2001 -From: Philip Withnall -Date: Wed, 23 Jan 2019 15:14:58 +0000 -Subject: [PATCH 6/9] gkeyfilesettingsbackend: Add a code comment to clarify - things - -Signed-off-by: Philip Withnall ---- - gio/gkeyfilesettingsbackend.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c -index d5796b706..5ea632305 100644 ---- a/gio/gkeyfilesettingsbackend.c -+++ b/gio/gkeyfilesettingsbackend.c -@@ -225,6 +225,10 @@ get_from_keyfile (GKeyfileSettingsBackend *kfsb, - if (str) - { - return_value = g_variant_parse (type, str, NULL, NULL, NULL); -+ -+ /* As a special case, support values of type %G_VARIANT_TYPE_STRING -+ * not being quoted, since users keep forgetting to do it and then -+ * getting confused. */ - if (return_value == NULL && - g_variant_type_equal (type, G_VARIANT_TYPE_STRING) && - str[0] != '\"') --- -2.28.0 - - -From 1df628861afe027e8dce5e27f4249059bad6bc60 Mon Sep 17 00:00:00 2001 -From: Matthias Clasen -Date: Wed, 10 Jul 2019 11:14:03 -0400 -Subject: [PATCH 7/9] key file: Handle filename being NULL - -This happens when we are default-constructed -without explicit arguments. - -Closes: https://gitlab.gnome.org/GNOME/glib/issues/1825 ---- - gio/gkeyfilesettingsbackend.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c -index 5ea632305..a874af287 100644 ---- a/gio/gkeyfilesettingsbackend.c -+++ b/gio/gkeyfilesettingsbackend.c -@@ -739,7 +739,8 @@ g_keyfile_settings_backend_set_property (GObject *object, - case PROP_FILENAME: - /* Construct only. */ - g_assert (kfsb->file == NULL); -- kfsb->file = g_file_new_for_path (g_value_get_string (value)); -+ if (g_value_get_string (value)) -+ kfsb->file = g_file_new_for_path (g_value_get_string (value)); - break; - - case PROP_ROOT_PATH: --- -2.28.0 - - -From 9c5d3a6081e5ff419db96d9651bddbfcdb8b1bc6 Mon Sep 17 00:00:00 2001 -From: Matthias Clasen -Date: Fri, 12 Jul 2019 11:30:30 -0400 -Subject: [PATCH] portal: Add a getter for dconf access - -Add method to find whether the sandbox provides -access to dconf. This will be used to tweak -the priorities for the keyfile settings backend. ---- - gio/gportalsupport.c | 18 ++++++++++++++++++ - gio/gportalsupport.h | 1 + - 2 files changed, 19 insertions(+) - -diff --git a/gio/gportalsupport.c b/gio/gportalsupport.c -index 2f1e82517..b0a94b360 100644 ---- a/gio/gportalsupport.c -+++ b/gio/gportalsupport.c -@@ -23,6 +23,7 @@ - static gboolean flatpak_info_read; - static gboolean use_portal; - static gboolean network_available; -+static gboolean dconf_access; - - static void - read_flatpak_info (void) -@@ -40,11 +41,13 @@ read_flatpak_info (void) - - use_portal = TRUE; - network_available = FALSE; -+ dconf_access = FALSE; - - keyfile = g_key_file_new (); - if (g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL)) - { - char **shared = NULL; -+ char *dconf_policy = NULL; - - shared = g_key_file_get_string_list (keyfile, "Context", "shared", NULL, NULL); - if (shared) -@@ -52,6 +55,14 @@ read_flatpak_info (void) - network_available = g_strv_contains ((const char * const *)shared, "network"); - g_strfreev (shared); - } -+ -+ dconf_policy = g_key_file_get_string (keyfile, "Session Bus Policy", "ca.desrt.dconf", NULL); -+ if (dconf_policy) -+ { -+ if (strcmp (dconf_policy, "talk") == 0) -+ dconf_access = TRUE; -+ g_free (dconf_policy); -+ } - } - - g_key_file_unref (keyfile); -@@ -64,6 +75,7 @@ read_flatpak_info (void) - if (var && var[0] == '1') - use_portal = TRUE; - network_available = TRUE; -+ dconf_access = TRUE; - } - } - -@@ -81,3 +93,9 @@ glib_network_available_in_sandbox (void) - return network_available; - } - -+gboolean -+glib_has_dconf_access_in_sandbox (void) -+{ -+ read_flatpak_info (); -+ return dconf_access; -+} -diff --git a/gio/gportalsupport.h b/gio/gportalsupport.h -index a331f45d3..746f1fd6b 100644 ---- a/gio/gportalsupport.h -+++ b/gio/gportalsupport.h -@@ -24,6 +24,7 @@ G_BEGIN_DECLS - - gboolean glib_should_use_portal (void); - gboolean glib_network_available_in_sandbox (void); -+gboolean glib_has_dconf_access_in_sandbox (void); - - G_END_DECLS - --- -GitLab - - -From e6461f208931e27b52d82f7d3b5a7ce4fc26c9d7 Mon Sep 17 00:00:00 2001 -From: Matthias Clasen -Date: Fri, 12 Jul 2019 11:31:37 -0400 -Subject: [PATCH 8/9] settings: Tweak priorities for keyfile backend - -We want to use the keyfile backend in sandboxes, -but we want to avoid people losing their existing -settings that are stored in dconf. Flatpak does -a migration from dconf to keyfile, but only if -the app explictly requests it. - -From an app perspective, there are two steps to -the dconf->keyfile migration: -1. Request that flatpak do the migration, by adding - the migrate-path key to the metadata -2. Stop adding the 'dconf hole' to the sandbox - -To keep us from switching to the keyfile backend -prematurely, look at whether the app has stopped -requesting a 'dconf hole' in the sandbox. ---- - gio/gkeyfilesettingsbackend.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c -index a874af287..f5358818e 100644 ---- a/gio/gkeyfilesettingsbackend.c -+++ b/gio/gkeyfilesettingsbackend.c -@@ -80,7 +80,7 @@ typedef struct - #ifdef G_OS_WIN32 - #define EXTENSION_PRIORITY 10 - #else --#define EXTENSION_PRIORITY (glib_should_use_portal () ? 110 : 10) -+#define EXTENSION_PRIORITY (glib_should_use_portal () && !glib_has_dconf_access_in_sandbox () ? 110 : 10) - #endif - - G_DEFINE_TYPE_WITH_CODE (GKeyfileSettingsBackend, --- -2.28.0 - - -From 5f8d787815dc220fa2e288e03cd0cb9497727753 Mon Sep 17 00:00:00 2001 -From: Matthias Clasen -Date: Mon, 8 Jul 2019 10:31:51 -0400 -Subject: [PATCH] Ensure that the keyfile settings backend exists - -We need to bring the type into existence. - -Closes: https://gitlab.gnome.org/GNOME/glib/issues/1822 ---- - gio/giomodule.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/gio/giomodule.c b/gio/giomodule.c -index 9bb28985a..1007abdbf 100644 ---- a/gio/giomodule.c -+++ b/gio/giomodule.c -@@ -1211,6 +1211,7 @@ _g_io_modules_ensure_loaded (void) - /* Initialize types from built-in "modules" */ - g_type_ensure (g_null_settings_backend_get_type ()); - g_type_ensure (g_memory_settings_backend_get_type ()); -+ g_type_ensure (g_keyfile_settings_backend_get_type ()); - #if defined(HAVE_INOTIFY_INIT1) - g_type_ensure (g_inotify_file_monitor_get_type ()); - #endif --- -GitLab