Compare commits
No commits in common. "imports/c8s/glib2-2.56.4-157.el8" and "c8" have entirely different histories.
imports/c8
...
c8
139
SOURCES/1134.patch
Normal file
139
SOURCES/1134.patch
Normal file
@ -0,0 +1,139 @@
|
||||
From 08f5ab3c3a1877e4a8965a9075bd7675f64eae53 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <withnall@endlessm.com>
|
||||
Date: Fri, 27 Sep 2019 14:46:18 +0100
|
||||
Subject: [PATCH 1/2] gfile: Factor out flags when copying files
|
||||
|
||||
This introduces no functional changes; just reduces duplication in the
|
||||
code a little.
|
||||
|
||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
||||
---
|
||||
gio/gfile.c | 15 +++++++++------
|
||||
1 file changed, 9 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/gio/gfile.c b/gio/gfile.c
|
||||
index 29ebaaa62..a617b4cc8 100644
|
||||
--- a/gio/gfile.c
|
||||
+++ b/gio/gfile.c
|
||||
@@ -3184,6 +3184,7 @@ file_copy_fallback (GFile *source,
|
||||
const char *target;
|
||||
char *attrs_to_read;
|
||||
gboolean do_set_attributes = FALSE;
|
||||
+ GFileCreateFlags create_flags;
|
||||
|
||||
/* need to know the file type */
|
||||
info = g_file_query_info (source,
|
||||
@@ -3274,18 +3275,21 @@ file_copy_fallback (GFile *source,
|
||||
* If a future API like g_file_replace_with_info() is added, switch
|
||||
* this code to use that.
|
||||
*/
|
||||
+ create_flags = G_FILE_CREATE_PRIVATE;
|
||||
+ if (flags & G_FILE_COPY_OVERWRITE)
|
||||
+ create_flags |= G_FILE_CREATE_REPLACE_DESTINATION;
|
||||
+
|
||||
if (G_IS_LOCAL_FILE (destination))
|
||||
{
|
||||
if (flags & G_FILE_COPY_OVERWRITE)
|
||||
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 |
|
||||
- G_FILE_CREATE_PRIVATE, info,
|
||||
+ create_flags, info,
|
||||
cancellable, error);
|
||||
else
|
||||
out = (GOutputStream*)_g_local_file_output_stream_create (_g_local_file_get_filename (G_LOCAL_FILE (destination)),
|
||||
- FALSE, G_FILE_CREATE_PRIVATE, info,
|
||||
+ FALSE, create_flags, info,
|
||||
cancellable, error);
|
||||
}
|
||||
else if (flags & G_FILE_COPY_OVERWRITE)
|
||||
@@ -3293,13 +3297,12 @@ 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_PRIVATE,
|
||||
+ create_flags,
|
||||
cancellable, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
- out = (GOutputStream *)g_file_create (destination, G_FILE_CREATE_PRIVATE, cancellable, error);
|
||||
+ out = (GOutputStream *)g_file_create (destination, create_flags, cancellable, error);
|
||||
}
|
||||
|
||||
if (!out)
|
||||
--
|
||||
2.37.3
|
||||
|
||||
From b37d628c01da0bd61348b3ac73b7a436af008d8d Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <withnall@endlessm.com>
|
||||
Date: Fri, 27 Sep 2019 15:02:32 +0100
|
||||
Subject: [PATCH 2/2] =?UTF-8?q?gfile:=20Don=E2=80=99t=20copy=20files=20as?=
|
||||
=?UTF-8?q?=20private=20if=20using=20default=20permissions?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
If a copy operation is started with `G_FILE_COPY_TARGET_DEFAULT_PERMS`,
|
||||
don’t create the destination file as private. Instead, create it with
|
||||
the process’ current umask (i.e. ‘default permissions’).
|
||||
|
||||
This is a partial re-work of commit d8f8f4d637ce43f8699ba94c9b, with
|
||||
input from Ondrej Holy.
|
||||
|
||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
||||
|
||||
Fixes: #174
|
||||
---
|
||||
gio/gfile.c | 22 +++++++++++++++++++---
|
||||
1 file changed, 19 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gio/gfile.c b/gio/gfile.c
|
||||
index a617b4cc8..447da3cfb 100644
|
||||
--- a/gio/gfile.c
|
||||
+++ b/gio/gfile.c
|
||||
@@ -3274,8 +3274,22 @@ file_copy_fallback (GFile *source,
|
||||
*
|
||||
* If a future API like g_file_replace_with_info() is added, switch
|
||||
* this code to use that.
|
||||
+ *
|
||||
+ * Use %G_FILE_CREATE_PRIVATE unless
|
||||
+ * - we were told to create the file with default permissions (i.e. the
|
||||
+ * process’ umask),
|
||||
+ * - or if the source file is on a file system which doesn’t support
|
||||
+ * `unix::mode` (in which case it probably also makes sense to create the
|
||||
+ * destination with default permissions because the source cannot be
|
||||
+ * private),
|
||||
+ * - or if the destination file is a `GLocalFile`, in which case we can
|
||||
+ * directly open() it with the permissions from the source file.
|
||||
*/
|
||||
- create_flags = G_FILE_CREATE_PRIVATE;
|
||||
+ create_flags = G_FILE_CREATE_NONE;
|
||||
+ if (!(flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) &&
|
||||
+ g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE) &&
|
||||
+ !G_IS_LOCAL_FILE (destination))
|
||||
+ create_flags |= G_FILE_CREATE_PRIVATE;
|
||||
if (flags & G_FILE_COPY_OVERWRITE)
|
||||
create_flags |= G_FILE_CREATE_REPLACE_DESTINATION;
|
||||
|
||||
@@ -3285,11 +3299,13 @@ 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,
|
||||
- create_flags, info,
|
||||
+ create_flags,
|
||||
+ (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) ? NULL : info,
|
||||
cancellable, error);
|
||||
else
|
||||
out = (GOutputStream*)_g_local_file_output_stream_create (_g_local_file_get_filename (G_LOCAL_FILE (destination)),
|
||||
- FALSE, create_flags, info,
|
||||
+ FALSE, create_flags,
|
||||
+ (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) ? NULL : info,
|
||||
cancellable, error);
|
||||
}
|
||||
else if (flags & G_FILE_COPY_OVERWRITE)
|
||||
--
|
||||
2.37.3
|
||||
|
654
SOURCES/13.patch
Normal file
654
SOURCES/13.patch
Normal file
@ -0,0 +1,654 @@
|
||||
From fe823e3cfe25c96de5e453d1acbdc036892a9c36 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <withnall@endlessm.com>
|
||||
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 <withnall@endlessm.com>
|
||||
|
||||
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 <withnall@endlessm.com>
|
||||
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 <withnall@endlessm.com>
|
||||
|
||||
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 @@
|
||||
<arg><option>--xml-files</option> <replaceable>FILE</replaceable></arg>
|
||||
<arg><option>--header</option></arg>
|
||||
<arg><option>--body</option></arg>
|
||||
+ <arg><option>--interface-info-header</option></arg>
|
||||
+ <arg><option>--interface-info-body</option></arg>
|
||||
<arg><option>--output</option> <replaceable>OUTFILE</replaceable></arg>
|
||||
<group choice="plain" rep="repeat">
|
||||
<arg>
|
||||
@@ -69,7 +71,11 @@
|
||||
arguments on the command line and generates output files.
|
||||
It currently supports generating C source code (via
|
||||
<option>--body</option>) or header (via <option>--header</option>)
|
||||
- and Docbook XML (via <option>--generate-docbook</option>).
|
||||
+ and Docbook XML (via <option>--generate-docbook</option>). Alternatively,
|
||||
+ more restricted C source code and headers can be generated, which just
|
||||
+ contain the interface information (as <type>GDBusInterfaceInfo</type>
|
||||
+ structures) using <option>--interface-info-body</option> and
|
||||
+ <option>--interface-info-header</option>.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
@@ -90,8 +96,11 @@
|
||||
</para>
|
||||
<para>
|
||||
For C code generation either <option>--body</option> that
|
||||
- generates source code, or <option>--header</option> that
|
||||
- generates headers, can be used. These options must be used along with
|
||||
+ generates source code, <option>--header</option> that
|
||||
+ generates headers, <option>--interface-info-body</option> that generates
|
||||
+ interface information source code, or
|
||||
+ <option>--interface-info-header</option> that generates interface information
|
||||
+ headers, can be used. These options must be used along with
|
||||
<option>--output</option>, which is used to specify the file to output to.
|
||||
</para>
|
||||
<para>
|
||||
@@ -282,8 +291,10 @@
|
||||
Directory to output generated source to. Equivalent to changing directory before generation.
|
||||
</para>
|
||||
<para>
|
||||
- This option cannot be used with neither <option>--body</option> nor
|
||||
- <option>--header</option>, and <option>--output</option> must be used.
|
||||
+ This option cannot be used with <option>--body</option>,
|
||||
+ <option>--header</option>, <option>--interface-info-body</option> or
|
||||
+ <option>--interface-info-header</option>; and
|
||||
+ <option>--output</option> must be used.
|
||||
</para>
|
||||
|
||||
</listitem>
|
||||
@@ -321,12 +332,52 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><option>--interface-info-header</option></term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ If this option is passed, it will generate the header code for the
|
||||
+ <type>GDBusInterfaceInfo</type> structures only and will write it to
|
||||
+ the disk by using the path and file name provided by
|
||||
+ <option>--output</option>.
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ Using <option>--generate-c-code</option>, <option>--generate-docbook</option> or
|
||||
+ <option>--output-directory</option> are not allowed to be used along with
|
||||
+ the <option>--interface-info-header</option> and
|
||||
+ <option>--interface-info-body</option> options, because these options
|
||||
+ are used to generate only one file.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term><option>--interface-info-body</option></term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ If this option is passed, it will generate the source code for the
|
||||
+ <type>GDBusInterfaceInfo</type> structures only and will write it to
|
||||
+ the disk by using the path and file name provided by
|
||||
+ <option>--output</option>.
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ Using <option>--generate-c-code</option>, <option>--generate-docbook</option> or
|
||||
+ <option>--output-directory</option> are not allowed to be used along with
|
||||
+ the <option>--interface-info-header</option> and
|
||||
+ <option>--interface-info-body</option> options, because these options
|
||||
+ are used to generate only one file.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term><option>--output</option> <replaceable>OUTFILE</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
- The full path where the header (<option>--header</option>) or the source code
|
||||
- (<option>--body</option>) will be written, using the path and filename provided by
|
||||
+ The full path where the header (<option>--header</option>,
|
||||
+ <option>--interface-info-header</option>) or the source code
|
||||
+ (<option>--body</option>, <option>--interface-info-body</option>) will
|
||||
+ be written, using the path and filename provided by
|
||||
<option>--output</option>. The full path could be something like
|
||||
<literal>$($OUTFILE).{c,h}</literal>.
|
||||
</para>
|
||||
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 <gio/gio.h>\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 <string.h>\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 <withnall@endlessm.com>
|
||||
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 <withnall@endlessm.com>
|
||||
|
||||
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 <withnall@endlessm.com>
|
||||
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 <withnall@endlessm.com>
|
||||
|
||||
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
|
401
SOURCES/1549.patch
Normal file
401
SOURCES/1549.patch
Normal file
@ -0,0 +1,401 @@
|
||||
From d0821da5244fd08c756a5f84ec0d3063c72d1ac6 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Thu, 26 Apr 2018 10:36:36 +0200
|
||||
Subject: [PATCH] gio: Add g_unix_mount_get_options
|
||||
|
||||
GVfsUDisks2VolumeMonitor handles x-gvfs-hide/x-gvfs-show mount options
|
||||
used to overwrite our heuristics whether the mount should be shown, or
|
||||
hidden. Unfortunately, it works currently only for mounts with
|
||||
corresponding fstab entries, because the options are read over
|
||||
g_unix_mount_point_get_options. Let's introduce g_unix_mount_get_options
|
||||
to allow reading of the options for all sort of mounts (e.g. created
|
||||
over pam_mount, or manually mounted).
|
||||
|
||||
(Minor fixes to the documentation by Philip Withnall
|
||||
<withnall@endlessm.com>.)
|
||||
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=668132
|
||||
---
|
||||
docs/reference/gio/gio-sections.txt | 1 +
|
||||
gio/gunixmounts.c | 37 +++++++++++++++++++++++++++++
|
||||
gio/gunixmounts.h | 2 ++
|
||||
3 files changed, 40 insertions(+)
|
||||
|
||||
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
|
||||
index 2eb7efc748..0a35f9541b 100644
|
||||
--- a/docs/reference/gio/gio-sections.txt
|
||||
+++ b/docs/reference/gio/gio-sections.txt
|
||||
@@ -1546,6 +1546,7 @@ g_unix_mount_copy
|
||||
g_unix_mount_get_mount_path
|
||||
g_unix_mount_get_device_path
|
||||
g_unix_mount_get_fs_type
|
||||
+g_unix_mount_get_options
|
||||
g_unix_mount_is_readonly
|
||||
g_unix_mount_is_system_internal
|
||||
g_unix_mount_guess_icon
|
||||
diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c
|
||||
index c74b0cfaf4..f2db27e661 100644
|
||||
--- a/gio/gunixmounts.c
|
||||
+++ b/gio/gunixmounts.c
|
||||
@@ -126,6 +126,7 @@ struct _GUnixMountEntry {
|
||||
char *mount_path;
|
||||
char *device_path;
|
||||
char *filesystem_type;
|
||||
+ char *options;
|
||||
gboolean is_read_only;
|
||||
gboolean is_system_internal;
|
||||
};
|
||||
@@ -412,6 +413,7 @@ static GUnixMountEntry *
|
||||
create_unix_mount_entry (const char *device_path,
|
||||
const char *mount_path,
|
||||
const char *filesystem_type,
|
||||
+ const char *options,
|
||||
gboolean is_read_only)
|
||||
{
|
||||
GUnixMountEntry *mount_entry = NULL;
|
||||
@@ -420,6 +422,7 @@ create_unix_mount_entry (const char *device_path,
|
||||
mount_entry->device_path = g_strdup (device_path);
|
||||
mount_entry->mount_path = g_strdup (mount_path);
|
||||
mount_entry->filesystem_type = g_strdup (filesystem_type);
|
||||
+ mount_entry->options = g_strdup (options);
|
||||
mount_entry->is_read_only = is_read_only;
|
||||
|
||||
mount_entry->is_system_internal =
|
||||
@@ -498,6 +501,7 @@ _g_get_unix_mounts (void)
|
||||
mount_entry = create_unix_mount_entry (device_path,
|
||||
mnt_fs_get_target (fs),
|
||||
mnt_fs_get_fstype (fs),
|
||||
+ mnt_fs_get_options (fs),
|
||||
is_read_only);
|
||||
|
||||
return_list = g_list_prepend (return_list, mount_entry);
|
||||
@@ -592,6 +596,7 @@ _g_get_unix_mounts (void)
|
||||
mount_entry = create_unix_mount_entry (device_path,
|
||||
mntent->mnt_dir,
|
||||
mntent->mnt_type,
|
||||
+ mntent->mnt_opts,
|
||||
is_read_only);
|
||||
|
||||
g_hash_table_insert (mounts_hash,
|
||||
@@ -705,6 +710,7 @@ _g_get_unix_mounts (void)
|
||||
mount_entry = create_unix_mount_entry (mntent.mnt_special,
|
||||
mntent.mnt_mountp,
|
||||
mntent.mnt_fstype,
|
||||
+ mntent.mnt_opts,
|
||||
is_read_only);
|
||||
|
||||
return_list = g_list_prepend (return_list, mount_entry);
|
||||
@@ -771,6 +777,7 @@ _g_get_unix_mounts (void)
|
||||
mount_entry = create_unix_mount_entry (vmt2dataptr (vmount_info, VMT_OBJECT),
|
||||
vmt2dataptr (vmount_info, VMT_STUB),
|
||||
fs_info == NULL ? "unknown" : fs_info->vfsent_name,
|
||||
+ NULL,
|
||||
is_read_only);
|
||||
|
||||
return_list = g_list_prepend (return_list, mount_entry);
|
||||
@@ -846,6 +853,7 @@ _g_get_unix_mounts (void)
|
||||
mount_entry = create_unix_mount_entry (mntent[i].f_mntfromname,
|
||||
mntent[i].f_mntonname,
|
||||
mntent[i].f_fstypename,
|
||||
+ NULL,
|
||||
is_read_only);
|
||||
|
||||
return_list = g_list_prepend (return_list, mount_entry);
|
||||
@@ -1989,6 +1997,7 @@ g_unix_mount_free (GUnixMountEntry *mount_entry)
|
||||
g_free (mount_entry->mount_path);
|
||||
g_free (mount_entry->device_path);
|
||||
g_free (mount_entry->filesystem_type);
|
||||
+ g_free (mount_entry->options);
|
||||
g_free (mount_entry);
|
||||
}
|
||||
|
||||
@@ -2013,6 +2022,7 @@ g_unix_mount_copy (GUnixMountEntry *mount_entry)
|
||||
copy->mount_path = g_strdup (mount_entry->mount_path);
|
||||
copy->device_path = g_strdup (mount_entry->device_path);
|
||||
copy->filesystem_type = g_strdup (mount_entry->filesystem_type);
|
||||
+ copy->options = g_strdup (mount_entry->options);
|
||||
copy->is_read_only = mount_entry->is_read_only;
|
||||
copy->is_system_internal = mount_entry->is_system_internal;
|
||||
|
||||
@@ -2096,6 +2106,10 @@ g_unix_mount_compare (GUnixMountEntry *mount1,
|
||||
if (res != 0)
|
||||
return res;
|
||||
|
||||
+ res = g_strcmp0 (mount1->options, mount2->options);
|
||||
+ if (res != 0)
|
||||
+ return res;
|
||||
+
|
||||
res = mount1->is_read_only - mount2->is_read_only;
|
||||
if (res != 0)
|
||||
return res;
|
||||
@@ -2151,6 +2165,29 @@ g_unix_mount_get_fs_type (GUnixMountEntry *mount_entry)
|
||||
return mount_entry->filesystem_type;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * g_unix_mount_get_options:
|
||||
+ * @mount_entry: a #GUnixMountEntry.
|
||||
+ *
|
||||
+ * Gets a comma-separated list of mount options for the unix mount. For example,
|
||||
+ * `rw,relatime,seclabel,data=ordered`.
|
||||
+ *
|
||||
+ * This is similar to g_unix_mount_point_get_options(), but it takes
|
||||
+ * a #GUnixMountEntry as an argument.
|
||||
+ *
|
||||
+ * Returns: (nullable): a string containing the options, or %NULL if not
|
||||
+ * available.
|
||||
+ *
|
||||
+ * Since: 2.58
|
||||
+ */
|
||||
+const gchar *
|
||||
+g_unix_mount_get_options (GUnixMountEntry *mount_entry)
|
||||
+{
|
||||
+ g_return_val_if_fail (mount_entry != NULL, NULL);
|
||||
+
|
||||
+ return mount_entry->options;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* g_unix_mount_is_readonly:
|
||||
* @mount_entry: a #GUnixMount.
|
||||
diff --git a/gio/gunixmounts.h b/gio/gunixmounts.h
|
||||
index 04d6b0726b..a392d497f1 100644
|
||||
--- a/gio/gunixmounts.h
|
||||
+++ b/gio/gunixmounts.h
|
||||
@@ -81,6 +81,8 @@ GLIB_AVAILABLE_IN_ALL
|
||||
const char * g_unix_mount_get_device_path (GUnixMountEntry *mount_entry);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
const char * g_unix_mount_get_fs_type (GUnixMountEntry *mount_entry);
|
||||
+GLIB_AVAILABLE_IN_2_56
|
||||
+const char * g_unix_mount_get_options (GUnixMountEntry *mount_entry);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gboolean g_unix_mount_is_readonly (GUnixMountEntry *mount_entry);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
--
|
||||
GitLab
|
||||
|
||||
From 51ec01382137251e08948bbd860a5fbfde41e5ba Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Tue, 23 Jun 2020 08:23:16 +0200
|
||||
Subject: [PATCH 1/2] gunixmounts: Add g_unix_mount_point_at
|
||||
|
||||
There is already g_unix_mount_at function which allows to find certain
|
||||
unix mount for given mount path. It would be useful to have similar
|
||||
function for mount points, which will allow to replace custom codes in
|
||||
gvfs. Let's add g_unix_mount_point_at.
|
||||
---
|
||||
docs/reference/gio/gio-sections.txt | 1 +
|
||||
gio/gunixmounts.c | 46 +++++++++++++++++++++++++++++
|
||||
gio/gunixmounts.h | 3 ++
|
||||
3 files changed, 50 insertions(+)
|
||||
|
||||
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
|
||||
index 2eb7efc74..5c9cbc34c 100644
|
||||
--- a/docs/reference/gio/gio-sections.txt
|
||||
+++ b/docs/reference/gio/gio-sections.txt
|
||||
@@ -1568,6 +1568,7 @@ g_unix_mount_point_guess_symbolic_icon
|
||||
g_unix_mount_point_guess_name
|
||||
g_unix_mount_point_guess_can_eject
|
||||
g_unix_mount_points_get
|
||||
+g_unix_mount_point_at
|
||||
g_unix_mounts_get
|
||||
g_unix_mount_at
|
||||
g_unix_mounts_changed_since
|
||||
diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c
|
||||
index 4d19217ca..144da4d29 100644
|
||||
--- a/gio/gunixmounts.c
|
||||
+++ b/gio/gunixmounts.c
|
||||
@@ -1596,6 +1596,52 @@ g_unix_mount_points_get (guint64 *time_read)
|
||||
return _g_get_unix_mount_points ();
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * g_unix_mount_point_at:
|
||||
+ * @mount_path: (type filename): path for a possible unix mount point.
|
||||
+ * @time_read: (out) (optional): guint64 to contain a timestamp.
|
||||
+ *
|
||||
+ * Gets a #GUnixMountPoint for a given mount path. If @time_read is set, it
|
||||
+ * will be filled with a unix timestamp for checking if the mount points have
|
||||
+ * changed since with g_unix_mount_points_changed_since().
|
||||
+ *
|
||||
+ * If more mount points have the same mount path, the last matching mount point
|
||||
+ * is returned.
|
||||
+ *
|
||||
+ * Returns: (transfer full) (nullable): a #GUnixMountPoint, or %NULL if no match
|
||||
+ * is found.
|
||||
+ *
|
||||
+ * Since: 2.66
|
||||
+ **/
|
||||
+GUnixMountPoint *
|
||||
+g_unix_mount_point_at (const char *mount_path,
|
||||
+ guint64 *time_read)
|
||||
+{
|
||||
+ GList *mount_points, *l;
|
||||
+ GUnixMountPoint *mount_point, *found;
|
||||
+
|
||||
+ mount_points = g_unix_mount_points_get (time_read);
|
||||
+
|
||||
+ found = NULL;
|
||||
+ for (l = mount_points; l != NULL; l = l->next)
|
||||
+ {
|
||||
+ mount_point = l->data;
|
||||
+
|
||||
+ if (strcmp (mount_path, mount_point->mount_path) == 0)
|
||||
+ {
|
||||
+ if (found != NULL)
|
||||
+ g_unix_mount_point_free (found);
|
||||
+
|
||||
+ found = mount_point;
|
||||
+ }
|
||||
+ else
|
||||
+ g_unix_mount_point_free (mount_point);
|
||||
+ }
|
||||
+ g_list_free (mount_points);
|
||||
+
|
||||
+ return found;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* g_unix_mounts_changed_since:
|
||||
* @time: guint64 to contain a timestamp.
|
||||
diff --git a/gio/gunixmounts.h b/gio/gunixmounts.h
|
||||
index 04d6b0726..ab9d3dbb9 100644
|
||||
--- a/gio/gunixmounts.h
|
||||
+++ b/gio/gunixmounts.h
|
||||
@@ -128,6 +128,9 @@ GIcon * g_unix_mount_point_guess_symbolic_icon (GUnixMountPoint *mount
|
||||
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GList * g_unix_mount_points_get (guint64 *time_read);
|
||||
+GLIB_AVAILABLE_IN_2_56
|
||||
+GUnixMountPoint *g_unix_mount_point_at (const char *mount_path,
|
||||
+ guint64 *time_read);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GList * g_unix_mounts_get (guint64 *time_read);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
--
|
||||
2.41.0
|
||||
|
||||
From 6daee34fac29df6f182e7e2aa656e0b34bd916a5 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Tue, 23 Jun 2020 08:36:26 +0200
|
||||
Subject: [PATCH 2/2] gfile: Add support for x-gvfs-notrash option to ignore
|
||||
mounts
|
||||
|
||||
Add support for x-gvfs-notrash mount option, which allows to disable
|
||||
trash functionality for certain mounts. This might be especially useful
|
||||
e.g. to prevent trash folder creation on enterprise shares, which are
|
||||
also accessed from Windows...
|
||||
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1096200
|
||||
---
|
||||
gio/gfile.c | 4 ++-
|
||||
gio/glocalfile.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 66 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gio/gfile.c b/gio/gfile.c
|
||||
index 447da3cfb..43c5c3d74 100644
|
||||
--- a/gio/gfile.c
|
||||
+++ b/gio/gfile.c
|
||||
@@ -4166,7 +4166,9 @@ g_file_delete_finish (GFile *file,
|
||||
* Sends @file to the "Trashcan", if possible. This is similar to
|
||||
* deleting it, but the user can recover it before emptying the trashcan.
|
||||
* Not all file systems support trashing, so this call can return the
|
||||
- * %G_IO_ERROR_NOT_SUPPORTED error.
|
||||
+ * %G_IO_ERROR_NOT_SUPPORTED error. Since GLib 2.66, the `x-gvfs-notrash` unix
|
||||
+ * mount option can be used to disable g_file_trash() support for certain
|
||||
+ * mounts, the %G_IO_ERROR_NOT_SUPPORTED error will be returned in that case.
|
||||
*
|
||||
* If @cancellable is not %NULL, then the operation can be cancelled by
|
||||
* triggering the cancellable object from another thread. If the operation
|
||||
diff --git a/gio/glocalfile.c b/gio/glocalfile.c
|
||||
index e7481454e..cb0ecdafb 100644
|
||||
--- a/gio/glocalfile.c
|
||||
+++ b/gio/glocalfile.c
|
||||
@@ -1858,6 +1858,52 @@ try_make_relative (const char *path,
|
||||
return g_strdup (path);
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+ignore_trash_mount (GUnixMountEntry *mount)
|
||||
+{
|
||||
+ GUnixMountPoint *mount_point = NULL;
|
||||
+ const gchar *mount_options;
|
||||
+ gboolean retval = TRUE;
|
||||
+
|
||||
+ if (g_unix_mount_is_system_internal (mount))
|
||||
+ return TRUE;
|
||||
+
|
||||
+ mount_options = g_unix_mount_get_options (mount);
|
||||
+ if (mount_options == NULL)
|
||||
+ {
|
||||
+ mount_point = g_unix_mount_point_at (g_unix_mount_get_mount_path (mount),
|
||||
+ NULL);
|
||||
+ if (mount_point != NULL)
|
||||
+ mount_options = g_unix_mount_point_get_options (mount_point);
|
||||
+ }
|
||||
+
|
||||
+ if (mount_options == NULL ||
|
||||
+ strstr (mount_options, "x-gvfs-notrash") == NULL)
|
||||
+ retval = FALSE;
|
||||
+
|
||||
+ g_clear_pointer (&mount_point, g_unix_mount_point_free);
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+ignore_trash_path (const gchar *topdir)
|
||||
+{
|
||||
+ GUnixMountEntry *mount;
|
||||
+ gboolean retval = TRUE;
|
||||
+
|
||||
+ mount = g_unix_mount_at (topdir, NULL);
|
||||
+ if (mount == NULL)
|
||||
+ goto out;
|
||||
+
|
||||
+ retval = ignore_trash_mount (mount);
|
||||
+
|
||||
+ out:
|
||||
+ g_clear_pointer (&mount, g_unix_mount_free);
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
gboolean
|
||||
_g_local_file_has_trash_dir (const char *dirname, dev_t dir_dev)
|
||||
{
|
||||
@@ -1886,6 +1932,13 @@ _g_local_file_has_trash_dir (const char *dirname, dev_t dir_dev)
|
||||
if (topdir == NULL)
|
||||
return FALSE;
|
||||
|
||||
+ if (ignore_trash_path (topdir))
|
||||
+ {
|
||||
+ g_free (topdir);
|
||||
+
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
globaldir = g_build_filename (topdir, ".Trash", NULL);
|
||||
if (g_lstat (globaldir, &global_stat) == 0 &&
|
||||
S_ISDIR (global_stat.st_mode) &&
|
||||
@@ -2041,7 +2094,16 @@ g_local_file_trash (GFile *file,
|
||||
file, G_IO_ERROR_NOT_SUPPORTED);
|
||||
return FALSE;
|
||||
}
|
||||
-
|
||||
+
|
||||
+ if (ignore_trash_path (topdir))
|
||||
+ {
|
||||
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
+ _("Trashing on system internal mounts is not supported"));
|
||||
+ g_free (topdir);
|
||||
+
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
/* Try looking for global trash dir $topdir/.Trash/$uid */
|
||||
globaldir = g_build_filename (topdir, ".Trash", NULL);
|
||||
if (g_lstat (globaldir, &global_stat) == 0 &&
|
||||
--
|
||||
2.41.0
|
||||
|
83
SOURCES/4155.patch
Normal file
83
SOURCES/4155.patch
Normal file
@ -0,0 +1,83 @@
|
||||
From d9fec76b594fccc6eda3ce04a74beae1c8b8c1d2 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Fri, 12 Jul 2024 11:14:10 +0200
|
||||
Subject: [PATCH] gfile: Add support for x-gvfs-trash mount option
|
||||
|
||||
Currently, the trash functionality is disabled for system internal mounts.
|
||||
That might be a problem in some cases. The `x-gvfs-notrash` mount option
|
||||
allows disabling the trash functionality for certain mounts. Let's add
|
||||
support for the `x-gvfs-trash` mount option to allow the opposite.
|
||||
|
||||
See: https://issues.redhat.com/browse/RHEL-46828
|
||||
---
|
||||
gio/gfile.c | 7 +++++--
|
||||
gio/glocalfile.c | 22 +++++++++++++---------
|
||||
2 files changed, 18 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/gio/gfile.c b/gio/gfile.c
|
||||
index 4f9b9c6750..5ac73c03e8 100644
|
||||
--- a/gio/gfile.c
|
||||
+++ b/gio/gfile.c
|
||||
@@ -4744,10 +4744,13 @@ g_file_delete_finish (GFile *file,
|
||||
*
|
||||
* Sends @file to the "Trashcan", if possible. This is similar to
|
||||
* deleting it, but the user can recover it before emptying the trashcan.
|
||||
- * Not all file systems support trashing, so this call can return the
|
||||
+ * Trashing is disabled for system mounts by default (see
|
||||
+ * g_unix_mount_is_system_internal()), so this call can return the
|
||||
* %G_IO_ERROR_NOT_SUPPORTED error. Since GLib 2.66, the `x-gvfs-notrash` unix
|
||||
- * mount option can be used to disable g_file_trash() support for certain
|
||||
+ * mount option can be used to disable g_file_trash() support for particular
|
||||
* mounts, the %G_IO_ERROR_NOT_SUPPORTED error will be returned in that case.
|
||||
+ * Since 2.82, the `x-gvfs-trash` unix mount option can be used to enable
|
||||
+ * g_file_trash() support for particular system mounts.
|
||||
*
|
||||
* If @cancellable is not %NULL, then the operation can be cancelled by
|
||||
* triggering the cancellable object from another thread. If the operation
|
||||
diff --git a/gio/glocalfile.c b/gio/glocalfile.c
|
||||
index 7b70c614c6..ac918d25e3 100644
|
||||
--- a/gio/glocalfile.c
|
||||
+++ b/gio/glocalfile.c
|
||||
@@ -1807,10 +1807,6 @@ ignore_trash_mount (GUnixMountEntry *mount)
|
||||
{
|
||||
GUnixMountPoint *mount_point = NULL;
|
||||
const gchar *mount_options;
|
||||
- gboolean retval = TRUE;
|
||||
-
|
||||
- if (g_unix_mount_is_system_internal (mount))
|
||||
- return TRUE;
|
||||
|
||||
mount_options = g_unix_mount_get_options (mount);
|
||||
if (mount_options == NULL)
|
||||
@@ -1819,15 +1815,23 @@ ignore_trash_mount (GUnixMountEntry *mount)
|
||||
NULL);
|
||||
if (mount_point != NULL)
|
||||
mount_options = g_unix_mount_point_get_options (mount_point);
|
||||
+
|
||||
+ g_clear_pointer (&mount_point, g_unix_mount_point_free);
|
||||
}
|
||||
|
||||
- if (mount_options == NULL ||
|
||||
- strstr (mount_options, "x-gvfs-notrash") == NULL)
|
||||
- retval = FALSE;
|
||||
+ if (mount_options != NULL)
|
||||
+ {
|
||||
+ if (strstr (mount_options, "x-gvfs-trash") != NULL)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (strstr (mount_options, "x-gvfs-notrash") != NULL)
|
||||
+ return TRUE;
|
||||
+ }
|
||||
|
||||
- g_clear_pointer (&mount_point, g_unix_mount_point_free);
|
||||
+ if (g_unix_mount_is_system_internal (mount))
|
||||
+ return TRUE;
|
||||
|
||||
- return retval;
|
||||
+ return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
--
|
||||
GitLab
|
||||
|
702
SOURCES/54.patch
Normal file
702
SOURCES/54.patch
Normal file
@ -0,0 +1,702 @@
|
||||
From 9e5a53d576765819d1c7c233515b9f6e5d77eb61 Mon Sep 17 00:00:00 2001
|
||||
From: Emmanuele Bassi <ebassi@gnome.org>
|
||||
Date: Wed, 17 Jan 2018 16:38:45 +0000
|
||||
Subject: [PATCH] Add reference counting types
|
||||
|
||||
We have a common pattern for reference counting in GLib, but we always
|
||||
implement it with ad hoc code. This is a good chance at trying to
|
||||
standardise the implementation and make it public, so that other code
|
||||
using GLib can take advantage of shared behaviour and semantics.
|
||||
|
||||
Instead of simply taking an integer variable, we should create type
|
||||
aliases, to immediately distinguish the reference counting semantics of
|
||||
the code; we can handle mixing atomic reference counting with a
|
||||
non-atomic type (and vice versa) by using differently signed values for
|
||||
the atomic and non-atomic cases.
|
||||
|
||||
The gatomicrefcount type is modelled on the Linux kernel refcount_t
|
||||
type; the grefcount type is added to let single-threaded code bases to
|
||||
avoid paying the price of atomic memory barriers on reference counting
|
||||
operations.
|
||||
---
|
||||
docs/reference/glib/glib-docs.xml | 1 +
|
||||
docs/reference/glib/glib-sections.txt | 15 ++
|
||||
glib/Makefile.am | 2 +
|
||||
glib/glib.h | 1 +
|
||||
glib/grefcount.c | 285 ++++++++++++++++++++++++++
|
||||
glib/grefcount.h | 52 +++++
|
||||
glib/gtypes.h | 3 +
|
||||
glib/meson.build | 2 +
|
||||
8 files changed, 361 insertions(+)
|
||||
create mode 100644 glib/grefcount.c
|
||||
create mode 100644 glib/grefcount.h
|
||||
|
||||
diff --git a/docs/reference/glib/glib-docs.xml b/docs/reference/glib/glib-docs.xml
|
||||
index a0716c1727..26cdafb67b 100644
|
||||
--- a/docs/reference/glib/glib-docs.xml
|
||||
+++ b/docs/reference/glib/glib-docs.xml
|
||||
@@ -119,6 +119,7 @@
|
||||
<xi:include href="xml/gvariant.xml"/>
|
||||
<xi:include href="gvariant-varargs.xml"/>
|
||||
<xi:include href="gvariant-text.xml"/>
|
||||
+ <xi:include href="xml/refcount.xml"/>
|
||||
</chapter>
|
||||
|
||||
<chapter id="deprecated">
|
||||
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
|
||||
index 0183b0898a..331d92c75f 100644
|
||||
--- a/docs/reference/glib/glib-sections.txt
|
||||
+++ b/docs/reference/glib/glib-sections.txt
|
||||
@@ -3449,3 +3449,18 @@ g_hostname_is_ip_address
|
||||
g_uuid_string_is_valid
|
||||
g_uuid_string_random
|
||||
</SECTION>
|
||||
+
|
||||
+<SECTION>
|
||||
+<FILE>refcount</FILE>
|
||||
+grefcount
|
||||
+g_ref_count_init
|
||||
+g_ref_count_inc
|
||||
+g_ref_count_dec
|
||||
+g_ref_count_compare
|
||||
+<SUBSECTION>
|
||||
+gatomicrefcount
|
||||
+g_atomic_ref_count_init
|
||||
+g_atomic_ref_count_inc
|
||||
+g_atomic_ref_count_dec
|
||||
+g_atomic_ref_count_compare
|
||||
+</SECTION>
|
||||
diff --git a/glib/Makefile.am b/glib/Makefile.am
|
||||
index 0497061265..4d04e09daa 100644
|
||||
--- a/glib/Makefile.am
|
||||
+++ b/glib/Makefile.am
|
||||
@@ -149,6 +149,7 @@ libglib_2_0_la_SOURCES = \
|
||||
gquark.c \
|
||||
gqueue.c \
|
||||
grand.c \
|
||||
+ grefcount.c \
|
||||
gregex.c \
|
||||
gscanner.c \
|
||||
gscripttable.h \
|
||||
@@ -284,6 +285,7 @@ glibsubinclude_HEADERS = \
|
||||
gquark.h \
|
||||
gqueue.h \
|
||||
grand.h \
|
||||
+ grefcount.h \
|
||||
gregex.h \
|
||||
gscanner.h \
|
||||
gsequence.h \
|
||||
diff --git a/glib/glib.h b/glib/glib.h
|
||||
index 4f5a7f702f..84299c4f90 100644
|
||||
--- a/glib/glib.h
|
||||
+++ b/glib/glib.h
|
||||
@@ -69,6 +69,7 @@
|
||||
#include <glib/gquark.h>
|
||||
#include <glib/gqueue.h>
|
||||
#include <glib/grand.h>
|
||||
+#include <glib/grefcount.h>
|
||||
#include <glib/gregex.h>
|
||||
#include <glib/gscanner.h>
|
||||
#include <glib/gsequence.h>
|
||||
diff --git a/glib/grefcount.c b/glib/grefcount.c
|
||||
new file mode 100644
|
||||
index 0000000000..10e35a217d
|
||||
--- /dev/null
|
||||
+++ b/glib/grefcount.c
|
||||
@@ -0,0 +1,285 @@
|
||||
+/* grefcount.c: Reference counting
|
||||
+ *
|
||||
+ * Copyright 2018 Emmanuele Bassi
|
||||
+ *
|
||||
+ * 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 <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * SECTION:refcount
|
||||
+ * @Title: Reference counting
|
||||
+ * @Short_description: Reference counting types and functions
|
||||
+ *
|
||||
+ * Reference counting is a garbage collection mechanism that is based on
|
||||
+ * assigning a counter to a data type, or any memory area; the counter is
|
||||
+ * increased whenever a new reference to that data type is acquired, and
|
||||
+ * decreased whenever the reference is released. Once the last reference
|
||||
+ * is released, the resources associated to that data type are freed.
|
||||
+ *
|
||||
+ * GLib uses reference counting in many of its data types, and provides
|
||||
+ * the #grefcount and #gatomicrefcount types to implement safe and atomic
|
||||
+ * reference counting semantics in new data types.
|
||||
+ *
|
||||
+ * It is important to note that #grefcount and #gatomicrefcount should be
|
||||
+ * considered completely opaque types; you should always use the provided
|
||||
+ * API to increase and decrease the counters, and you should never check
|
||||
+ * their content directly, or compare their content with other values.
|
||||
+ *
|
||||
+ * Since: 2.58
|
||||
+ */
|
||||
+
|
||||
+#include "config.h"
|
||||
+
|
||||
+#include "grefcount.h"
|
||||
+
|
||||
+#include "gatomic.h"
|
||||
+#include "gmessages.h"
|
||||
+
|
||||
+/**
|
||||
+ * grefcount:
|
||||
+ *
|
||||
+ * A type for implementing non-atomic reference count semantics.
|
||||
+ *
|
||||
+ * Use g_ref_count_init() to initialize it; g_ref_count_inc() to
|
||||
+ * increase the counter, and g_ref_count_dec() to decrease it.
|
||||
+ *
|
||||
+ * It is safe to use #grefcount only if you're expecting to operate
|
||||
+ * on the reference counter from a single thread. It is entirely up
|
||||
+ * to you to ensure that all reference count changes happen in the
|
||||
+ * same thread.
|
||||
+ *
|
||||
+ * See also: #gatomicrefcount
|
||||
+ *
|
||||
+ * Since: 2.58
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * gatomicrefcount:
|
||||
+ *
|
||||
+ * A type for implementing atomic reference count semantics.
|
||||
+ *
|
||||
+ * Use g_atomic_ref_count_init() to initialize it; g_atomic_ref_count_inc()
|
||||
+ * to increase the counter, and g_atomic_ref_count_dec() to decrease it.
|
||||
+ *
|
||||
+ * It is safe to use #gatomicrefcount if you're expecting to operate on the
|
||||
+ * reference counter from multiple threads.
|
||||
+ *
|
||||
+ * See also: #grefcount
|
||||
+ *
|
||||
+ * Since: 2.58
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * g_ref_count_init:
|
||||
+ * @rc: the address of a reference count variable
|
||||
+ *
|
||||
+ * Initializes a reference count variable.
|
||||
+ *
|
||||
+ * Since: 2.58
|
||||
+ */
|
||||
+void
|
||||
+g_ref_count_init (grefcount *rc)
|
||||
+{
|
||||
+ g_return_if_fail (rc != NULL);
|
||||
+
|
||||
+ /* Non-atomic refcounting is implemented using the negative range
|
||||
+ * of signed integers:
|
||||
+ *
|
||||
+ * G_MININT Z¯< 0 > Z⺠G_MAXINT
|
||||
+ * |----------------------------|----------------------------|
|
||||
+ *
|
||||
+ * Acquiring a reference moves us towards MININT, and releasing a
|
||||
+ * reference moves us towards 0.
|
||||
+ */
|
||||
+ *rc = -1;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * g_ref_count_inc:
|
||||
+ * @rc: the address of a reference count variable
|
||||
+ *
|
||||
+ * Increases the reference count.
|
||||
+ *
|
||||
+ * Since: 2.58
|
||||
+ */
|
||||
+void
|
||||
+g_ref_count_inc (grefcount *rc)
|
||||
+{
|
||||
+ grefcount rrc;
|
||||
+
|
||||
+ g_return_if_fail (rc != NULL);
|
||||
+
|
||||
+ rrc = *rc;
|
||||
+
|
||||
+ g_return_if_fail (rrc < 0);
|
||||
+
|
||||
+ /* Check for saturation */
|
||||
+ if (rrc == G_MININT)
|
||||
+ {
|
||||
+ g_critical ("Reference count %p has reached saturation", rc);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ rrc -= 1;
|
||||
+
|
||||
+ *rc = rrc;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * g_ref_count_dec:
|
||||
+ * @rc: the address of a reference count variable
|
||||
+ *
|
||||
+ * Decreases the reference count.
|
||||
+ *
|
||||
+ * Returns: %TRUE if the reference count reached 0, and %FALSE otherwise
|
||||
+ *
|
||||
+ * Since: 2.58
|
||||
+ */
|
||||
+gboolean
|
||||
+g_ref_count_dec (grefcount *rc)
|
||||
+{
|
||||
+ grefcount rrc;
|
||||
+
|
||||
+ g_return_val_if_fail (rc != NULL, FALSE);
|
||||
+
|
||||
+ rrc = *rc;
|
||||
+
|
||||
+ g_return_val_if_fail (rrc < 0, FALSE);
|
||||
+
|
||||
+ rrc += 1;
|
||||
+ if (rrc == 0)
|
||||
+ return TRUE;
|
||||
+
|
||||
+ *rc = rrc;
|
||||
+
|
||||
+ return FALSE;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * g_ref_count_compare:
|
||||
+ * @rc: the address of a reference count variable
|
||||
+ * @val: the value to compare
|
||||
+ *
|
||||
+ * Compares the current value of @rc with @val.
|
||||
+ *
|
||||
+ * Returns: %TRUE if the reference count is the same
|
||||
+ * as the given value
|
||||
+ *
|
||||
+ * Since: 2.58
|
||||
+ */
|
||||
+gboolean
|
||||
+g_ref_count_compare (grefcount *rc,
|
||||
+ gint val)
|
||||
+{
|
||||
+ grefcount rrc;
|
||||
+
|
||||
+ g_return_val_if_fail (rc != NULL, FALSE);
|
||||
+ g_return_val_if_fail (val >= 0, FALSE);
|
||||
+
|
||||
+ rrc = *rc;
|
||||
+
|
||||
+ if (val == G_MAXINT)
|
||||
+ return rrc == G_MININT;
|
||||
+
|
||||
+ return rrc == -val;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * g_atomic_ref_count_init:
|
||||
+ * @arc: the address of an atomic reference count variable
|
||||
+ *
|
||||
+ * Atomically initializes a reference count variable.
|
||||
+ *
|
||||
+ * Since: 2.58
|
||||
+ */
|
||||
+void
|
||||
+g_atomic_ref_count_init (gatomicrefcount *arc)
|
||||
+{
|
||||
+ g_return_if_fail (arc != NULL);
|
||||
+
|
||||
+ /* Atomic refcounting is implemented using the positive range
|
||||
+ * of signed integers:
|
||||
+ *
|
||||
+ * G_MININT Z¯< 0 > Z⺠G_MAXINT
|
||||
+ * |----------------------------|----------------------------|
|
||||
+ *
|
||||
+ * Acquiring a reference moves us towards MAXINT, and releasing a
|
||||
+ * reference moves us towards 0.
|
||||
+ */
|
||||
+ g_atomic_int_set (arc, 1);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * g_atomic_ref_count_inc:
|
||||
+ * @arc: the address of an atomic reference count variable
|
||||
+ *
|
||||
+ * Atomically increases the reference count.
|
||||
+ *
|
||||
+ * Since: 2.58
|
||||
+ */
|
||||
+void
|
||||
+g_atomic_ref_count_inc (gatomicrefcount *arc)
|
||||
+{
|
||||
+ g_return_if_fail (arc != NULL);
|
||||
+ g_return_if_fail (g_atomic_int_get (arc) > 0);
|
||||
+
|
||||
+ if (g_atomic_int_get (arc) == G_MAXINT)
|
||||
+ {
|
||||
+ g_critical ("Reference count has reached saturation");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ g_atomic_int_inc (arc);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * g_atomic_ref_count_dec:
|
||||
+ * @arc: the address of an atomic reference count variable
|
||||
+ *
|
||||
+ * Atomically decreases the reference count.
|
||||
+ *
|
||||
+ * Returns: %TRUE if the reference count reached 0, and %FALSE otherwise
|
||||
+ *
|
||||
+ * Since: 2.58
|
||||
+ */
|
||||
+gboolean
|
||||
+g_atomic_ref_count_dec (gatomicrefcount *arc)
|
||||
+{
|
||||
+ g_return_val_if_fail (arc != NULL, FALSE);
|
||||
+ g_return_val_if_fail (g_atomic_int_get (arc) > 0, FALSE);
|
||||
+
|
||||
+ return g_atomic_int_dec_and_test (arc);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * g_atomic_ref_count_compare:
|
||||
+ * @arc: the address of an atomic reference count variable
|
||||
+ * @val: the value to compare
|
||||
+ *
|
||||
+ * Atomically compares the current value of @arc with @val.
|
||||
+ *
|
||||
+ * Returns: %TRUE if the reference count is the same
|
||||
+ * as the given value
|
||||
+ *
|
||||
+ * Since: 2.58
|
||||
+ */
|
||||
+gboolean
|
||||
+g_atomic_ref_count_compare (gatomicrefcount *arc,
|
||||
+ gint val)
|
||||
+{
|
||||
+ g_return_val_if_fail (arc != NULL, FALSE);
|
||||
+ g_return_val_if_fail (val >= 0, FALSE);
|
||||
+
|
||||
+ return g_atomic_int_get (arc) == val;
|
||||
+}
|
||||
diff --git a/glib/grefcount.h b/glib/grefcount.h
|
||||
new file mode 100644
|
||||
index 0000000000..b24c71e8cb
|
||||
--- /dev/null
|
||||
+++ b/glib/grefcount.h
|
||||
@@ -0,0 +1,52 @@
|
||||
+/* grefcount.h: Reference counting
|
||||
+ *
|
||||
+ * Copyright 2018 Emmanuele Bassi
|
||||
+ *
|
||||
+ * 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 <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __GREFCOUNT_H__
|
||||
+#define __GREFCOUNT_H__
|
||||
+
|
||||
+#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
+#error "Only <glib.h> can be included directly."
|
||||
+#endif
|
||||
+
|
||||
+#include <glib/gtypes.h>
|
||||
+
|
||||
+G_BEGIN_DECLS
|
||||
+
|
||||
+GLIB_AVAILABLE_IN_2_56
|
||||
+void g_ref_count_init (grefcount *rc);
|
||||
+GLIB_AVAILABLE_IN_2_56
|
||||
+void g_ref_count_inc (grefcount *rc);
|
||||
+GLIB_AVAILABLE_IN_2_56
|
||||
+gboolean g_ref_count_dec (grefcount *rc);
|
||||
+GLIB_AVAILABLE_IN_2_56
|
||||
+gboolean g_ref_count_compare (grefcount *rc,
|
||||
+ gint val);
|
||||
+
|
||||
+GLIB_AVAILABLE_IN_2_56
|
||||
+void g_atomic_ref_count_init (gatomicrefcount *arc);
|
||||
+GLIB_AVAILABLE_IN_2_56
|
||||
+void g_atomic_ref_count_inc (gatomicrefcount *arc);
|
||||
+GLIB_AVAILABLE_IN_2_56
|
||||
+gboolean g_atomic_ref_count_dec (gatomicrefcount *arc);
|
||||
+GLIB_AVAILABLE_IN_2_56
|
||||
+gboolean g_atomic_ref_count_compare (gatomicrefcount *arc,
|
||||
+ gint val);
|
||||
+
|
||||
+G_END_DECLS
|
||||
+
|
||||
+#endif /* __GREFCOUNT_H__ */
|
||||
diff --git a/glib/gtypes.h b/glib/gtypes.h
|
||||
index 09d9bd1456..67adb7f1f8 100644
|
||||
--- a/glib/gtypes.h
|
||||
+++ b/glib/gtypes.h
|
||||
@@ -510,6 +510,9 @@ struct _GTimeVal
|
||||
glong tv_usec;
|
||||
};
|
||||
|
||||
+typedef gint grefcount;
|
||||
+typedef volatile gint gatomicrefcount;
|
||||
+
|
||||
G_END_DECLS
|
||||
|
||||
/* We prefix variable declarations so they can
|
||||
diff --git a/glib/meson.build b/glib/meson.build
|
||||
index 036d1f4d60..76d354c2a7 100644
|
||||
--- a/glib/meson.build
|
||||
+++ b/glib/meson.build
|
||||
@@ -76,6 +76,7 @@ glib_sub_headers = files(
|
||||
'gquark.h',
|
||||
'gqueue.h',
|
||||
'grand.h',
|
||||
+ 'grefcount.h',
|
||||
'gregex.h',
|
||||
'gscanner.h',
|
||||
'gsequence.h',
|
||||
@@ -159,6 +160,7 @@ glib_sources = files(
|
||||
'gquark.c',
|
||||
'gqueue.c',
|
||||
'grand.c',
|
||||
+ 'grefcount.c',
|
||||
'gregex.c',
|
||||
'gscanner.c',
|
||||
'gsequence.c',
|
||||
--
|
||||
GitLab
|
||||
|
||||
From 827c208cbf9cc0ef17b8c4531a40aafe1edc3f01 Mon Sep 17 00:00:00 2001
|
||||
From: Emmanuele Bassi <ebassi@gnome.org>
|
||||
Date: Mon, 4 Jun 2018 11:38:40 +0100
|
||||
Subject: [PATCH] Use macros for refcount types API
|
||||
|
||||
If we're using GCC we can use __extension__ to inline the grefcount and
|
||||
gatomicrefcount API, and avoid the function call.
|
||||
|
||||
These macros are only enabled if G_DISABLE_CHECKS is defined, as they
|
||||
remove critical warnings when the reference counters achieve saturation.
|
||||
---
|
||||
glib/grefcount.c | 20 +++++++-------
|
||||
glib/grefcount.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 80 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/glib/grefcount.c b/glib/grefcount.c
|
||||
index 10e35a217d..37085316b9 100644
|
||||
--- a/glib/grefcount.c
|
||||
+++ b/glib/grefcount.c
|
||||
@@ -89,7 +89,7 @@
|
||||
* Since: 2.58
|
||||
*/
|
||||
void
|
||||
-g_ref_count_init (grefcount *rc)
|
||||
+(g_ref_count_init) (grefcount *rc)
|
||||
{
|
||||
g_return_if_fail (rc != NULL);
|
||||
|
||||
@@ -114,7 +114,7 @@ g_ref_count_init (grefcount *rc)
|
||||
* Since: 2.58
|
||||
*/
|
||||
void
|
||||
-g_ref_count_inc (grefcount *rc)
|
||||
+(g_ref_count_inc) (grefcount *rc)
|
||||
{
|
||||
grefcount rrc;
|
||||
|
||||
@@ -147,7 +147,7 @@ g_ref_count_inc (grefcount *rc)
|
||||
* Since: 2.58
|
||||
*/
|
||||
gboolean
|
||||
-g_ref_count_dec (grefcount *rc)
|
||||
+(g_ref_count_dec) (grefcount *rc)
|
||||
{
|
||||
grefcount rrc;
|
||||
|
||||
@@ -179,8 +179,8 @@ g_ref_count_dec (grefcount *rc)
|
||||
* Since: 2.58
|
||||
*/
|
||||
gboolean
|
||||
-g_ref_count_compare (grefcount *rc,
|
||||
- gint val)
|
||||
+(g_ref_count_compare) (grefcount *rc,
|
||||
+ gint val)
|
||||
{
|
||||
grefcount rrc;
|
||||
|
||||
@@ -204,7 +204,7 @@ g_ref_count_compare (grefcount *rc,
|
||||
* Since: 2.58
|
||||
*/
|
||||
void
|
||||
-g_atomic_ref_count_init (gatomicrefcount *arc)
|
||||
+(g_atomic_ref_count_init) (gatomicrefcount *arc)
|
||||
{
|
||||
g_return_if_fail (arc != NULL);
|
||||
|
||||
@@ -229,7 +229,7 @@ g_atomic_ref_count_init (gatomicrefcount *arc)
|
||||
* Since: 2.58
|
||||
*/
|
||||
void
|
||||
-g_atomic_ref_count_inc (gatomicrefcount *arc)
|
||||
+(g_atomic_ref_count_inc) (gatomicrefcount *arc)
|
||||
{
|
||||
g_return_if_fail (arc != NULL);
|
||||
g_return_if_fail (g_atomic_int_get (arc) > 0);
|
||||
@@ -254,7 +254,7 @@ g_atomic_ref_count_inc (gatomicrefcount *arc)
|
||||
* Since: 2.58
|
||||
*/
|
||||
gboolean
|
||||
-g_atomic_ref_count_dec (gatomicrefcount *arc)
|
||||
+(g_atomic_ref_count_dec) (gatomicrefcount *arc)
|
||||
{
|
||||
g_return_val_if_fail (arc != NULL, FALSE);
|
||||
g_return_val_if_fail (g_atomic_int_get (arc) > 0, FALSE);
|
||||
@@ -275,8 +275,8 @@ g_atomic_ref_count_dec (gatomicrefcount *arc)
|
||||
* Since: 2.58
|
||||
*/
|
||||
gboolean
|
||||
-g_atomic_ref_count_compare (gatomicrefcount *arc,
|
||||
- gint val)
|
||||
+(g_atomic_ref_count_compare) (gatomicrefcount *arc,
|
||||
+ gint val)
|
||||
{
|
||||
g_return_val_if_fail (arc != NULL, FALSE);
|
||||
g_return_val_if_fail (val >= 0, FALSE);
|
||||
diff --git a/glib/grefcount.h b/glib/grefcount.h
|
||||
index b24c71e8cb..dec9a5ffb8 100644
|
||||
--- a/glib/grefcount.h
|
||||
+++ b/glib/grefcount.h
|
||||
@@ -47,6 +47,76 @@ GLIB_AVAILABLE_IN_2_58
|
||||
gboolean g_atomic_ref_count_compare (gatomicrefcount *arc,
|
||||
gint val);
|
||||
|
||||
+/* On GCC we can use __extension__ to inline the API without using
|
||||
+ * ancillary functions; we only do this when disabling checks, as
|
||||
+ * it disables warnings when saturating the reference counters
|
||||
+ */
|
||||
+#if defined(__GNUC__) && defined(G_DISABLE_CHECKS)
|
||||
+
|
||||
+# define g_ref_count_init(rc) \
|
||||
+ (G_GNUC_EXTENSION ({ \
|
||||
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
|
||||
+ (void) (0 ? *(rc) ^ *(rc) : 1); \
|
||||
+ *(rc) = -1; \
|
||||
+ }))
|
||||
+
|
||||
+# define g_ref_count_inc(rc) \
|
||||
+ (G_GNUC_EXTENSION ({ \
|
||||
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
|
||||
+ (void) (0 ? *(rc) ^ *(rc) : 1); \
|
||||
+ if (*(rc) == G_MININT) ; else { \
|
||||
+ *(rc) -= 1; \
|
||||
+ } \
|
||||
+ }))
|
||||
+
|
||||
+# define g_ref_count_dec(rc) \
|
||||
+ (G_GNUC_EXTENSION ({ \
|
||||
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
|
||||
+ grefcount __rc = *(rc); \
|
||||
+ __rc += 1; \
|
||||
+ if (__rc == 0) ; else { \
|
||||
+ *(rc) = __rc; \
|
||||
+ } \
|
||||
+ (gboolean) (__rc == 0); \
|
||||
+ }))
|
||||
+
|
||||
+# define g_ref_count_compare(rc,val) \
|
||||
+ (G_GNUC_EXTENSION ({ \
|
||||
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
|
||||
+ (void) (0 ? *(rc) ^ (val) : 1); \
|
||||
+ (gboolean) (*(rc) == -(val)); \
|
||||
+ }))
|
||||
+
|
||||
+# define g_atomic_ref_count_init(rc) \
|
||||
+ (G_GNUC_EXTENSION ({ \
|
||||
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
|
||||
+ (void) (0 ? *(rc) ^ *(rc) : 1); \
|
||||
+ g_atomic_int_set ((rc), 1); \
|
||||
+ }))
|
||||
+
|
||||
+# define g_atomic_ref_count_inc(rc) \
|
||||
+ (G_GNUC_EXTENSION ({ \
|
||||
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
|
||||
+ (void) (0 ? *(rc) ^ *(rc) : 1); \
|
||||
+ (void) (g_atomic_int_get (rc) == G_MAXINT ? 0 : g_atomic_int_inc ((rc))); \
|
||||
+ }))
|
||||
+
|
||||
+# define g_atomic_ref_count_dec(rc) \
|
||||
+ (G_GNUC_EXTENSION ({ \
|
||||
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
|
||||
+ (void) (0 ? *(rc) ^ *(rc) : 1); \
|
||||
+ g_atomic_int_dec_and_test ((rc)); \
|
||||
+ }))
|
||||
+
|
||||
+# define g_atomic_ref_count_compare(rc,val) \
|
||||
+ (G_GNUC_EXTENSION ({ \
|
||||
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
|
||||
+ (void) (0 ? *(rc) ^ (val) : 1); \
|
||||
+ (gboolean) (g_atomic_int_get (rc) == (val)); \
|
||||
+ }))
|
||||
+
|
||||
+#endif /* __GNUC__ && G_DISABLE_CHECKS */
|
||||
+
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GREFCOUNT_H__ */
|
||||
--
|
||||
GitLab
|
||||
|
||||
From 09c149453ac969dedb1cb2d15d489d1dd81412bf Mon Sep 17 00:00:00 2001
|
||||
From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
|
||||
Date: Sat, 13 Oct 2018 23:10:33 +0200
|
||||
Subject: [PATCH] grefcount: add missing gatomic.h
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Without gatomic.h, build fails on:
|
||||
In file included from garcbox.c:24:0:
|
||||
garcbox.c: In function ‘g_atomic_rc_box_acquire’:
|
||||
grefcount.h:101:13: error: implicit declaration of function ‘g_atomic_int_get’; did you mean ‘__atomic_store’? [-Werror=implicit-function-declaration]
|
||||
(void) (g_atomic_int_get (rc) == G_MAXINT ? 0 : g_atomic_int_inc ((rc))); \
|
||||
^
|
||||
garcbox.c:292:3: note: in expansion of macro ‘g_atomic_ref_count_inc’
|
||||
g_atomic_ref_count_inc (&real_box->ref_count);
|
||||
|
||||
Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
|
||||
---
|
||||
glib/grefcount.h | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/glib/grefcount.h b/glib/grefcount.h
|
||||
index dec9a5ffb8..b6eced1b7d 100644
|
||||
--- a/glib/grefcount.h
|
||||
+++ b/glib/grefcount.h
|
||||
@@ -23,6 +23,7 @@
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
+#include <glib/gatomic.h>
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
--
|
||||
GitLab
|
||||
|
3170
SOURCES/CVE-2024-34397.patch
Normal file
3170
SOURCES/CVE-2024-34397.patch
Normal file
File diff suppressed because it is too large
Load Diff
45
SOURCES/CVE-2024-52533.patch
Normal file
45
SOURCES/CVE-2024-52533.patch
Normal file
@ -0,0 +1,45 @@
|
||||
From 25833cefda24c60af913d6f2d532b5afd608b821 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Catanzaro <mcatanzaro@redhat.com>
|
||||
Date: Thu, 19 Sep 2024 18:35:53 +0100
|
||||
Subject: [PATCH] gsocks4aproxy: Fix a single byte buffer overflow in connect
|
||||
messages
|
||||
|
||||
`SOCKS4_CONN_MSG_LEN` failed to account for the length of the final nul
|
||||
byte in the connect message, which is an addition in SOCKSv4a vs
|
||||
SOCKSv4.
|
||||
|
||||
This means that the buffer for building and transmitting the connect
|
||||
message could be overflowed if the username and hostname are both
|
||||
`SOCKS4_MAX_LEN` (255) bytes long.
|
||||
|
||||
Proxy configurations are normally statically configured, so the username
|
||||
is very unlikely to be near its maximum length, and hence this overflow
|
||||
is unlikely to be triggered in practice.
|
||||
|
||||
(Commit message by Philip Withnall, diagnosis and fix by Michael
|
||||
Catanzaro.)
|
||||
|
||||
Fixes: #3461
|
||||
---
|
||||
gio/gsocks4aproxy.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gio/gsocks4aproxy.c b/gio/gsocks4aproxy.c
|
||||
index 3dad118eb7..b3146d08fd 100644
|
||||
--- a/gio/gsocks4aproxy.c
|
||||
+++ b/gio/gsocks4aproxy.c
|
||||
@@ -79,9 +79,9 @@ g_socks4a_proxy_init (GSocks4aProxy *proxy)
|
||||
* +----+----+----+----+----+----+----+----+----+----+....+----+------+....+------+
|
||||
* | VN | CD | DSTPORT | DSTIP | USERID |NULL| HOST | | NULL |
|
||||
* +----+----+----+----+----+----+----+----+----+----+....+----+------+....+------+
|
||||
- * 1 1 2 4 variable 1 variable
|
||||
+ * 1 1 2 4 variable 1 variable 1
|
||||
*/
|
||||
-#define SOCKS4_CONN_MSG_LEN (9 + SOCKS4_MAX_LEN * 2)
|
||||
+#define SOCKS4_CONN_MSG_LEN (10 + SOCKS4_MAX_LEN * 2)
|
||||
static gint
|
||||
set_connect_msg (guint8 *msg,
|
||||
const gchar *hostname,
|
||||
--
|
||||
GitLab
|
||||
|
433
SOURCES/CVE-2025-4373.patch
Normal file
433
SOURCES/CVE-2025-4373.patch
Normal file
@ -0,0 +1,433 @@
|
||||
From 6c2178a3bc216a6cc765fc6ba3b0e6d22ce5af7e Mon Sep 17 00:00:00 2001
|
||||
From: Emmanuel Fleury <emmanuel.fleury@u-bordeaux.fr>
|
||||
Date: Mon, 4 Feb 2019 13:31:28 +0100
|
||||
Subject: [PATCH 1/3] Fixing various warnings in glib/gstring.c
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
In file included from glib/glibconfig.h:9,
|
||||
from glib/gtypes.h:32,
|
||||
from glib/gstring.h:32,
|
||||
from glib/gstring.c:37:
|
||||
glib/gstring.c: In function ‘g_string_insert_len’:
|
||||
glib/gstring.c:441:31: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
||||
g_return_val_if_fail (pos <= string->len, string);
|
||||
^~
|
||||
glib/gmacros.h:455:25: note: in definition of macro ‘G_LIKELY’
|
||||
#define G_LIKELY(expr) (expr)
|
||||
^~~~
|
||||
glib/gstring.c:441:5: note: in expansion of macro ‘g_return_val_if_fail’
|
||||
g_return_val_if_fail (pos <= string->len, string);
|
||||
^~~~~~~~~~~~~~~~~~~~
|
||||
glib/gstring.c:458:15: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
||||
if (pos < string->len)
|
||||
^
|
||||
glib/gstring.c:462:18: error: comparison of integer expressions of different signedness: ‘gsize’ {aka ‘long unsigned int’} and ‘gssize’ {aka ‘long int’} [-Werror=sign-compare]
|
||||
if (offset < pos)
|
||||
^
|
||||
In file included from glib/glibconfig.h:9,
|
||||
from glib/gtypes.h:32,
|
||||
from glib/gstring.h:32,
|
||||
from glib/gstring.c:37:
|
||||
glib/gmacros.h:351:26: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘long unsigned int’ [-Werror=sign-compare]
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
^
|
||||
glib/gstring.c:464:22: note: in expansion of macro ‘MIN’
|
||||
precount = MIN (len, pos - offset);
|
||||
^~~
|
||||
glib/gmacros.h:351:35: error: operand of ?: changes signedness from ‘gssize’ {aka ‘long int’} to ‘long unsigned int’ due to unsignedness of other operand [-Werror=sign-compare]
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
^~~
|
||||
glib/gstring.c:464:22: note: in expansion of macro ‘MIN’
|
||||
precount = MIN (len, pos - offset);
|
||||
^~~
|
||||
glib/gstring.c:469:15: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
||||
if (len > precount)
|
||||
^
|
||||
glib/gstring.c:481:15: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
||||
if (pos < string->len)
|
||||
^
|
||||
In file included from glib/glibconfig.h:9,
|
||||
from glib/gtypes.h:32,
|
||||
from glib/gstring.h:32,
|
||||
from glib/gstring.c:37:
|
||||
glib/gstring.c: In function ‘g_string_insert_c’:
|
||||
glib/gstring.c:782:31: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
||||
g_return_val_if_fail (pos <= string->len, string);
|
||||
^~
|
||||
glib/gmacros.h:455:25: note: in definition of macro ‘G_LIKELY’
|
||||
#define G_LIKELY(expr) (expr)
|
||||
^~~~
|
||||
glib/gstring.c:782:5: note: in expansion of macro ‘g_return_val_if_fail’
|
||||
g_return_val_if_fail (pos <= string->len, string);
|
||||
^~~~~~~~~~~~~~~~~~~~
|
||||
glib/gstring.c:785:11: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
||||
if (pos < string->len)
|
||||
^
|
||||
In file included from glib/glibconfig.h:9,
|
||||
from glib/gtypes.h:32,
|
||||
from glib/gstring.h:32,
|
||||
from glib/gstring.c:37:
|
||||
glib/gstring.c: In function ‘g_string_insert_unichar’:
|
||||
glib/gstring.c:857:31: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
||||
g_return_val_if_fail (pos <= string->len, string);
|
||||
^~
|
||||
glib/gmacros.h:455:25: note: in definition of macro ‘G_LIKELY’
|
||||
#define G_LIKELY(expr) (expr)
|
||||
^~~~
|
||||
glib/gstring.c:857:5: note: in expansion of macro ‘g_return_val_if_fail’
|
||||
g_return_val_if_fail (pos <= string->len, string);
|
||||
^~~~~~~~~~~~~~~~~~~~
|
||||
glib/gstring.c:860:11: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
||||
if (pos < string->len)
|
||||
^
|
||||
In file included from glib/glibconfig.h:9,
|
||||
from glib/gtypes.h:32,
|
||||
from glib/gstring.h:32,
|
||||
from glib/gstring.c:37:
|
||||
glib/gstring.c: In function ‘g_string_erase’:
|
||||
glib/gstring.c:969:29: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
||||
g_return_val_if_fail (pos <= string->len, string);
|
||||
^~
|
||||
glib/gmacros.h:455:25: note: in definition of macro ‘G_LIKELY’
|
||||
#define G_LIKELY(expr) (expr)
|
||||
^~~~
|
||||
glib/gstring.c:969:3: note: in expansion of macro ‘g_return_val_if_fail’
|
||||
g_return_val_if_fail (pos <= string->len, string);
|
||||
^~~~~~~~~~~~~~~~~~~~
|
||||
glib/gstring.c:975:39: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
||||
g_return_val_if_fail (pos + len <= string->len, string);
|
||||
^~
|
||||
glib/gmacros.h:455:25: note: in definition of macro ‘G_LIKELY’
|
||||
#define G_LIKELY(expr) (expr)
|
||||
^~~~
|
||||
glib/gstring.c:975:7: note: in expansion of macro ‘g_return_val_if_fail’
|
||||
g_return_val_if_fail (pos + len <= string->len, string);
|
||||
^~~~~~~~~~~~~~~~~~~~
|
||||
glib/gstring.c:977:21: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
||||
if (pos + len < string->len)
|
||||
^
|
||||
---
|
||||
glib/gstring.c | 82 +++++++++++++++++++++++++++++++-------------------
|
||||
1 file changed, 51 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/glib/gstring.c b/glib/gstring.c
|
||||
index 966502019..f5bfeb0ed 100644
|
||||
--- a/glib/gstring.c
|
||||
+++ b/glib/gstring.c
|
||||
@@ -426,6 +426,8 @@ g_string_insert_len (GString *string,
|
||||
const gchar *val,
|
||||
gssize len)
|
||||
{
|
||||
+ gsize len_unsigned, pos_unsigned;
|
||||
+
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
g_return_val_if_fail (len == 0 || val != NULL, string);
|
||||
|
||||
@@ -434,11 +436,15 @@ g_string_insert_len (GString *string,
|
||||
|
||||
if (len < 0)
|
||||
len = strlen (val);
|
||||
+ len_unsigned = len;
|
||||
|
||||
if (pos < 0)
|
||||
- pos = string->len;
|
||||
+ pos_unsigned = string->len;
|
||||
else
|
||||
- g_return_val_if_fail (pos <= string->len, string);
|
||||
+ {
|
||||
+ pos_unsigned = pos;
|
||||
+ g_return_val_if_fail (pos_unsigned <= string->len, string);
|
||||
+ }
|
||||
|
||||
/* Check whether val represents a substring of string.
|
||||
* This test probably violates chapter and verse of the C standards,
|
||||
@@ -450,45 +456,48 @@ g_string_insert_len (GString *string,
|
||||
gsize offset = val - string->str;
|
||||
gsize precount = 0;
|
||||
|
||||
- g_string_maybe_expand (string, len);
|
||||
+ g_string_maybe_expand (string, len_unsigned);
|
||||
val = string->str + offset;
|
||||
/* At this point, val is valid again. */
|
||||
|
||||
/* Open up space where we are going to insert. */
|
||||
- if (pos < string->len)
|
||||
- memmove (string->str + pos + len, string->str + pos, string->len - pos);
|
||||
+ if (pos_unsigned < string->len)
|
||||
+ memmove (string->str + pos_unsigned + len_unsigned,
|
||||
+ string->str + pos_unsigned, string->len - pos_unsigned);
|
||||
|
||||
/* Move the source part before the gap, if any. */
|
||||
- if (offset < pos)
|
||||
+ if (offset < pos_unsigned)
|
||||
{
|
||||
- precount = MIN (len, pos - offset);
|
||||
- memcpy (string->str + pos, val, precount);
|
||||
+ precount = MIN (len_unsigned, pos_unsigned - offset);
|
||||
+ memcpy (string->str + pos_unsigned, val, precount);
|
||||
}
|
||||
|
||||
/* Move the source part after the gap, if any. */
|
||||
- if (len > precount)
|
||||
- memcpy (string->str + pos + precount,
|
||||
- val + /* Already moved: */ precount + /* Space opened up: */ len,
|
||||
- len - precount);
|
||||
+ if (len_unsigned > precount)
|
||||
+ memcpy (string->str + pos_unsigned + precount,
|
||||
+ val + /* Already moved: */ precount +
|
||||
+ /* Space opened up: */ len_unsigned,
|
||||
+ len_unsigned - precount);
|
||||
}
|
||||
else
|
||||
{
|
||||
- g_string_maybe_expand (string, len);
|
||||
+ g_string_maybe_expand (string, len_unsigned);
|
||||
|
||||
/* If we aren't appending at the end, move a hunk
|
||||
* of the old string to the end, opening up space
|
||||
*/
|
||||
- if (pos < string->len)
|
||||
- memmove (string->str + pos + len, string->str + pos, string->len - pos);
|
||||
+ if (pos_unsigned < string->len)
|
||||
+ memmove (string->str + pos_unsigned + len_unsigned,
|
||||
+ string->str + pos_unsigned, string->len - pos_unsigned);
|
||||
|
||||
/* insert the new string */
|
||||
- if (len == 1)
|
||||
- string->str[pos] = *val;
|
||||
+ if (len_unsigned == 1)
|
||||
+ string->str[pos_unsigned] = *val;
|
||||
else
|
||||
- memcpy (string->str + pos, val, len);
|
||||
+ memcpy (string->str + pos_unsigned, val, len_unsigned);
|
||||
}
|
||||
|
||||
- string->len += len;
|
||||
+ string->len += len_unsigned;
|
||||
|
||||
string->str[string->len] = 0;
|
||||
|
||||
@@ -772,6 +781,8 @@ g_string_insert_c (GString *string,
|
||||
gssize pos,
|
||||
gchar c)
|
||||
{
|
||||
+ gsize pos_unsigned;
|
||||
+
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
|
||||
g_string_maybe_expand (string, 1);
|
||||
@@ -779,13 +790,15 @@ g_string_insert_c (GString *string,
|
||||
if (pos < 0)
|
||||
pos = string->len;
|
||||
else
|
||||
- g_return_val_if_fail (pos <= string->len, string);
|
||||
+ g_return_val_if_fail ((gsize) pos <= string->len, string);
|
||||
+ pos_unsigned = pos;
|
||||
|
||||
/* If not just an append, move the old stuff */
|
||||
- if (pos < string->len)
|
||||
- memmove (string->str + pos + 1, string->str + pos, string->len - pos);
|
||||
+ if (pos_unsigned < string->len)
|
||||
+ memmove (string->str + pos_unsigned + 1,
|
||||
+ string->str + pos_unsigned, string->len - pos_unsigned);
|
||||
|
||||
- string->str[pos] = c;
|
||||
+ string->str[pos_unsigned] = c;
|
||||
|
||||
string->len += 1;
|
||||
|
||||
@@ -854,10 +867,10 @@ g_string_insert_unichar (GString *string,
|
||||
if (pos < 0)
|
||||
pos = string->len;
|
||||
else
|
||||
- g_return_val_if_fail (pos <= string->len, string);
|
||||
+ g_return_val_if_fail ((gsize) pos <= string->len, string);
|
||||
|
||||
/* If not just an append, move the old stuff */
|
||||
- if (pos < string->len)
|
||||
+ if ((gsize) pos < string->len)
|
||||
memmove (string->str + pos + charlen, string->str + pos, string->len - pos);
|
||||
|
||||
dest = string->str + pos;
|
||||
@@ -964,21 +977,28 @@ g_string_erase (GString *string,
|
||||
gssize pos,
|
||||
gssize len)
|
||||
{
|
||||
+ gsize len_unsigned, pos_unsigned;
|
||||
+
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
g_return_val_if_fail (pos >= 0, string);
|
||||
- g_return_val_if_fail (pos <= string->len, string);
|
||||
+ pos_unsigned = pos;
|
||||
+
|
||||
+ g_return_val_if_fail (pos_unsigned <= string->len, string);
|
||||
|
||||
if (len < 0)
|
||||
- len = string->len - pos;
|
||||
+ len_unsigned = string->len - pos_unsigned;
|
||||
else
|
||||
{
|
||||
- g_return_val_if_fail (pos + len <= string->len, string);
|
||||
+ len_unsigned = len;
|
||||
+ g_return_val_if_fail (pos_unsigned + len_unsigned <= string->len, string);
|
||||
|
||||
- if (pos + len < string->len)
|
||||
- memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
|
||||
+ if (pos_unsigned + len_unsigned < string->len)
|
||||
+ memmove (string->str + pos_unsigned,
|
||||
+ string->str + pos_unsigned + len_unsigned,
|
||||
+ string->len - (pos_unsigned + len_unsigned));
|
||||
}
|
||||
|
||||
- string->len -= len;
|
||||
+ string->len -= len_unsigned;
|
||||
|
||||
string->str[string->len] = 0;
|
||||
|
||||
--
|
||||
2.50.0
|
||||
|
||||
|
||||
From 101afb01778659cb7051b3cb33d55dc965c8dc7e Mon Sep 17 00:00:00 2001
|
||||
From: Michael Catanzaro <mcatanzaro@redhat.com>
|
||||
Date: Thu, 10 Apr 2025 10:57:20 -0500
|
||||
Subject: [PATCH 2/3] gstring: carefully handle gssize parameters
|
||||
|
||||
Wherever we use gssize to allow passing -1, we need to ensure we don't
|
||||
overflow the value by assigning a gsize to it without checking if the
|
||||
size exceeds the maximum gssize. The safest way to do this is to just
|
||||
use normal gsize everywhere instead and use gssize only for the
|
||||
parameter.
|
||||
|
||||
Our computers don't have enough RAM to write tests for this. I tried
|
||||
forcing string->len to high values for test purposes, but this isn't
|
||||
valid and will just cause out of bounds reads/writes due to
|
||||
string->allocated_len being unexpectedly small, so I don't think we can
|
||||
test this easily.
|
||||
---
|
||||
glib/gstring.c | 36 +++++++++++++++++++++++-------------
|
||||
1 file changed, 23 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/glib/gstring.c b/glib/gstring.c
|
||||
index f5bfeb0ed..84a98da25 100644
|
||||
--- a/glib/gstring.c
|
||||
+++ b/glib/gstring.c
|
||||
@@ -435,8 +435,9 @@ g_string_insert_len (GString *string,
|
||||
return string;
|
||||
|
||||
if (len < 0)
|
||||
- len = strlen (val);
|
||||
- len_unsigned = len;
|
||||
+ len_unsigned = strlen (val);
|
||||
+ else
|
||||
+ len_unsigned = len;
|
||||
|
||||
if (pos < 0)
|
||||
pos_unsigned = string->len;
|
||||
@@ -788,10 +789,12 @@ g_string_insert_c (GString *string,
|
||||
g_string_maybe_expand (string, 1);
|
||||
|
||||
if (pos < 0)
|
||||
- pos = string->len;
|
||||
+ pos_unsigned = string->len;
|
||||
else
|
||||
- g_return_val_if_fail ((gsize) pos <= string->len, string);
|
||||
- pos_unsigned = pos;
|
||||
+ {
|
||||
+ pos_unsigned = pos;
|
||||
+ g_return_val_if_fail (pos_unsigned <= string->len, string);
|
||||
+ }
|
||||
|
||||
/* If not just an append, move the old stuff */
|
||||
if (pos_unsigned < string->len)
|
||||
@@ -824,6 +827,7 @@ g_string_insert_unichar (GString *string,
|
||||
gssize pos,
|
||||
gunichar wc)
|
||||
{
|
||||
+ gsize pos_unsigned;
|
||||
gint charlen, first, i;
|
||||
gchar *dest;
|
||||
|
||||
@@ -865,15 +869,18 @@ g_string_insert_unichar (GString *string,
|
||||
g_string_maybe_expand (string, charlen);
|
||||
|
||||
if (pos < 0)
|
||||
- pos = string->len;
|
||||
+ pos_unsigned = string->len;
|
||||
else
|
||||
- g_return_val_if_fail ((gsize) pos <= string->len, string);
|
||||
+ {
|
||||
+ pos_unsigned = pos;
|
||||
+ g_return_val_if_fail (pos_unsigned <= string->len, string);
|
||||
+ }
|
||||
|
||||
/* If not just an append, move the old stuff */
|
||||
- if ((gsize) pos < string->len)
|
||||
- memmove (string->str + pos + charlen, string->str + pos, string->len - pos);
|
||||
+ if (pos_unsigned < string->len)
|
||||
+ memmove (string->str + pos_unsigned + charlen, string->str + pos_unsigned, string->len - pos_unsigned);
|
||||
|
||||
- dest = string->str + pos;
|
||||
+ dest = string->str + pos_unsigned;
|
||||
/* Code copied from g_unichar_to_utf() */
|
||||
for (i = charlen - 1; i > 0; --i)
|
||||
{
|
||||
@@ -931,6 +938,7 @@ g_string_overwrite_len (GString *string,
|
||||
const gchar *val,
|
||||
gssize len)
|
||||
{
|
||||
+ gssize len_unsigned;
|
||||
gsize end;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
@@ -942,14 +950,16 @@ g_string_overwrite_len (GString *string,
|
||||
g_return_val_if_fail (pos <= string->len, string);
|
||||
|
||||
if (len < 0)
|
||||
- len = strlen (val);
|
||||
+ len_unsigned = strlen (val);
|
||||
+ else
|
||||
+ len_unsigned = len;
|
||||
|
||||
- end = pos + len;
|
||||
+ end = pos + len_unsigned;
|
||||
|
||||
if (end > string->len)
|
||||
g_string_maybe_expand (string, end - string->len);
|
||||
|
||||
- memcpy (string->str + pos, val, len);
|
||||
+ memcpy (string->str + pos, val, len_unsigned);
|
||||
|
||||
if (end > string->len)
|
||||
{
|
||||
--
|
||||
2.50.0
|
||||
|
||||
|
||||
From 789c240db9738cae37ee77f7e135e5dbc39ab3ca Mon Sep 17 00:00:00 2001
|
||||
From: Peter Bloomfield <peterbloomfield@bellsouth.net>
|
||||
Date: Fri, 11 Apr 2025 05:52:33 +0000
|
||||
Subject: [PATCH 3/3] gstring: Make len_unsigned unsigned
|
||||
|
||||
---
|
||||
glib/gstring.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/glib/gstring.c b/glib/gstring.c
|
||||
index 84a98da25..7379517f5 100644
|
||||
--- a/glib/gstring.c
|
||||
+++ b/glib/gstring.c
|
||||
@@ -938,7 +938,7 @@ g_string_overwrite_len (GString *string,
|
||||
const gchar *val,
|
||||
gssize len)
|
||||
{
|
||||
- gssize len_unsigned;
|
||||
+ gsize len_unsigned;
|
||||
gsize end;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
--
|
||||
2.50.0
|
||||
|
126
SOURCES/gdatetime-test.patch
Normal file
126
SOURCES/gdatetime-test.patch
Normal file
@ -0,0 +1,126 @@
|
||||
From a07f759373d888c837a780cb93f14542b029e19c Mon Sep 17 00:00:00 2001
|
||||
From: "Rebecca N. Palmer" <rebecca_palmer@zoho.com>
|
||||
Date: Fri, 11 Oct 2024 09:38:52 +0100
|
||||
Subject: [PATCH 1/2] gdatetime test: Do not assume PST8PDT was always exactly
|
||||
-8/-7
|
||||
|
||||
In newer tzdata, it is an alias for America/Los_Angeles, which has a
|
||||
slightly different meaning: DST did not exist there before 1883. As a
|
||||
result, we can no longer hard-code the knowledge that interval 0 is
|
||||
standard time and interval 1 is summer time, and instead we need to look
|
||||
up the correct intervals from known timestamps.
|
||||
|
||||
Resolves: https://gitlab.gnome.org/GNOME/glib/-/issues/3502
|
||||
Bug-Debian: https://bugs.debian.org/1084190
|
||||
[smcv: expand commit message, fix whitespace]
|
||||
Signed-off-by: Simon McVittie <smcv@debian.org>
|
||||
---
|
||||
glib/tests/gdatetime.c | 23 +++++++++++++++++------
|
||||
1 file changed, 17 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c
|
||||
index 5a2190d5f..80098bab3 100644
|
||||
--- a/glib/tests/gdatetime.c
|
||||
+++ b/glib/tests/gdatetime.c
|
||||
@@ -2096,6 +2096,7 @@ test_posix_parse (void)
|
||||
{
|
||||
GTimeZone *tz;
|
||||
GDateTime *gdt1, *gdt2;
|
||||
+ gint i1, i2;
|
||||
|
||||
tz = g_time_zone_new ("PST");
|
||||
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "UTC");
|
||||
@@ -2111,14 +2112,24 @@ test_posix_parse (void)
|
||||
|
||||
/* This fails rules_from_identifier on Unix (though not on Windows)
|
||||
* but passes anyway because PST8PDT is a zone name.
|
||||
+ *
|
||||
+ * Intervals i1 and i2 (rather than 0 and 1) are needed because in
|
||||
+ * recent tzdata, PST8PDT may be an alias for America/Los_Angeles,
|
||||
+ * and hence be aware that DST has not always existed.
|
||||
+ * https://bugs.debian.org/1084190
|
||||
*/
|
||||
tz = g_time_zone_new ("PST8PDT");
|
||||
- g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "PST");
|
||||
- g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, - 8 * 3600);
|
||||
- g_assert (!g_time_zone_is_dst (tz, 0));
|
||||
- g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 1), ==, "PDT");
|
||||
- g_assert_cmpint (g_time_zone_get_offset (tz, 1), ==,- 7 * 3600);
|
||||
- g_assert (g_time_zone_is_dst (tz, 1));
|
||||
+ g_assert_nonnull (tz);
|
||||
+ /* a date in winter = non-DST */
|
||||
+ i1 = g_time_zone_find_interval (tz, G_TIME_TYPE_STANDARD, 0);
|
||||
+ /* approximately 6 months in seconds, i.e. a date in summer = DST */
|
||||
+ i2 = g_time_zone_find_interval (tz, G_TIME_TYPE_DAYLIGHT, 15000000);
|
||||
+ g_assert_cmpstr (g_time_zone_get_abbreviation (tz, i1), ==, "PST");
|
||||
+ g_assert_cmpint (g_time_zone_get_offset (tz, i1), ==, - 8 * 3600);
|
||||
+ g_assert (!g_time_zone_is_dst (tz, i1));
|
||||
+ g_assert_cmpstr (g_time_zone_get_abbreviation (tz, i2), ==, "PDT");
|
||||
+ g_assert_cmpint (g_time_zone_get_offset (tz, i2), ==,- 7 * 3600);
|
||||
+ g_assert (g_time_zone_is_dst (tz, i2));
|
||||
g_time_zone_unref (tz);
|
||||
|
||||
tz = g_time_zone_new ("PST8PDT6:32:15");
|
||||
--
|
||||
2.50.0
|
||||
|
||||
|
||||
From d1e564d6d4f478c9e0b163763ed2b199dfafd500 Mon Sep 17 00:00:00 2001
|
||||
From: Simon McVittie <smcv@debian.org>
|
||||
Date: Fri, 18 Oct 2024 11:03:19 +0100
|
||||
Subject: [PATCH 2/2] gdatetime test: Try to make PST8PDT test more obviously
|
||||
correct
|
||||
|
||||
Instead of using timestamp 0 as a magic number (in this case interpreted
|
||||
as 1970-01-01T00:00:00-08:00), calculate a timestamp from a recent
|
||||
year/month/day in winter, in this case 2024-01-01T00:00:00-08:00.
|
||||
|
||||
Similarly, instead of using a timestamp 15 million seconds later
|
||||
(1970-06-23T15:40:00-07:00), calculate a timestamp from a recent
|
||||
year/month/day in summer, in this case 2024-07-01T00:00:00-07:00.
|
||||
|
||||
Signed-off-by: Simon McVittie <smcv@debian.org>
|
||||
---
|
||||
glib/tests/gdatetime.c | 15 +++++++--------
|
||||
1 file changed, 7 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c
|
||||
index 80098bab3..d0755e722 100644
|
||||
--- a/glib/tests/gdatetime.c
|
||||
+++ b/glib/tests/gdatetime.c
|
||||
@@ -2112,18 +2112,15 @@ test_posix_parse (void)
|
||||
|
||||
/* This fails rules_from_identifier on Unix (though not on Windows)
|
||||
* but passes anyway because PST8PDT is a zone name.
|
||||
- *
|
||||
- * Intervals i1 and i2 (rather than 0 and 1) are needed because in
|
||||
- * recent tzdata, PST8PDT may be an alias for America/Los_Angeles,
|
||||
- * and hence be aware that DST has not always existed.
|
||||
- * https://bugs.debian.org/1084190
|
||||
*/
|
||||
tz = g_time_zone_new ("PST8PDT");
|
||||
g_assert_nonnull (tz);
|
||||
/* a date in winter = non-DST */
|
||||
- i1 = g_time_zone_find_interval (tz, G_TIME_TYPE_STANDARD, 0);
|
||||
- /* approximately 6 months in seconds, i.e. a date in summer = DST */
|
||||
- i2 = g_time_zone_find_interval (tz, G_TIME_TYPE_DAYLIGHT, 15000000);
|
||||
+ gdt1 = g_date_time_new (tz, 2024, 1, 1, 0, 0, 0);
|
||||
+ i1 = g_time_zone_find_interval (tz, G_TIME_TYPE_STANDARD, g_date_time_to_unix (gdt1));
|
||||
+ /* a date in summer = DST */
|
||||
+ gdt2 = g_date_time_new (tz, 2024, 7, 1, 0, 0, 0);
|
||||
+ i2 = g_time_zone_find_interval (tz, G_TIME_TYPE_DAYLIGHT, g_date_time_to_unix (gdt2));
|
||||
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, i1), ==, "PST");
|
||||
g_assert_cmpint (g_time_zone_get_offset (tz, i1), ==, - 8 * 3600);
|
||||
g_assert (!g_time_zone_is_dst (tz, i1));
|
||||
@@ -2131,6 +2128,8 @@ test_posix_parse (void)
|
||||
g_assert_cmpint (g_time_zone_get_offset (tz, i2), ==,- 7 * 3600);
|
||||
g_assert (g_time_zone_is_dst (tz, i2));
|
||||
g_time_zone_unref (tz);
|
||||
+ g_date_time_unref (gdt1);
|
||||
+ g_date_time_unref (gdt2);
|
||||
|
||||
tz = g_time_zone_new ("PST8PDT6:32:15");
|
||||
#ifdef G_OS_WIN32
|
||||
--
|
||||
2.50.0
|
||||
|
401
SOURCES/gdbus-conflict-reduction.patch
Normal file
401
SOURCES/gdbus-conflict-reduction.patch
Normal file
@ -0,0 +1,401 @@
|
||||
From b43d2e06834a9779801f9a68904ae73a26578f01 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <withnall@endlessm.com>
|
||||
Date: Sat, 21 Sep 2019 10:45:36 +0200
|
||||
Subject: [PATCH 1/2] gatomic: Add various casts to use of g_atomic_*()s to fix
|
||||
warnings
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
When compiling GLib with `-Wsign-conversion`, we get various warnings
|
||||
about the atomic calls. A lot of these were fixed by
|
||||
3ad375a629c91a27d0165a31f0ed298fd553de0a, but some remain. Fix them by
|
||||
adding appropriate casts at the call sites.
|
||||
|
||||
Note that `g_atomic_int_{and,or,xor}()` actually all operate on `guint`s
|
||||
rather than `gint`s (which is what the rest of the `g_atomic_int_*()`
|
||||
functions operate on). I can’t find any written reasoning for this, but
|
||||
assume that it’s because signedness is irrelevant when you’re using an
|
||||
integer as a bit field. It’s unfortunate that they’re named a
|
||||
`g_atomic_int_*()` rather than `g_atomic_uint_*()` functions.
|
||||
|
||||
Tested by compiling GLib as:
|
||||
```
|
||||
CFLAGS=-Wsign-conversion jhbuild make -ac |& grep atomic
|
||||
```
|
||||
|
||||
I’m not going to add `-Wsign-conversion` to the set of default warnings
|
||||
for building GLib, because it mostly produces false positives throughout
|
||||
the rest of GLib.
|
||||
|
||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
||||
|
||||
Fixes: #1565
|
||||
---
|
||||
gio/gdbusconnection.c | 8 ++++----
|
||||
gio/gdbusnamewatching.c | 4 ++--
|
||||
gio/tests/gdbus-threading.c | 2 +-
|
||||
glib/gbitlock.c | 2 +-
|
||||
glib/gquark.c | 2 +-
|
||||
glib/gthread-posix.c | 2 +-
|
||||
glib/gthreadpool.c | 10 +++++-----
|
||||
glib/tests/atomic.c | 20 ++++++++++----------
|
||||
8 files changed, 25 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
||||
index 117c8df35..1c1f0cf3d 100644
|
||||
--- a/gio/gdbusconnection.c
|
||||
+++ b/gio/gdbusconnection.c
|
||||
@@ -3127,7 +3127,7 @@ g_dbus_connection_add_filter (GDBusConnection *connection,
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
data = g_new0 (FilterData, 1);
|
||||
- data->id = g_atomic_int_add (&_global_filter_id, 1); /* TODO: overflow etc. */
|
||||
+ data->id = (guint) g_atomic_int_add (&_global_filter_id, 1); /* TODO: overflow etc. */
|
||||
data->ref_count = 1;
|
||||
data->filter_function = filter_function;
|
||||
data->user_data = user_data;
|
||||
@@ -3482,7 +3482,7 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
||||
subscriber.callback = callback;
|
||||
subscriber.user_data = user_data;
|
||||
subscriber.user_data_free_func = user_data_free_func;
|
||||
- subscriber.id = g_atomic_int_add (&_global_subscriber_id, 1); /* TODO: overflow etc. */
|
||||
+ subscriber.id = (guint) g_atomic_int_add (&_global_subscriber_id, 1); /* TODO: overflow etc. */
|
||||
subscriber.context = g_main_context_ref_thread_default ();
|
||||
|
||||
/* see if we've already have this rule */
|
||||
@@ -5172,7 +5172,7 @@ g_dbus_connection_register_object (GDBusConnection *connection,
|
||||
}
|
||||
|
||||
ei = g_new0 (ExportedInterface, 1);
|
||||
- ei->id = g_atomic_int_add (&_global_registration_id, 1); /* TODO: overflow etc. */
|
||||
+ ei->id = (guint) g_atomic_int_add (&_global_registration_id, 1); /* TODO: overflow etc. */
|
||||
ei->eo = eo;
|
||||
ei->user_data = user_data;
|
||||
ei->user_data_free_func = user_data_free_func;
|
||||
@@ -6832,7 +6832,7 @@ g_dbus_connection_register_subtree (GDBusConnection *connection,
|
||||
|
||||
es->vtable = _g_dbus_subtree_vtable_copy (vtable);
|
||||
es->flags = flags;
|
||||
- es->id = g_atomic_int_add (&_global_subtree_registration_id, 1); /* TODO: overflow etc. */
|
||||
+ es->id = (guint) g_atomic_int_add (&_global_subtree_registration_id, 1); /* TODO: overflow etc. */
|
||||
es->user_data = user_data;
|
||||
es->user_data_free_func = user_data_free_func;
|
||||
es->context = g_main_context_ref_thread_default ();
|
||||
diff --git a/gio/gdbusnamewatching.c b/gio/gdbusnamewatching.c
|
||||
index dad8e75ec..01ee6e762 100644
|
||||
--- a/gio/gdbusnamewatching.c
|
||||
+++ b/gio/gdbusnamewatching.c
|
||||
@@ -603,7 +603,7 @@ g_bus_watch_name (GBusType bus_type,
|
||||
|
||||
client = g_new0 (Client, 1);
|
||||
client->ref_count = 1;
|
||||
- client->id = g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */
|
||||
+ client->id = (guint) g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */
|
||||
client->name = g_strdup (name);
|
||||
client->flags = flags;
|
||||
client->name_appeared_handler = name_appeared_handler;
|
||||
@@ -665,7 +665,7 @@ guint g_bus_watch_name_on_connection (GDBusConnection *connection,
|
||||
|
||||
client = g_new0 (Client, 1);
|
||||
client->ref_count = 1;
|
||||
- client->id = g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */
|
||||
+ client->id = (guint) g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */
|
||||
client->name = g_strdup (name);
|
||||
client->flags = flags;
|
||||
client->name_appeared_handler = name_appeared_handler;
|
||||
diff --git a/gio/tests/gdbus-threading.c b/gio/tests/gdbus-threading.c
|
||||
index 3e4dc92e5..13ff15bab 100644
|
||||
--- a/gio/tests/gdbus-threading.c
|
||||
+++ b/gio/tests/gdbus-threading.c
|
||||
@@ -514,7 +514,7 @@ test_threaded_singleton (void)
|
||||
/* We want to be the last ref, so let it finish setting up */
|
||||
for (j = 0; j < 100; j++)
|
||||
{
|
||||
- guint r = g_atomic_int_get (&G_OBJECT (c)->ref_count);
|
||||
+ guint r = (guint) g_atomic_int_get (&G_OBJECT (c)->ref_count);
|
||||
|
||||
if (r == 1)
|
||||
break;
|
||||
diff --git a/glib/gbitlock.c b/glib/gbitlock.c
|
||||
index 46e5f7d06..23024d08c 100644
|
||||
--- a/glib/gbitlock.c
|
||||
+++ b/glib/gbitlock.c
|
||||
@@ -224,7 +224,7 @@ g_bit_lock (volatile gint *address,
|
||||
guint mask = 1u << lock_bit;
|
||||
guint v;
|
||||
|
||||
- v = g_atomic_int_get (address);
|
||||
+ v = (guint) g_atomic_int_get (address);
|
||||
if (v & mask)
|
||||
{
|
||||
guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended);
|
||||
diff --git a/glib/gquark.c b/glib/gquark.c
|
||||
index c4d12b870..df12ff69a 100644
|
||||
--- a/glib/gquark.c
|
||||
+++ b/glib/gquark.c
|
||||
@@ -262,7 +262,7 @@ g_quark_to_string (GQuark quark)
|
||||
gchar **strings;
|
||||
gint seq_id;
|
||||
|
||||
- seq_id = g_atomic_int_get (&quark_seq_id);
|
||||
+ seq_id = (guint) g_atomic_int_get (&quark_seq_id);
|
||||
strings = g_atomic_pointer_get (&quarks);
|
||||
|
||||
if (quark < seq_id)
|
||||
diff --git a/glib/gthread-posix.c b/glib/gthread-posix.c
|
||||
index 5fff51477..aca9208cc 100644
|
||||
--- a/glib/gthread-posix.c
|
||||
+++ b/glib/gthread-posix.c
|
||||
@@ -1396,7 +1396,7 @@ void
|
||||
g_cond_wait (GCond *cond,
|
||||
GMutex *mutex)
|
||||
{
|
||||
- guint sampled = g_atomic_int_get (&cond->i[0]);
|
||||
+ guint sampled = (guint) g_atomic_int_get (&cond->i[0]);
|
||||
|
||||
g_mutex_unlock (mutex);
|
||||
syscall (__NR_futex, &cond->i[0], (gsize) FUTEX_WAIT_PRIVATE, (gsize) sampled, NULL);
|
||||
diff --git a/glib/gthreadpool.c b/glib/gthreadpool.c
|
||||
index dd7289370..7d75245b0 100644
|
||||
--- a/glib/gthreadpool.c
|
||||
+++ b/glib/gthreadpool.c
|
||||
@@ -145,7 +145,7 @@ g_thread_pool_wait_for_new_pool (void)
|
||||
gint last_wakeup_thread_serial;
|
||||
gboolean have_relayed_thread_marker = FALSE;
|
||||
|
||||
- local_max_unused_threads = g_atomic_int_get (&max_unused_threads);
|
||||
+ local_max_unused_threads = (guint) g_atomic_int_get (&max_unused_threads);
|
||||
local_max_idle_time = g_atomic_int_get (&max_idle_time);
|
||||
last_wakeup_thread_serial = g_atomic_int_get (&wakeup_thread_serial);
|
||||
|
||||
@@ -209,7 +209,7 @@ g_thread_pool_wait_for_new_pool (void)
|
||||
DEBUG_MSG (("thread %p updating to new limits.",
|
||||
g_thread_self ()));
|
||||
|
||||
- local_max_unused_threads = g_atomic_int_get (&max_unused_threads);
|
||||
+ local_max_unused_threads = (guint) g_atomic_int_get (&max_unused_threads);
|
||||
local_max_idle_time = g_atomic_int_get (&max_idle_time);
|
||||
last_wakeup_thread_serial = local_wakeup_thread_serial;
|
||||
|
||||
@@ -893,7 +893,7 @@ g_thread_pool_get_max_unused_threads (void)
|
||||
guint
|
||||
g_thread_pool_get_num_unused_threads (void)
|
||||
{
|
||||
- return g_atomic_int_get (&unused_threads);
|
||||
+ return (guint) g_atomic_int_get (&unused_threads);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1016,7 +1016,7 @@ g_thread_pool_set_max_idle_time (guint interval)
|
||||
|
||||
g_atomic_int_set (&max_idle_time, interval);
|
||||
|
||||
- i = g_atomic_int_get (&unused_threads);
|
||||
+ i = (guint) g_atomic_int_get (&unused_threads);
|
||||
if (i > 0)
|
||||
{
|
||||
g_atomic_int_inc (&wakeup_thread_serial);
|
||||
@@ -1052,5 +1052,5 @@ g_thread_pool_set_max_idle_time (guint interval)
|
||||
guint
|
||||
g_thread_pool_get_max_idle_time (void)
|
||||
{
|
||||
- return g_atomic_int_get (&max_idle_time);
|
||||
+ return (guint) g_atomic_int_get (&max_idle_time);
|
||||
}
|
||||
diff --git a/glib/tests/atomic.c b/glib/tests/atomic.c
|
||||
index 35fa705a4..856df12d2 100644
|
||||
--- a/glib/tests/atomic.c
|
||||
+++ b/glib/tests/atomic.c
|
||||
@@ -27,7 +27,7 @@ test_types (void)
|
||||
cspp = &csp;
|
||||
|
||||
g_atomic_int_set (&u, 5);
|
||||
- u2 = g_atomic_int_get (&u);
|
||||
+ u2 = (guint) g_atomic_int_get (&u);
|
||||
g_assert_cmpint (u2, ==, 5);
|
||||
res = g_atomic_int_compare_and_exchange (&u, 6, 7);
|
||||
g_assert (!res);
|
||||
@@ -62,13 +62,13 @@ test_types (void)
|
||||
res = g_atomic_int_dec_and_test (&s);
|
||||
g_assert (!res);
|
||||
g_assert_cmpint (s, ==, 6);
|
||||
- s2 = g_atomic_int_and (&s, 5);
|
||||
+ s2 = (gint) g_atomic_int_and (&s, 5);
|
||||
g_assert_cmpint (s2, ==, 6);
|
||||
g_assert_cmpint (s, ==, 4);
|
||||
- s2 = g_atomic_int_or (&s, 8);
|
||||
+ s2 = (gint) g_atomic_int_or (&s, 8);
|
||||
g_assert_cmpint (s2, ==, 4);
|
||||
g_assert_cmpint (s, ==, 12);
|
||||
- s2 = g_atomic_int_xor (&s, 4);
|
||||
+ s2 = (gint) g_atomic_int_xor (&s, 4);
|
||||
g_assert_cmpint (s2, ==, 12);
|
||||
g_assert_cmpint (s, ==, 8);
|
||||
|
||||
@@ -92,7 +92,7 @@ test_types (void)
|
||||
res = g_atomic_pointer_compare_and_exchange (&gs, 0, 0);
|
||||
g_assert (res);
|
||||
g_assert (gs == 0);
|
||||
- gs2 = g_atomic_pointer_add (&gs, 5);
|
||||
+ gs2 = (gsize) g_atomic_pointer_add (&gs, 5);
|
||||
g_assert (gs2 == 0);
|
||||
g_assert (gs == 5);
|
||||
gs2 = g_atomic_pointer_and (&gs, 6);
|
||||
@@ -127,7 +127,7 @@ test_types (void)
|
||||
#undef g_atomic_pointer_xor
|
||||
|
||||
g_atomic_int_set ((gint*)&u, 5);
|
||||
- u2 = g_atomic_int_get ((gint*)&u);
|
||||
+ u2 = (guint) g_atomic_int_get ((gint*)&u);
|
||||
g_assert_cmpint (u2, ==, 5);
|
||||
res = g_atomic_int_compare_and_exchange ((gint*)&u, 6, 7);
|
||||
g_assert (!res);
|
||||
@@ -161,13 +161,13 @@ test_types (void)
|
||||
res = g_atomic_int_dec_and_test (&s);
|
||||
g_assert (!res);
|
||||
g_assert_cmpint (s, ==, 6);
|
||||
- s2 = g_atomic_int_and ((guint*)&s, 5);
|
||||
+ s2 = (gint) g_atomic_int_and ((guint*)&s, 5);
|
||||
g_assert_cmpint (s2, ==, 6);
|
||||
g_assert_cmpint (s, ==, 4);
|
||||
- s2 = g_atomic_int_or ((guint*)&s, 8);
|
||||
+ s2 = (gint) g_atomic_int_or ((guint*)&s, 8);
|
||||
g_assert_cmpint (s2, ==, 4);
|
||||
g_assert_cmpint (s, ==, 12);
|
||||
- s2 = g_atomic_int_xor ((guint*)&s, 4);
|
||||
+ s2 = (gint) g_atomic_int_xor ((guint*)&s, 4);
|
||||
g_assert_cmpint (s2, ==, 12);
|
||||
g_assert_cmpint (s, ==, 8);
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
@@ -196,7 +196,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
res = g_atomic_pointer_compare_and_exchange (&gs, 0, 0);
|
||||
g_assert (res);
|
||||
g_assert (gs == 0);
|
||||
- gs2 = g_atomic_pointer_add (&gs, 5);
|
||||
+ gs2 = (gsize) g_atomic_pointer_add (&gs, 5);
|
||||
g_assert (gs2 == 0);
|
||||
g_assert (gs == 5);
|
||||
gs2 = g_atomic_pointer_and (&gs, 6);
|
||||
--
|
||||
2.50.0
|
||||
|
||||
|
||||
From 5d6ced6a7fc6dbbc891992a7d16cd465f2ff1290 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@endlessos.org>
|
||||
Date: Wed, 22 Feb 2023 12:19:16 +0000
|
||||
Subject: [PATCH 2/2] gdbusconnection: Rearrange refcount handling of
|
||||
map_method_serial_to_task
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
It already implicitly held a strong ref on its `GTask` values, but
|
||||
didn’t have a free function set so that they would be automatically
|
||||
unreffed on removal from the map.
|
||||
|
||||
This meant that the functions handling removals from the map,
|
||||
`on_worker_closed()` (via `cancel_method_on_close()`) and
|
||||
`send_message_with_reply_cleanup()` had to call unref once more than
|
||||
they would otherwise.
|
||||
|
||||
In `send_message_with_reply_cleanup()`, this behaviour depended on
|
||||
whether it was called with `remove == TRUE`. If not, it was `(transfer
|
||||
none)` not `(transfer full)`. This led to bugs in its callers.
|
||||
|
||||
For example, this led to a direct leak in `cancel_method_on_close()`, as
|
||||
it needed to remove tasks from `map_method_serial_to_task`, but called
|
||||
`send_message_with_reply_cleanup(remove = FALSE)` and erroneously didn’t
|
||||
call unref an additional time.
|
||||
|
||||
Try and simplify it all by setting a `GDestroyNotify` on
|
||||
`map_method_serial_to_task`’s values, and making the refcount handling
|
||||
of `send_message_with_reply_cleanup()` not be conditional on its
|
||||
arguments.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
|
||||
|
||||
Helps: #1264
|
||||
---
|
||||
gio/gdbusconnection.c | 18 ++++++++++--------
|
||||
1 file changed, 10 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
||||
index 1c1f0cf3d..63f37ca4b 100644
|
||||
--- a/gio/gdbusconnection.c
|
||||
+++ b/gio/gdbusconnection.c
|
||||
@@ -433,7 +433,7 @@ struct _GDBusConnection
|
||||
GDBusConnectionFlags flags;
|
||||
|
||||
/* Map used for managing method replies, protected by @lock */
|
||||
- GHashTable *map_method_serial_to_task; /* guint32 -> GTask* */
|
||||
+ GHashTable *map_method_serial_to_task; /* guint32 -> owned GTask* */
|
||||
|
||||
/* Maps used for managing signal subscription, protected by @lock */
|
||||
GHashTable *map_rule_to_signal_data; /* match rule (gchar*) -> SignalData */
|
||||
@@ -1067,7 +1067,7 @@ g_dbus_connection_init (GDBusConnection *connection)
|
||||
g_mutex_init (&connection->lock);
|
||||
g_mutex_init (&connection->init_lock);
|
||||
|
||||
- connection->map_method_serial_to_task = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
+ connection->map_method_serial_to_task = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
|
||||
|
||||
connection->map_rule_to_signal_data = g_hash_table_new (g_str_hash,
|
||||
g_str_equal);
|
||||
@@ -1759,7 +1759,7 @@ send_message_data_free (SendMessageData *data)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
-/* can be called from any thread with lock held; @task is (transfer full) */
|
||||
+/* can be called from any thread with lock held; @task is (transfer none) */
|
||||
static void
|
||||
send_message_with_reply_cleanup (GTask *task, gboolean remove)
|
||||
{
|
||||
@@ -1789,13 +1789,11 @@ send_message_with_reply_cleanup (GTask *task, gboolean remove)
|
||||
GUINT_TO_POINTER (data->serial));
|
||||
g_warn_if_fail (removed);
|
||||
}
|
||||
-
|
||||
- g_object_unref (task);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
-/* Called from GDBus worker thread with lock held; @task is (transfer full). */
|
||||
+/* Called from GDBus worker thread with lock held; @task is (transfer none). */
|
||||
static void
|
||||
send_message_data_deliver_reply_unlocked (GTask *task,
|
||||
GDBusMessage *reply)
|
||||
@@ -1813,7 +1811,7 @@ send_message_data_deliver_reply_unlocked (GTask *task,
|
||||
;
|
||||
}
|
||||
|
||||
-/* Called from a user thread, lock is not held */
|
||||
+/* Called from a user thread, lock is not held; @task is (transfer none) */
|
||||
static void
|
||||
send_message_data_deliver_error (GTask *task,
|
||||
GQuark domain,
|
||||
@@ -1830,7 +1828,10 @@ send_message_data_deliver_error (GTask *task,
|
||||
return;
|
||||
}
|
||||
|
||||
+ /* Hold a ref on @task as send_message_with_reply_cleanup() will remove it
|
||||
+ * from the task map and could end up dropping the last reference */
|
||||
g_object_ref (task);
|
||||
+
|
||||
send_message_with_reply_cleanup (task, TRUE);
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
@@ -2363,7 +2364,8 @@ on_worker_message_about_to_be_sent (GDBusWorker *worker,
|
||||
return message;
|
||||
}
|
||||
|
||||
-/* called with connection lock held, in GDBusWorker thread */
|
||||
+/* called with connection lock held, in GDBusWorker thread
|
||||
+ * @key, @value and @user_data are (transfer none) */
|
||||
static gboolean
|
||||
cancel_method_on_close (gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
--
|
||||
2.50.0
|
||||
|
780
SOURCES/gdbus-signal-race.patch
Normal file
780
SOURCES/gdbus-signal-race.patch
Normal file
@ -0,0 +1,780 @@
|
||||
From c53784092c2d69c4a1d916bb22235ffb8f0b5bad Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <withnall@endlessm.com>
|
||||
Date: Fri, 17 Jan 2020 16:11:06 +0000
|
||||
Subject: [PATCH 1/5] gdbusconnection: Allocate SignalSubscriber structs
|
||||
individually
|
||||
|
||||
The `SignalSubscriber` structs contain the callback and `user_data` of each
|
||||
subscriber to a signal, along with the `guint id` token held by that
|
||||
subscriber to identify their subscription. There are one or more
|
||||
`SignalSubscriber` structs for a given signal match rule, which is
|
||||
represented as a `SignalData` struct.
|
||||
|
||||
Previously, the `SignalSubscriber` structs were stored in a `GArray` in
|
||||
the `SignalData` struct, to reduce the number of allocations needed
|
||||
when subscribing to a signal.
|
||||
|
||||
However, this means that a `SignalSubscriber` struct cannot have a
|
||||
lifetime which exceeds the `SignalData` which contains it. In order to
|
||||
fix the race in #978, one thread needs to be able to unsubscribe from a
|
||||
signal (destroying the `SignalData` struct) while zero or more other
|
||||
threads are in the process of calling the callbacks from a previous
|
||||
emission of that signal (using the callback and `user_data` from zero or
|
||||
more `SignalSubscriber` structs). Multiple threads could be calling
|
||||
callbacks because callbacks are invoked in the `GMainContext` which
|
||||
originally made a subscription, and GDBus supports subscribing to a
|
||||
signal from multiple threads. In that case, the callbacks are dispatched
|
||||
to multiple threads.
|
||||
|
||||
In order to allow the `SignalSubscriber` structs to outlive the
|
||||
`SignalData` which contained their old match rule, store them in a
|
||||
`GPtrArray` in the `SignalData` struct, and refcount them individually.
|
||||
|
||||
This commit in itself should make no functional changes to how GDBus
|
||||
works, but will allow following commits to do so.
|
||||
|
||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
||||
|
||||
Helps: #978
|
||||
---
|
||||
gio/gdbusconnection.c | 105 +++++++++++++++++++++++++-----------------
|
||||
1 file changed, 63 insertions(+), 42 deletions(-)
|
||||
|
||||
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
||||
index 63f37ca4b..170057682 100644
|
||||
--- a/gio/gdbusconnection.c
|
||||
+++ b/gio/gdbusconnection.c
|
||||
@@ -3229,18 +3229,9 @@ typedef struct
|
||||
gchar *object_path;
|
||||
gchar *arg0;
|
||||
GDBusSignalFlags flags;
|
||||
- GArray *subscribers;
|
||||
+ GPtrArray *subscribers; /* (owned) (element-type SignalSubscriber) */
|
||||
} SignalData;
|
||||
|
||||
-typedef struct
|
||||
-{
|
||||
- GDBusSignalCallback callback;
|
||||
- gpointer user_data;
|
||||
- GDestroyNotify user_data_free_func;
|
||||
- guint id;
|
||||
- GMainContext *context;
|
||||
-} SignalSubscriber;
|
||||
-
|
||||
static void
|
||||
signal_data_free (SignalData *signal_data)
|
||||
{
|
||||
@@ -3251,10 +3242,37 @@ signal_data_free (SignalData *signal_data)
|
||||
g_free (signal_data->member);
|
||||
g_free (signal_data->object_path);
|
||||
g_free (signal_data->arg0);
|
||||
- g_array_free (signal_data->subscribers, TRUE);
|
||||
+ g_ptr_array_unref (signal_data->subscribers);
|
||||
g_free (signal_data);
|
||||
}
|
||||
|
||||
+typedef struct
|
||||
+{
|
||||
+ gatomicrefcount ref_count;
|
||||
+ GDBusSignalCallback callback;
|
||||
+ gpointer user_data;
|
||||
+ GDestroyNotify user_data_free_func;
|
||||
+ guint id;
|
||||
+ GMainContext *context;
|
||||
+} SignalSubscriber;
|
||||
+
|
||||
+static SignalSubscriber *
|
||||
+signal_subscriber_ref (SignalSubscriber *subscriber)
|
||||
+{
|
||||
+ g_atomic_ref_count_inc (&subscriber->ref_count);
|
||||
+ return subscriber;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+signal_subscriber_unref (SignalSubscriber *subscriber)
|
||||
+{
|
||||
+ if (g_atomic_ref_count_dec (&subscriber->ref_count))
|
||||
+ {
|
||||
+ g_main_context_unref (subscriber->context);
|
||||
+ g_free (subscriber);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static gchar *
|
||||
args_to_rule (const gchar *sender,
|
||||
const gchar *interface_name,
|
||||
@@ -3440,7 +3458,7 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
||||
{
|
||||
gchar *rule;
|
||||
SignalData *signal_data;
|
||||
- SignalSubscriber subscriber;
|
||||
+ SignalSubscriber *subscriber;
|
||||
GPtrArray *signal_data_array;
|
||||
const gchar *sender_unique_name;
|
||||
|
||||
@@ -3481,17 +3499,19 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
||||
else
|
||||
sender_unique_name = "";
|
||||
|
||||
- subscriber.callback = callback;
|
||||
- subscriber.user_data = user_data;
|
||||
- subscriber.user_data_free_func = user_data_free_func;
|
||||
- subscriber.id = (guint) g_atomic_int_add (&_global_subscriber_id, 1); /* TODO: overflow etc. */
|
||||
- subscriber.context = g_main_context_ref_thread_default ();
|
||||
+ subscriber = g_new0 (SignalSubscriber, 1);
|
||||
+ subscriber->ref_count = 1;
|
||||
+ subscriber->callback = callback;
|
||||
+ subscriber->user_data = user_data;
|
||||
+ subscriber->user_data_free_func = user_data_free_func;
|
||||
+ subscriber->id = (guint) g_atomic_int_add (&_global_subscriber_id, 1); /* TODO: overflow etc. */
|
||||
+ subscriber->context = g_main_context_ref_thread_default ();
|
||||
|
||||
/* see if we've already have this rule */
|
||||
signal_data = g_hash_table_lookup (connection->map_rule_to_signal_data, rule);
|
||||
if (signal_data != NULL)
|
||||
{
|
||||
- g_array_append_val (signal_data->subscribers, subscriber);
|
||||
+ g_ptr_array_add (signal_data->subscribers, subscriber);
|
||||
g_free (rule);
|
||||
goto out;
|
||||
}
|
||||
@@ -3505,8 +3525,8 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
||||
signal_data->object_path = g_strdup (object_path);
|
||||
signal_data->arg0 = g_strdup (arg0);
|
||||
signal_data->flags = flags;
|
||||
- signal_data->subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
|
||||
- g_array_append_val (signal_data->subscribers, subscriber);
|
||||
+ signal_data->subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref);
|
||||
+ g_ptr_array_add (signal_data->subscribers, subscriber);
|
||||
|
||||
g_hash_table_insert (connection->map_rule_to_signal_data,
|
||||
signal_data->rule,
|
||||
@@ -3536,12 +3556,12 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
||||
|
||||
out:
|
||||
g_hash_table_insert (connection->map_id_to_signal_data,
|
||||
- GUINT_TO_POINTER (subscriber.id),
|
||||
+ GUINT_TO_POINTER (subscriber->id),
|
||||
signal_data);
|
||||
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
- return subscriber.id;
|
||||
+ return subscriber->id;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
@@ -3551,7 +3571,7 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
||||
static void
|
||||
unsubscribe_id_internal (GDBusConnection *connection,
|
||||
guint subscription_id,
|
||||
- GArray *out_removed_subscribers)
|
||||
+ GPtrArray *out_removed_subscribers)
|
||||
{
|
||||
SignalData *signal_data;
|
||||
GPtrArray *signal_data_array;
|
||||
@@ -3567,16 +3587,19 @@ unsubscribe_id_internal (GDBusConnection *connection,
|
||||
|
||||
for (n = 0; n < signal_data->subscribers->len; n++)
|
||||
{
|
||||
- SignalSubscriber *subscriber;
|
||||
+ SignalSubscriber *subscriber = signal_data->subscribers->pdata[n];
|
||||
|
||||
- subscriber = &(g_array_index (signal_data->subscribers, SignalSubscriber, n));
|
||||
if (subscriber->id != subscription_id)
|
||||
continue;
|
||||
|
||||
+ /* It’s OK to rearrange the array order using the ‘fast’ #GPtrArray
|
||||
+ * removal functions, since we’re going to exit the loop below anyway — we
|
||||
+ * never move on to the next element. Secondly, subscription IDs are
|
||||
+ * guaranteed to be unique. */
|
||||
g_warn_if_fail (g_hash_table_remove (connection->map_id_to_signal_data,
|
||||
GUINT_TO_POINTER (subscription_id)));
|
||||
- g_array_append_val (out_removed_subscribers, *subscriber);
|
||||
- g_array_remove_index (signal_data->subscribers, n);
|
||||
+ g_ptr_array_add (out_removed_subscribers, signal_subscriber_ref (subscriber));
|
||||
+ g_ptr_array_remove_index_fast (signal_data->subscribers, n);
|
||||
|
||||
if (signal_data->subscribers->len == 0)
|
||||
{
|
||||
@@ -3634,13 +3657,13 @@ void
|
||||
g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
|
||||
guint subscription_id)
|
||||
{
|
||||
- GArray *subscribers;
|
||||
+ GPtrArray *subscribers;
|
||||
guint n;
|
||||
|
||||
g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
|
||||
g_return_if_fail (check_initialized (connection));
|
||||
|
||||
- subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
|
||||
+ subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref);
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
unsubscribe_id_internal (connection,
|
||||
@@ -3654,15 +3677,15 @@ g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
|
||||
/* call GDestroyNotify without lock held */
|
||||
for (n = 0; n < subscribers->len; n++)
|
||||
{
|
||||
- SignalSubscriber *subscriber;
|
||||
- subscriber = &(g_array_index (subscribers, SignalSubscriber, n));
|
||||
+ SignalSubscriber *subscriber = subscribers->pdata[n];
|
||||
call_destroy_notify (subscriber->context,
|
||||
subscriber->user_data_free_func,
|
||||
subscriber->user_data);
|
||||
- g_main_context_unref (subscriber->context);
|
||||
+ subscriber->user_data_free_func = NULL;
|
||||
+ subscriber->user_data = NULL;
|
||||
}
|
||||
|
||||
- g_array_free (subscribers, TRUE);
|
||||
+ g_ptr_array_unref (subscribers);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
@@ -3852,12 +3875,10 @@ schedule_callbacks (GDBusConnection *connection,
|
||||
|
||||
for (m = 0; m < signal_data->subscribers->len; m++)
|
||||
{
|
||||
- SignalSubscriber *subscriber;
|
||||
+ SignalSubscriber *subscriber = signal_data->subscribers->pdata[m];
|
||||
GSource *idle_source;
|
||||
SignalInstance *signal_instance;
|
||||
|
||||
- subscriber = &(g_array_index (signal_data->subscribers, SignalSubscriber, m));
|
||||
-
|
||||
signal_instance = g_new0 (SignalInstance, 1);
|
||||
signal_instance->subscription_id = subscriber->id;
|
||||
signal_instance->callback = subscriber->callback;
|
||||
@@ -3930,7 +3951,7 @@ purge_all_signal_subscriptions (GDBusConnection *connection)
|
||||
GHashTableIter iter;
|
||||
gpointer key;
|
||||
GArray *ids;
|
||||
- GArray *subscribers;
|
||||
+ GPtrArray *subscribers;
|
||||
guint n;
|
||||
|
||||
ids = g_array_new (FALSE, FALSE, sizeof (guint));
|
||||
@@ -3941,7 +3962,7 @@ purge_all_signal_subscriptions (GDBusConnection *connection)
|
||||
g_array_append_val (ids, subscription_id);
|
||||
}
|
||||
|
||||
- subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
|
||||
+ subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref);
|
||||
for (n = 0; n < ids->len; n++)
|
||||
{
|
||||
guint subscription_id = g_array_index (ids, guint, n);
|
||||
@@ -3954,15 +3975,15 @@ purge_all_signal_subscriptions (GDBusConnection *connection)
|
||||
/* call GDestroyNotify without lock held */
|
||||
for (n = 0; n < subscribers->len; n++)
|
||||
{
|
||||
- SignalSubscriber *subscriber;
|
||||
- subscriber = &(g_array_index (subscribers, SignalSubscriber, n));
|
||||
+ SignalSubscriber *subscriber = subscribers->pdata[n];
|
||||
call_destroy_notify (subscriber->context,
|
||||
subscriber->user_data_free_func,
|
||||
subscriber->user_data);
|
||||
- g_main_context_unref (subscriber->context);
|
||||
+ subscriber->user_data_free_func = NULL;
|
||||
+ subscriber->user_data = NULL;
|
||||
}
|
||||
|
||||
- g_array_free (subscribers, TRUE);
|
||||
+ g_ptr_array_unref (subscribers);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
--
|
||||
2.50.0
|
||||
|
||||
|
||||
From d21d9fb02496f21864e4175d08b5f55416e832e6 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <withnall@endlessm.com>
|
||||
Date: Fri, 17 Jan 2020 19:52:46 +0000
|
||||
Subject: [PATCH 2/5] gdbusconnection: Tidy up destroy notification for signal
|
||||
subscriptions
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Tie the destruction of the `user_data` to the destruction of the
|
||||
`SignalSubscriber` struct. This is tidier, and ensures that the fields
|
||||
in `SignalSubscriber` are all immutable after being set, so the
|
||||
structure can safely be used across threads without locking.
|
||||
|
||||
It doesn’t matter which thread we call `call_destroy_notify()` in, since
|
||||
it always defers calling `user_data_free_func` to the user-provided
|
||||
`GMainContext`.
|
||||
|
||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
||||
|
||||
Helps: #978
|
||||
---
|
||||
gio/gdbusconnection.c | 32 +++++++++-----------------------
|
||||
1 file changed, 9 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
||||
index 170057682..2dba09fcc 100644
|
||||
--- a/gio/gdbusconnection.c
|
||||
+++ b/gio/gdbusconnection.c
|
||||
@@ -3248,6 +3248,7 @@ signal_data_free (SignalData *signal_data)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
+ /* All fields are immutable after construction. */
|
||||
gatomicrefcount ref_count;
|
||||
GDBusSignalCallback callback;
|
||||
gpointer user_data;
|
||||
@@ -3268,6 +3269,14 @@ signal_subscriber_unref (SignalSubscriber *subscriber)
|
||||
{
|
||||
if (g_atomic_ref_count_dec (&subscriber->ref_count))
|
||||
{
|
||||
+ /* Destroy the user data. It doesn’t matter which thread
|
||||
+ * signal_subscriber_unref() is called in (or whether it’s called with a
|
||||
+ * lock held), as call_destroy_notify() always defers to the next
|
||||
+ * #GMainContext iteration. */
|
||||
+ call_destroy_notify (subscriber->context,
|
||||
+ subscriber->user_data_free_func,
|
||||
+ subscriber->user_data);
|
||||
+
|
||||
g_main_context_unref (subscriber->context);
|
||||
g_free (subscriber);
|
||||
}
|
||||
@@ -3658,7 +3667,6 @@ g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
|
||||
guint subscription_id)
|
||||
{
|
||||
GPtrArray *subscribers;
|
||||
- guint n;
|
||||
|
||||
g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
|
||||
g_return_if_fail (check_initialized (connection));
|
||||
@@ -3674,17 +3682,6 @@ g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
|
||||
/* invariant */
|
||||
g_assert (subscribers->len == 0 || subscribers->len == 1);
|
||||
|
||||
- /* call GDestroyNotify without lock held */
|
||||
- for (n = 0; n < subscribers->len; n++)
|
||||
- {
|
||||
- SignalSubscriber *subscriber = subscribers->pdata[n];
|
||||
- call_destroy_notify (subscriber->context,
|
||||
- subscriber->user_data_free_func,
|
||||
- subscriber->user_data);
|
||||
- subscriber->user_data_free_func = NULL;
|
||||
- subscriber->user_data = NULL;
|
||||
- }
|
||||
-
|
||||
g_ptr_array_unref (subscribers);
|
||||
}
|
||||
|
||||
@@ -3972,17 +3969,6 @@ purge_all_signal_subscriptions (GDBusConnection *connection)
|
||||
}
|
||||
g_array_free (ids, TRUE);
|
||||
|
||||
- /* call GDestroyNotify without lock held */
|
||||
- for (n = 0; n < subscribers->len; n++)
|
||||
- {
|
||||
- SignalSubscriber *subscriber = subscribers->pdata[n];
|
||||
- call_destroy_notify (subscriber->context,
|
||||
- subscriber->user_data_free_func,
|
||||
- subscriber->user_data);
|
||||
- subscriber->user_data_free_func = NULL;
|
||||
- subscriber->user_data = NULL;
|
||||
- }
|
||||
-
|
||||
g_ptr_array_unref (subscribers);
|
||||
}
|
||||
|
||||
--
|
||||
2.50.0
|
||||
|
||||
|
||||
From 5b7c9398a67ad274cb8faef8bf45461540a7198e Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <withnall@endlessm.com>
|
||||
Date: Fri, 17 Jan 2020 19:38:55 +0000
|
||||
Subject: [PATCH 3/5] gdbusconnection: Fix race when emitting D-Bus signal
|
||||
callbacks
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Instead of storing a copy of the `callback` and `user_data` from a
|
||||
`SignalSubscriber` in a `SignalInstance` struct (which is the closure
|
||||
for signal callback data as it’s sent from the D-Bus worker thread to
|
||||
the thread which originally subscribed to a signal), store a strong
|
||||
reference to the `SignalSubscriber` struct itself.
|
||||
|
||||
This keeps the `SignalSubscriber` alive until the emission is
|
||||
complete, which ensures that the `user_data` is not freed prematurely.
|
||||
It also slightly reduces the allocation size of `SignalInstance` (not
|
||||
that it matters).
|
||||
|
||||
This is threadsafe because the fields in `SignalSubscriber` are all
|
||||
immutable after construction.
|
||||
|
||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
||||
|
||||
Helps: #978
|
||||
---
|
||||
gio/gdbusconnection.c | 27 ++++++++++++---------------
|
||||
1 file changed, 12 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
||||
index 2dba09fcc..4cae53b29 100644
|
||||
--- a/gio/gdbusconnection.c
|
||||
+++ b/gio/gdbusconnection.c
|
||||
@@ -3689,9 +3689,7 @@ g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
|
||||
|
||||
typedef struct
|
||||
{
|
||||
- guint subscription_id;
|
||||
- GDBusSignalCallback callback;
|
||||
- gpointer user_data;
|
||||
+ SignalSubscriber *subscriber; /* (owned) */
|
||||
GDBusMessage *message;
|
||||
GDBusConnection *connection;
|
||||
const gchar *sender;
|
||||
@@ -3723,7 +3721,7 @@ emit_signal_instance_in_idle_cb (gpointer data)
|
||||
|
||||
#if 0
|
||||
g_print ("in emit_signal_instance_in_idle_cb (id=%d sender=%s path=%s interface=%s member=%s params=%s)\n",
|
||||
- signal_instance->subscription_id,
|
||||
+ signal_instance->subscriber->id,
|
||||
signal_instance->sender,
|
||||
signal_instance->path,
|
||||
signal_instance->interface,
|
||||
@@ -3735,18 +3733,18 @@ emit_signal_instance_in_idle_cb (gpointer data)
|
||||
CONNECTION_LOCK (signal_instance->connection);
|
||||
has_subscription = FALSE;
|
||||
if (g_hash_table_lookup (signal_instance->connection->map_id_to_signal_data,
|
||||
- GUINT_TO_POINTER (signal_instance->subscription_id)) != NULL)
|
||||
+ GUINT_TO_POINTER (signal_instance->subscriber->id)) != NULL)
|
||||
has_subscription = TRUE;
|
||||
CONNECTION_UNLOCK (signal_instance->connection);
|
||||
|
||||
if (has_subscription)
|
||||
- signal_instance->callback (signal_instance->connection,
|
||||
- signal_instance->sender,
|
||||
- signal_instance->path,
|
||||
- signal_instance->interface,
|
||||
- signal_instance->member,
|
||||
- parameters,
|
||||
- signal_instance->user_data);
|
||||
+ signal_instance->subscriber->callback (signal_instance->connection,
|
||||
+ signal_instance->sender,
|
||||
+ signal_instance->path,
|
||||
+ signal_instance->interface,
|
||||
+ signal_instance->member,
|
||||
+ parameters,
|
||||
+ signal_instance->subscriber->user_data);
|
||||
|
||||
g_variant_unref (parameters);
|
||||
|
||||
@@ -3758,6 +3756,7 @@ signal_instance_free (SignalInstance *signal_instance)
|
||||
{
|
||||
g_object_unref (signal_instance->message);
|
||||
g_object_unref (signal_instance->connection);
|
||||
+ signal_subscriber_unref (signal_instance->subscriber);
|
||||
g_free (signal_instance);
|
||||
}
|
||||
|
||||
@@ -3877,9 +3876,7 @@ schedule_callbacks (GDBusConnection *connection,
|
||||
SignalInstance *signal_instance;
|
||||
|
||||
signal_instance = g_new0 (SignalInstance, 1);
|
||||
- signal_instance->subscription_id = subscriber->id;
|
||||
- signal_instance->callback = subscriber->callback;
|
||||
- signal_instance->user_data = subscriber->user_data;
|
||||
+ signal_instance->subscriber = signal_subscriber_ref (subscriber);
|
||||
signal_instance->message = g_object_ref (message);
|
||||
signal_instance->connection = g_object_ref (connection);
|
||||
signal_instance->sender = sender;
|
||||
--
|
||||
2.50.0
|
||||
|
||||
|
||||
From a13bbdc1dc0cd4ec16c3e75d0cc1c07eb791b3bc Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <withnall@endlessm.com>
|
||||
Date: Fri, 17 Jan 2020 19:56:58 +0000
|
||||
Subject: [PATCH 4/5] gdbusconnection: Tidy up unsubscription code
|
||||
|
||||
This just removes a now-redundant intermediate array. This means that
|
||||
the `SignalSubscriber` instances are now potentially freed a little
|
||||
sooner, inside the locked segment, but they are already careful to only
|
||||
call their `user_data_free_func` in the right thread. So that should not
|
||||
deadlock.
|
||||
|
||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
||||
|
||||
Helps: #978
|
||||
---
|
||||
gio/gdbusconnection.c | 33 +++++++++++----------------------
|
||||
1 file changed, 11 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
||||
index 4cae53b29..4d99f8570 100644
|
||||
--- a/gio/gdbusconnection.c
|
||||
+++ b/gio/gdbusconnection.c
|
||||
@@ -3576,15 +3576,16 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* called in any thread */
|
||||
-/* must hold lock when calling this (except if connection->finalizing is TRUE) */
|
||||
-static void
|
||||
+/* must hold lock when calling this (except if connection->finalizing is TRUE)
|
||||
+ * returns the number of removed subscribers */
|
||||
+static guint
|
||||
unsubscribe_id_internal (GDBusConnection *connection,
|
||||
- guint subscription_id,
|
||||
- GPtrArray *out_removed_subscribers)
|
||||
+ guint subscription_id)
|
||||
{
|
||||
SignalData *signal_data;
|
||||
GPtrArray *signal_data_array;
|
||||
guint n;
|
||||
+ guint n_removed = 0;
|
||||
|
||||
signal_data = g_hash_table_lookup (connection->map_id_to_signal_data,
|
||||
GUINT_TO_POINTER (subscription_id));
|
||||
@@ -3607,7 +3608,7 @@ unsubscribe_id_internal (GDBusConnection *connection,
|
||||
* guaranteed to be unique. */
|
||||
g_warn_if_fail (g_hash_table_remove (connection->map_id_to_signal_data,
|
||||
GUINT_TO_POINTER (subscription_id)));
|
||||
- g_ptr_array_add (out_removed_subscribers, signal_subscriber_ref (subscriber));
|
||||
+ n_removed++;
|
||||
g_ptr_array_remove_index_fast (signal_data->subscribers, n);
|
||||
|
||||
if (signal_data->subscribers->len == 0)
|
||||
@@ -3649,7 +3650,7 @@ unsubscribe_id_internal (GDBusConnection *connection,
|
||||
g_assert_not_reached ();
|
||||
|
||||
out:
|
||||
- ;
|
||||
+ return n_removed;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3666,23 +3667,17 @@ void
|
||||
g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
|
||||
guint subscription_id)
|
||||
{
|
||||
- GPtrArray *subscribers;
|
||||
+ guint n_subscribers_removed G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */;
|
||||
|
||||
g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
|
||||
g_return_if_fail (check_initialized (connection));
|
||||
|
||||
- subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref);
|
||||
-
|
||||
CONNECTION_LOCK (connection);
|
||||
- unsubscribe_id_internal (connection,
|
||||
- subscription_id,
|
||||
- subscribers);
|
||||
+ n_subscribers_removed = unsubscribe_id_internal (connection, subscription_id);
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
/* invariant */
|
||||
- g_assert (subscribers->len == 0 || subscribers->len == 1);
|
||||
-
|
||||
- g_ptr_array_unref (subscribers);
|
||||
+ g_assert (n_subscribers_removed == 0 || n_subscribers_removed == 1);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
@@ -3945,7 +3940,6 @@ purge_all_signal_subscriptions (GDBusConnection *connection)
|
||||
GHashTableIter iter;
|
||||
gpointer key;
|
||||
GArray *ids;
|
||||
- GPtrArray *subscribers;
|
||||
guint n;
|
||||
|
||||
ids = g_array_new (FALSE, FALSE, sizeof (guint));
|
||||
@@ -3956,17 +3950,12 @@ purge_all_signal_subscriptions (GDBusConnection *connection)
|
||||
g_array_append_val (ids, subscription_id);
|
||||
}
|
||||
|
||||
- subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref);
|
||||
for (n = 0; n < ids->len; n++)
|
||||
{
|
||||
guint subscription_id = g_array_index (ids, guint, n);
|
||||
- unsubscribe_id_internal (connection,
|
||||
- subscription_id,
|
||||
- subscribers);
|
||||
+ unsubscribe_id_internal (connection, subscription_id);
|
||||
}
|
||||
g_array_free (ids, TRUE);
|
||||
-
|
||||
- g_ptr_array_unref (subscribers);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
--
|
||||
2.50.0
|
||||
|
||||
|
||||
From 0ec439aab1da5df011bed6a1a317439efacb6c25 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <withnall@endlessm.com>
|
||||
Date: Fri, 17 Jan 2020 20:00:22 +0000
|
||||
Subject: [PATCH 5/5] gdbusnameowning: Fix race between connection shutdown and
|
||||
NameLost
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
As with all D-Bus signal subscriptions, it’s possible for a signal
|
||||
callback to be invoked in one thread (T1) while another thread (T2) is
|
||||
unsubscribing from that signal. In this case, T1 is the main thread, and
|
||||
T2 is the D-Bus connection worker thread which is unsubscribing all
|
||||
signals as it’s in the process of closing.
|
||||
|
||||
Due to this possibility, all `user_data` for signal callbacks needs to
|
||||
be referenced outside the lifecycle of the code which
|
||||
subscribes/unsubscribes the signal. In other words, it’s not safe to
|
||||
subscribe to a signal, store the subscription ID in a struct,
|
||||
unsubscribe from the signal when freeing the struct, and dereference the
|
||||
struct in the signal callback. The data passed to the signal callback
|
||||
has to have its own strong reference.
|
||||
|
||||
Instead, it’s safe to subscribe to a signal and add a strong reference
|
||||
to the struct, store the subscription ID in that struct, and unsubscribe
|
||||
from the signal when the last external reference to your struct is
|
||||
dropped. That unsubscription should break the refcount cycle between the
|
||||
signal connection and the struct, and allow the struct to be completely
|
||||
freed. Only with that approach is it safe to dereference the struct in
|
||||
the signal callback, if there’s any possibility that the signal might be
|
||||
unsubscribed from a separate thread.
|
||||
|
||||
The tests need specific additional main loop cycles to completely emit
|
||||
the NameLost signal callback. Ideally they need refactoring, but this
|
||||
will do (1000 test cycles passed).
|
||||
|
||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
||||
|
||||
Fixes: #978
|
||||
---
|
||||
gio/gdbusnameowning.c | 15 ++++++++++-----
|
||||
gio/tests/gdbus-names.c | 11 ++++++++++-
|
||||
2 files changed, 20 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/gio/gdbusnameowning.c b/gio/gdbusnameowning.c
|
||||
index 2c2714db2..00554c16a 100644
|
||||
--- a/gio/gdbusnameowning.c
|
||||
+++ b/gio/gdbusnameowning.c
|
||||
@@ -366,7 +366,12 @@ request_name_cb (GObject *source_object,
|
||||
connection = g_object_ref (client->connection);
|
||||
G_UNLOCK (lock);
|
||||
|
||||
- /* start listening to NameLost and NameAcquired messages */
|
||||
+ /* Start listening to NameLost and NameAcquired messages. We hold
|
||||
+ * references to the Client in the signal closures, since it’s possible
|
||||
+ * for a signal to be in-flight after unsubscribing the signal handler.
|
||||
+ * This creates a reference count cycle, but that’s explicitly broken by
|
||||
+ * disconnecting the signal handlers before calling client_unref() in
|
||||
+ * g_bus_unown_name(). */
|
||||
if (connection != NULL)
|
||||
{
|
||||
client->name_lost_subscription_id =
|
||||
@@ -378,8 +383,8 @@ request_name_cb (GObject *source_object,
|
||||
client->name,
|
||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||
on_name_lost_or_acquired,
|
||||
- client,
|
||||
- NULL);
|
||||
+ client_ref (client),
|
||||
+ (GDestroyNotify) client_unref);
|
||||
client->name_acquired_subscription_id =
|
||||
g_dbus_connection_signal_subscribe (connection,
|
||||
"org.freedesktop.DBus",
|
||||
@@ -389,8 +394,8 @@ request_name_cb (GObject *source_object,
|
||||
client->name,
|
||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||
on_name_lost_or_acquired,
|
||||
- client,
|
||||
- NULL);
|
||||
+ client_ref (client),
|
||||
+ (GDestroyNotify) client_unref);
|
||||
g_object_unref (connection);
|
||||
}
|
||||
}
|
||||
diff --git a/gio/tests/gdbus-names.c b/gio/tests/gdbus-names.c
|
||||
index 648b54774..b42ba2141 100644
|
||||
--- a/gio/tests/gdbus-names.c
|
||||
+++ b/gio/tests/gdbus-names.c
|
||||
@@ -189,6 +189,7 @@ test_bus_own_name (void)
|
||||
* Stop owning the name - this should invoke our free func
|
||||
*/
|
||||
g_bus_unown_name (id);
|
||||
+ g_main_loop_run (loop);
|
||||
g_assert_cmpint (data.num_free_func, ==, 2);
|
||||
|
||||
/*
|
||||
@@ -330,6 +331,7 @@ test_bus_own_name (void)
|
||||
g_assert_cmpint (data2.num_acquired, ==, 0);
|
||||
g_assert_cmpint (data2.num_lost, ==, 1);
|
||||
g_bus_unown_name (id2);
|
||||
+ g_main_loop_run (loop);
|
||||
g_assert_cmpint (data2.num_bus_acquired, ==, 0);
|
||||
g_assert_cmpint (data2.num_acquired, ==, 0);
|
||||
g_assert_cmpint (data2.num_lost, ==, 1);
|
||||
@@ -355,6 +357,7 @@ test_bus_own_name (void)
|
||||
g_assert_cmpint (data2.num_acquired, ==, 0);
|
||||
g_assert_cmpint (data2.num_lost, ==, 1);
|
||||
g_bus_unown_name (id2);
|
||||
+ g_main_loop_run (loop);
|
||||
g_assert_cmpint (data2.num_bus_acquired, ==, 0);
|
||||
g_assert_cmpint (data2.num_acquired, ==, 0);
|
||||
g_assert_cmpint (data2.num_lost, ==, 1);
|
||||
@@ -365,6 +368,7 @@ test_bus_own_name (void)
|
||||
*/
|
||||
data.expect_null_connection = FALSE;
|
||||
g_bus_unown_name (id);
|
||||
+ g_main_loop_run (loop);
|
||||
g_assert_cmpint (data.num_bus_acquired, ==, 1);
|
||||
g_assert_cmpint (data.num_acquired, ==, 1);
|
||||
g_assert_cmpint (data.num_free_func, ==, 4);
|
||||
@@ -418,6 +422,7 @@ test_bus_own_name (void)
|
||||
g_assert_cmpint (data2.num_acquired, ==, 0);
|
||||
g_assert_cmpint (data2.num_lost, ==, 1);
|
||||
g_bus_unown_name (id2);
|
||||
+ g_main_loop_run (loop);
|
||||
g_assert_cmpint (data2.num_bus_acquired, ==, 0);
|
||||
g_assert_cmpint (data2.num_acquired, ==, 0);
|
||||
g_assert_cmpint (data2.num_lost, ==, 1);
|
||||
@@ -450,8 +455,9 @@ test_bus_own_name (void)
|
||||
g_assert_cmpint (data2.num_bus_acquired, ==, 0);
|
||||
/* ok, make owner2 release the name - then wait for owner to automagically reacquire it */
|
||||
g_bus_unown_name (id2);
|
||||
- g_assert_cmpint (data2.num_free_func, ==, 1);
|
||||
g_main_loop_run (loop);
|
||||
+ g_main_loop_run (loop);
|
||||
+ g_assert_cmpint (data2.num_free_func, ==, 1);
|
||||
g_assert_cmpint (data.num_acquired, ==, 2);
|
||||
g_assert_cmpint (data.num_lost, ==, 1);
|
||||
|
||||
@@ -466,6 +472,7 @@ test_bus_own_name (void)
|
||||
g_assert_cmpint (data.num_acquired, ==, 2);
|
||||
g_assert_cmpint (data.num_lost, ==, 2);
|
||||
g_bus_unown_name (id);
|
||||
+ g_main_loop_run (loop);
|
||||
g_assert_cmpint (data.num_free_func, ==, 5);
|
||||
|
||||
g_object_unref (c);
|
||||
@@ -648,6 +655,7 @@ test_bus_watch_name (void)
|
||||
|
||||
/* unown the name */
|
||||
g_bus_unown_name (owner_id);
|
||||
+ g_main_loop_run (loop);
|
||||
g_assert_cmpint (data.num_acquired, ==, 1);
|
||||
g_assert_cmpint (data.num_free_func, ==, 2);
|
||||
|
||||
@@ -707,6 +715,7 @@ test_bus_watch_name (void)
|
||||
g_assert_cmpint (data.num_free_func, ==, 1);
|
||||
|
||||
g_bus_unown_name (owner_id);
|
||||
+ g_main_loop_run (loop);
|
||||
g_assert_cmpint (data.num_free_func, ==, 2);
|
||||
|
||||
session_bus_down ();
|
||||
--
|
||||
2.50.0
|
||||
|
431
SOURCES/gnetworkmonitornm.patch
Normal file
431
SOURCES/gnetworkmonitornm.patch
Normal file
@ -0,0 +1,431 @@
|
||||
From c48c984d39afeae84b0cad515f08f83c711fd9c4 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <withnall@endlessm.com>
|
||||
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 <withnall@endlessm.com>
|
||||
|
||||
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 <alarrosa@suse.com>
|
||||
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 <fabrice@bellet.info>
|
||||
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 <withnall@endlessm.com>
|
||||
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 <withnall@endlessm.com>
|
||||
|
||||
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 <hadess@hadess.net>
|
||||
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 <hadess@hadess.net>
|
||||
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 <hadess@hadess.net>
|
||||
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 <julian.klode@canonical.com>
|
||||
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 <julian.klode@canonical.com>
|
||||
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
|
@ -5,7 +5,7 @@
|
||||
|
||||
Name: glib2
|
||||
Version: 2.56.4
|
||||
Release: 157%{?dist}
|
||||
Release: 166%{?dist}
|
||||
Summary: A library of handy utility functions
|
||||
|
||||
License: LGPLv2+
|
||||
@ -106,6 +106,47 @@ 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
|
||||
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=2125184
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1134
|
||||
Patch21: 1134.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/54
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/400
|
||||
Patch22: 54.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1549
|
||||
# Also: https://gitlab.gnome.org/GNOME/glib/-/commit/d0821da5244fd08c756a5f84ec0d3063c72d1ac6
|
||||
Patch23: 1549.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4155
|
||||
Patch24: 4155.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4281
|
||||
Patch25: CVE-2024-52533.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4588
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4592
|
||||
Patch26: CVE-2025-4373.patch
|
||||
|
||||
# Contains commits from:
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1121
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3291
|
||||
Patch27: gdbus-conflict-reduction.patch
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1332
|
||||
Patch28: gdbus-signal-race.patch
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4038
|
||||
Patch29: CVE-2024-34397.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4356
|
||||
Patch30: gdatetime-test.patch
|
||||
|
||||
%description
|
||||
GLib is the low-level core library that forms the basis for projects
|
||||
such as GTK+ and GNOME. It provides data structure handling for C,
|
||||
@ -303,6 +344,46 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
|
||||
%{_datadir}/installed-tests
|
||||
|
||||
%changelog
|
||||
* Fri Jul 11 2025 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-166
|
||||
- Add patches for CVE-2024-34397, CVE-2024-52533, CVE-2025-4373
|
||||
- Update GDateTime test for new tzdata
|
||||
- Resolves: RHEL-67084
|
||||
- Resolves: RHEL-94286
|
||||
- Resolves: RHEL-94848
|
||||
|
||||
* Thu Sep 26 2024 Ondrej Holy <oholy@redhat.com> - 2.56.4-165
|
||||
- Add support for x-gvfs-trash mount option
|
||||
- Resolves: RHEL-46828
|
||||
|
||||
* Tue Feb 13 2024 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-164
|
||||
- Revert GUnixMountMonitor changes (it depends on functionality not in RHEL 8)
|
||||
- Resolves: RHEL-23636
|
||||
|
||||
* Thu Feb 01 2024 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-163
|
||||
- Backport GUnixMountMonitor port to libmnt_monitor
|
||||
- Make GUnixMountMonitor thread-safe
|
||||
- Resolves: RHEL-23636
|
||||
|
||||
* Thu Sep 21 2023 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-162
|
||||
- Add support to ignore trash for certain mounts
|
||||
- Resolves: RHEL-2836
|
||||
|
||||
* Tue Jan 03 2023 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-161
|
||||
- Backport grefcount API
|
||||
- Resolves: #2153205
|
||||
|
||||
* Wed Nov 16 2022 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-160
|
||||
- Fix G_FILE_COPY_TARGET_DEFAULT_PERMS, should not create private files
|
||||
- Resolves: #2125184
|
||||
|
||||
* Fri Apr 22 2022 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-159
|
||||
- Add --interface-info-[body|header] modes to gdbus-codegen
|
||||
- Related: #2061994
|
||||
|
||||
* Wed Dec 01 2021 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-158
|
||||
- Fix GNetworkMonitor after NetworkManager D-Bus API changes
|
||||
- Resolves: #2014652
|
||||
|
||||
* Wed Sep 15 2021 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-157
|
||||
- Fix g_get_user_database_entry() crash when used with nss-systemd
|
||||
- Resolves: #2002126
|
||||
|
Loading…
Reference in New Issue
Block a user