gdbus: Add FD support for gdbus call

Gdbus call could not take file handle (parameter 'h') as a parameter.

Original patch from Tim Waugh <twaugh@redhat.com>.

Fixes: #961
This commit is contained in:
Norbert Pocs 2020-11-06 17:19:27 +00:00 committed by Philip Withnall
parent 63dfceedd2
commit a879c46a39
2 changed files with 69 additions and 10 deletions

View File

@ -321,6 +321,18 @@ $ gdbus call --session \
5000
(uint32 12,)
</programlisting>
<para>
Call a method with file handle argument:
</para>
<programlisting>
$ gdbus call --session \
--dest org.example.foo \
--object-path /org/example/foo \
--method SendFDs \
1 \
10 \
10&lt;file.foo
</programlisting>
<para>
Monitoring all objects on a service:
</para>

View File

@ -27,6 +27,10 @@
#include <gio/gio.h>
#ifdef G_OS_UNIX
#include <gio/gunixfdlist.h>
#endif
#include <gi18n.h>
#ifdef G_OS_WIN32
@ -905,6 +909,10 @@ handle_call (gint *argc,
gchar *method_name;
GVariant *result;
GPtrArray *in_signature_types;
#ifdef G_OS_UNIX
GUnixFDList *fd_list;
guint fd_id;
#endif
gboolean complete_names;
gboolean complete_paths;
gboolean complete_methods;
@ -920,6 +928,9 @@ handle_call (gint *argc,
method_name = NULL;
result = NULL;
in_signature_types = NULL;
#ifdef G_OS_UNIX
fd_list = NULL;
#endif
modify_argv0_for_command (argc, argv, "call");
@ -1164,6 +1175,23 @@ handle_call (gint *argc,
}
g_free (context);
}
#ifdef G_OS_UNIX
if (g_variant_is_of_type (value, G_VARIANT_TYPE_HANDLE))
{
if (!fd_list)
fd_list = g_unix_fd_list_new ();
if ((fd_id = g_unix_fd_list_append (fd_list, g_variant_get_handle (value), &error)) == -1)
{
g_printerr (_("Error adding handle %d: %s\n"),
g_variant_get_handle (value), error->message);
g_variant_builder_clear (&builder);
g_error_free (error);
goto out;
}
g_variant_unref (value);
value = g_variant_new_handle (fd_id);
}
#endif
g_variant_builder_add_value (&builder, value);
++parm;
}
@ -1171,17 +1199,33 @@ handle_call (gint *argc,
if (parameters != NULL)
parameters = g_variant_ref_sink (parameters);
#ifdef G_OS_UNIX
result = g_dbus_connection_call_with_unix_fd_list_sync (c,
opt_call_dest,
opt_call_object_path,
interface_name,
method_name,
parameters,
NULL,
G_DBUS_CALL_FLAGS_NONE,
opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
fd_list,
NULL,
NULL,
&error);
#else
result = g_dbus_connection_call_sync (c,
opt_call_dest,
opt_call_object_path,
interface_name,
method_name,
parameters,
NULL,
G_DBUS_CALL_FLAGS_NONE,
opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
NULL,
&error);
opt_call_dest,
opt_call_object_path,
interface_name,
method_name,
parameters,
NULL,
G_DBUS_CALL_FLAGS_NONE,
opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
NULL,
&error);
#endif
if (result == NULL)
{
g_printerr (_("Error: %s\n"), error->message);
@ -1230,6 +1274,9 @@ handle_call (gint *argc,
g_free (interface_name);
g_free (method_name);
g_option_context_free (o);
#ifdef G_OS_UNIX
g_clear_object (&fd_list);
#endif
return ret;
}