From a547b494c2a754c6da8b60b3d1261b13f043d4a6 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 02 2019 23:27:12 +0000 Subject: import spice-vdagent-0.14.0-18.el7 --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..31a1e0f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/spice-vdagent-0.14.0.tar.bz2 diff --git a/.spice-vdagent.metadata b/.spice-vdagent.metadata new file mode 100644 index 0000000..6c42438 --- /dev/null +++ b/.spice-vdagent.metadata @@ -0,0 +1 @@ +2b1e913251906087cf85389051801377f38a62a3 SOURCES/spice-vdagent-0.14.0.tar.bz2 diff --git a/SOURCES/0001-vdagent-d-Add-printing-of-version-to-h-output.patch b/SOURCES/0001-vdagent-d-Add-printing-of-version-to-h-output.patch new file mode 100644 index 0000000..a8d5973 --- /dev/null +++ b/SOURCES/0001-vdagent-d-Add-printing-of-version-to-h-output.patch @@ -0,0 +1,57 @@ +From e22b6b97a067d7c10bfba64fbef60afa777f6275 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 6 Jun 2013 17:00:22 +0200 +Subject: [PATCH] vdagent[d]: Add printing of version to -h output + +Signed-off-by: Hans de Goede +(cherry picked from commit 256e01c8c7b0c386525a0fac71537bb7bb05d271) +--- + src/vdagent.c | 6 +++--- + src/vdagentd.c | 4 ++-- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/vdagent.c b/src/vdagent.c +index 7e1b474..9e238d3 100644 +--- a/src/vdagent.c ++++ b/src/vdagent.c +@@ -132,15 +132,15 @@ static void usage(FILE *fp) + { + fprintf(fp, + "Usage: spice-vdagent [OPTIONS]\n\n" +- "Spice guest agent X11 session agent.\n\n" ++ "Spice guest agent X11 session agent, version %s.\n\n" + "Options:\n" + " -h print this text\n" + " -d log debug messages\n" + " -s set virtio serial port\n" + " -x don't daemonize\n" + " -f file xfer save dir\n" +- " -o <0|1> open dir on file xfer completion\n" +- ); ++ " -o <0|1> open dir on file xfer completion\n", ++ VERSION); + } + + static void quit_handler(int sig) +diff --git a/src/vdagentd.c b/src/vdagentd.c +index fbbe315..1ba957a 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -718,7 +718,7 @@ static void usage(FILE *fp) + { + fprintf(fp, + "Usage: spice-vdagentd [OPTIONS]\n\n" +- "Spice guest agent daemon.\n\n" ++ "Spice guest agent daemon, version %s.\n\n" + "Options:\n" + " -h print this text\n" + " -d log debug messages (use twice for extra info)\n" +@@ -731,7 +731,7 @@ static void usage(FILE *fp) + #ifdef HAVE_LIBSYSTEMD_LOGIN + " -X Disable systemd-logind integration\n" + #endif +- ,portdev, uinput_device); ++ ,VERSION, portdev, uinput_device); + } + + void daemonize(void) diff --git a/SOURCES/0002-vdagentd-Advertise-VD_AGENT_CAP_GUEST_LINEEND_LF.patch b/SOURCES/0002-vdagentd-Advertise-VD_AGENT_CAP_GUEST_LINEEND_LF.patch new file mode 100644 index 0000000..c7e3388 --- /dev/null +++ b/SOURCES/0002-vdagentd-Advertise-VD_AGENT_CAP_GUEST_LINEEND_LF.patch @@ -0,0 +1,22 @@ +From b251f710663cbbf4170d98f64d1f0bd4eb70f848 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 24 Jun 2013 10:34:27 +0200 +Subject: [PATCH] vdagentd: Advertise VD_AGENT_CAP_GUEST_LINEEND_LF + +Signed-off-by: Hans de Goede +--- + src/vdagentd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/vdagentd.c b/src/vdagentd.c +index 1ba957a..6280dfa 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -95,6 +95,7 @@ static void send_capabilities(struct vdagent_virtio_port *vport, + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_SELECTION); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_SPARSE_MONITORS_CONFIG); ++ VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GUEST_LINEEND_LF); + + vdagent_virtio_port_write(vport, VDP_CLIENT_PORT, + VD_AGENT_ANNOUNCE_CAPABILITIES, 0, diff --git a/SOURCES/0003-buildsys-Build-vdagentd-as-pie-relro-when-possible.patch b/SOURCES/0003-buildsys-Build-vdagentd-as-pie-relro-when-possible.patch new file mode 100644 index 0000000..de5df8f --- /dev/null +++ b/SOURCES/0003-buildsys-Build-vdagentd-as-pie-relro-when-possible.patch @@ -0,0 +1,79 @@ +From 3b4db5a5064909641ad80e0c1678a62f94afb9aa Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 3 Jul 2013 11:16:20 +0200 +Subject: [PATCH] buildsys: Build vdagentd as pie + relro when possible + +Signed-off-by: Hans de Goede +(cherry picked from commit 71b8e75c6f1bc6c482d28cf29b82643d6b38cf34) +--- + Makefile.am | 6 ++++-- + configure.ac | 32 ++++++++++++++++++++++++++++++++ + 2 files changed, 36 insertions(+), 2 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index ea9bc05..5515ca0 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -8,8 +8,10 @@ src_spice_vdagent_CFLAGS = $(X_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) + src_spice_vdagent_LDADD = $(X_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) + src_spice_vdagent_SOURCES = src/vdagent.c src/vdagent-x11.c src/vdagent-x11-randr.c src/vdagent-file-xfers.c src/udscs.c + +-src_spice_vdagentd_CFLAGS = $(DBUS_CFLAGS) $(LIBSYSTEMD_LOGIN_CFLAGS) $(PCIACCESS_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) +-src_spice_vdagentd_LDADD = $(DBUS_LIBS) $(LIBSYSTEMD_LOGIN_LIBS) $(PCIACCESS_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) ++src_spice_vdagentd_CFLAGS = $(DBUS_CFLAGS) $(LIBSYSTEMD_LOGIN_CFLAGS) \ ++ $(PCIACCESS_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) $(PIE_CFLAGS) ++src_spice_vdagentd_LDADD = $(DBUS_LIBS) $(LIBSYSTEMD_LOGIN_LIBS) \ ++ $(PCIACCESS_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) $(PIE_LDFLAGS) + src_spice_vdagentd_SOURCES = src/vdagentd.c \ + src/vdagentd-uinput.c \ + src/vdagentd-xorg-conf.c \ +diff --git a/configure.ac b/configure.ac +index 91a24ff..a1ce6c0 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -141,6 +141,37 @@ if test "$ac_test_CFLAGS" != set; then + done + fi + ++AC_ARG_ENABLE([pie], ++ AS_HELP_STRING([--enable-pie=@<:@auto/yes/no@:>@], ++ [Enable position-independent-executable support (for spice-vdagentd)@<:@default=auto@:>@]), ++ [], ++ [enable_pie="auto"]) ++ ++if test "x$enable_pie" != "xno"; then ++ save_CFLAGS="$CFLAGS" ++ save_LDFLAGS="$LDFLAGS" ++ CFLAGS="$CFLAGS -fPIE" ++ LDFLAGS="$LDFLAGS -pie -Wl,-z,relro -Wl,-z,now" ++ AC_MSG_CHECKING([for PIE support]) ++ AC_LINK_IFELSE([AC_LANG_SOURCE([int main () { return 0; }])], ++ [have_pie=yes], ++ [have_pie=no]) ++ AC_MSG_RESULT([$have_pie]) ++ if test "x$have_pie" = "xno" && test "x$enable_pie" = "xyes"; then ++ AC_MSG_ERROR([pie support explicitly requested, but your toolchain does not support it]) ++ fi ++ if test "x$have_pie" = "xyes"; then ++ PIE_CFLAGS="-fPIE" ++ PIE_LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now" ++ AC_SUBST(PIE_CFLAGS) ++ AC_SUBST(PIE_LDFLAGS) ++ fi ++ CFLAGS="$save_CFLAGS" ++ LDFLAGS="$save_LDFLAGS" ++else ++ have_pie=no ++fi ++ + AC_CONFIG_FILES([ + Makefile + data/spice-vdagent.1 +@@ -160,6 +191,7 @@ AC_MSG_NOTICE([ + session-info: ${with_session_info} + pciaccess: ${enable_pciaccess} + static uinput: ${enable_static_uinput} ++ vdagentd pie + relro: ${have_pie} + + install RH initscript: ${init_redhat} + install systemd service: ${init_systemd} diff --git a/SOURCES/0004-Not-having-the-virtio-channel-is-not-an-error-instea.patch b/SOURCES/0004-Not-having-the-virtio-channel-is-not-an-error-instea.patch new file mode 100644 index 0000000..051213e --- /dev/null +++ b/SOURCES/0004-Not-having-the-virtio-channel-is-not-an-error-instea.patch @@ -0,0 +1,40 @@ +From 528a816d2be5fccb531e7711a4c2efea7dbd0348 Mon Sep 17 00:00:00 2001 +From: Colin Walters +Date: Tue, 11 Jun 2013 15:21:13 -0400 +Subject: [PATCH] Not having the virtio channel is not an error; instead + silently do nothing + +Fedora for example bundles the SPICE agent by default; however, we +don't want to spew an error when running non-virtualized, or with +plain VNC. + +Let's just silently exit; while we could change LOG_ERR -> LOG_INFO +or something, that's still pointless noise in most people's syslog. + +Someone who was debugging a misconfigured SPICE setup would pretty +quickly notice that they were missing the virtio port. + +(This patch is part of a larger initiative to reduce error + spew on default startup in common deployment scenarios such as + KVM+VNC.) + +Signed-off-by: Hans de Goede +--- + src/vdagent.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/src/vdagent.c b/src/vdagent.c +index 9e238d3..10ebf6e 100644 +--- a/src/vdagent.c ++++ b/src/vdagent.c +@@ -226,9 +226,7 @@ int main(int argc, char *argv[]) + LOG_USER); + + if (file_test(portdev) != 0) { +- syslog(LOG_ERR, "Missing virtio device '%s': %s", +- portdev, strerror(errno)); +- return 1; ++ return 0; + } + + if (do_daemonize) diff --git a/SOURCES/0005-vdagent-x11-Release-clipboard-on-client-disconnect-i.patch b/SOURCES/0005-vdagent-x11-Release-clipboard-on-client-disconnect-i.patch new file mode 100644 index 0000000..1970d64 --- /dev/null +++ b/SOURCES/0005-vdagent-x11-Release-clipboard-on-client-disconnect-i.patch @@ -0,0 +1,61 @@ +From 19f3f91c041ebc4e52e8d287ba6d9c66a85af0d0 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 9 Sep 2013 15:50:39 +0200 +Subject: [PATCH] vdagent-x11: Release clipboard on client disconnect if owned + by client + +https://bugzilla.redhat.com/show_bug.cgi?id=1003977 + +Signed-off-by: Hans de Goede +--- + src/vdagent-x11.c | 10 ++++++++++ + src/vdagent-x11.h | 2 ++ + src/vdagent.c | 1 + + 3 files changed, 13 insertions(+) + +diff --git a/src/vdagent-x11.c b/src/vdagent-x11.c +index 6a58532..8287421 100644 +--- a/src/vdagent-x11.c ++++ b/src/vdagent-x11.c +@@ -1301,6 +1301,16 @@ void vdagent_x11_clipboard_release(struct vdagent_x11 *x11, uint8_t selection) + vdagent_x11_do_read(x11); + } + ++void vdagent_x11_client_disconnected(struct vdagent_x11 *x11) ++{ ++ int sel; ++ ++ for (sel = 0; sel < VD_AGENT_CLIPBOARD_SELECTION_SECONDARY; sel++) { ++ if (x11->clipboard_owner[sel] == owner_client) ++ vdagent_x11_clipboard_release(x11, sel); ++ } ++} ++ + /* Function used to determine the default location to save file-xfers, + xdg desktop dir or xdg download dir. We error on the save side and use a + whitelist approach, so any unknown desktops will end up with saving +diff --git a/src/vdagent-x11.h b/src/vdagent-x11.h +index baa4ce8..5d949f6 100644 +--- a/src/vdagent-x11.h ++++ b/src/vdagent-x11.h +@@ -46,6 +46,8 @@ void vdagent_x11_clipboard_data(struct vdagent_x11 *x11, uint8_t selection, + uint32_t type, uint8_t *data, uint32_t size); + void vdagent_x11_clipboard_release(struct vdagent_x11 *x11, uint8_t selection); + ++void vdagent_x11_client_disconnected(struct vdagent_x11 *x11); ++ + int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11); + + #endif +diff --git a/src/vdagent.c b/src/vdagent.c +index 10ebf6e..c5e09ff 100644 +--- a/src/vdagent.c ++++ b/src/vdagent.c +@@ -103,6 +103,7 @@ void daemon_read_complete(struct udscs_connection **connp, + free(data); + break; + case VDAGENTD_CLIENT_DISCONNECTED: ++ vdagent_x11_client_disconnected(x11); + vdagent_file_xfers_destroy(vdagent_file_xfers); + vdagent_file_xfers = vdagent_file_xfers_create(client, fx_dir, + fx_open_dir, debug); diff --git a/SOURCES/0007-clipboard-target_to_type-fix-inner-loop-variable-nam.patch b/SOURCES/0007-clipboard-target_to_type-fix-inner-loop-variable-nam.patch new file mode 100644 index 0000000..f82917c --- /dev/null +++ b/SOURCES/0007-clipboard-target_to_type-fix-inner-loop-variable-nam.patch @@ -0,0 +1,25 @@ +From aff972e4123aa9288a19c34d0e704972e29dd630 Mon Sep 17 00:00:00 2001 +From: Uri Lublin +Date: Wed, 27 Nov 2013 18:38:07 +0200 +Subject: [PATCH] clipboard target_to_type: fix inner loop variable name + +(cherry picked from commit 29022fdc3b70d9cd4a89d5505be989b94aa466b3) + +https://bugzilla.redhat.com/show_bug.cgi?id=1117764 +--- + src/vdagent-x11.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/vdagent-x11.c b/src/vdagent-x11.c +index 8287421..8781d5e 100644 +--- a/src/vdagent-x11.c ++++ b/src/vdagent-x11.c +@@ -753,7 +753,7 @@ static uint32_t vdagent_x11_target_to_type(struct vdagent_x11 *x11, + int i, j; + + for (i = 0; i < clipboard_format_count; i++) { +- for (j = 0; j < x11->clipboard_formats[i].atom_count; i++) { ++ for (j = 0; j < x11->clipboard_formats[i].atom_count; j++) { + if (x11->clipboard_formats[i].atoms[j] == target) { + return x11->clipboard_formats[i].type; + } diff --git a/SOURCES/0008-Reply-to-TIMESTAMP-requests.patch b/SOURCES/0008-Reply-to-TIMESTAMP-requests.patch new file mode 100644 index 0000000..b757866 --- /dev/null +++ b/SOURCES/0008-Reply-to-TIMESTAMP-requests.patch @@ -0,0 +1,60 @@ +From ad6ddbe2857cfc7e7c8657b1eefb91f305012ef5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Tue, 15 Jul 2014 13:17:09 +0200 +Subject: [PATCH] Reply to TIMESTAMP requests + +Add TIMESTAMP handling, +This is to please vncviewer. + +https://bugzilla.redhat.com/show_bug.cgi?id=1117764 +(cherry picked from commit b87fab52eb825429e5393ac4c2c073c918d8ed8f) +--- + src/vdagent-x11-priv.h | 1 + + src/vdagent-x11.c | 15 +++++++++++++++ + 2 files changed, 16 insertions(+) + +diff --git a/src/vdagent-x11-priv.h b/src/vdagent-x11-priv.h +index c607850..4a5729b 100644 +--- a/src/vdagent-x11-priv.h ++++ b/src/vdagent-x11-priv.h +@@ -83,6 +83,7 @@ struct vdagent_x11 { + Atom targets_atom; + Atom incr_atom; + Atom multiple_atom; ++ Atom timestamp_atom; + Window root_window[MAX_SCREENS]; + Window selection_window; + struct udscs_connection *vdagentd; +diff --git a/src/vdagent-x11.c b/src/vdagent-x11.c +index 8781d5e..5ac2cf7 100644 +--- a/src/vdagent-x11.c ++++ b/src/vdagent-x11.c +@@ -218,6 +218,7 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd, + x11->targets_atom = XInternAtom(x11->display, "TARGETS", False); + x11->incr_atom = XInternAtom(x11->display, "INCR", False); + x11->multiple_atom = XInternAtom(x11->display, "MULTIPLE", False); ++ x11->timestamp_atom = XInternAtom(x11->display, "TIMESTAMP", False); + for(i = 0; i < clipboard_format_count; i++) { + x11->clipboard_formats[i].type = clipboard_format_templates[i].type; + for(j = 0; clipboard_format_templates[i].atom_names[j]; j++) { +@@ -1033,6 +1034,20 @@ static void vdagent_x11_handle_selection_request(struct vdagent_x11 *x11) + return; + } + ++ if (event->xselectionrequest.target == x11->timestamp_atom) { ++ /* TODO: use more accurate selection time */ ++ guint32 timestamp = event->xselectionrequest.time; ++ ++ XChangeProperty(x11->display, event->xselectionrequest.requestor, ++ event->xselectionrequest.property, ++ event->xselectionrequest.target, 32, PropModeReplace, ++ (guint8*)×tamp, 1); ++ vdagent_x11_send_selection_notify(x11, ++ event->xselectionrequest.property, NULL); ++ return; ++ } ++ ++ + if (event->xselectionrequest.target == x11->targets_atom) { + vdagent_x11_send_targets(x11, selection, event); + return; diff --git a/SOURCES/0009-Handle-STRING-selection-type.patch b/SOURCES/0009-Handle-STRING-selection-type.patch new file mode 100644 index 0000000..57a4619 --- /dev/null +++ b/SOURCES/0009-Handle-STRING-selection-type.patch @@ -0,0 +1,28 @@ +From cc07f85852d9dbb5e160d27804aec445f73f5833 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Tue, 15 Jul 2014 16:48:06 +0200 +Subject: [PATCH] Handle STRING selection type + +This is to please vncviewer. + +https://bugzilla.redhat.com/show_bug.cgi?id=1117764 +(cherry picked from commit 658c4d76e2aff9441614dcd09821057b9fd8c8c2) +--- + src/vdagent-x11-priv.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/vdagent-x11-priv.h b/src/vdagent-x11-priv.h +index 4a5729b..38f852e 100644 +--- a/src/vdagent-x11-priv.h ++++ b/src/vdagent-x11-priv.h +@@ -64,8 +64,8 @@ struct monitor_size { + }; + + static const struct clipboard_format_tmpl clipboard_format_templates[] = { +- { VD_AGENT_CLIPBOARD_UTF8_TEXT, { "UTF8_STRING", +- "text/plain;charset=UTF-8", "text/plain;charset=utf-8", NULL }, }, ++ { VD_AGENT_CLIPBOARD_UTF8_TEXT, { "UTF8_STRING", "text/plain;charset=UTF-8", ++ "text/plain;charset=utf-8", "STRING", NULL }, }, + { VD_AGENT_CLIPBOARD_IMAGE_PNG, { "image/png", NULL }, }, + { VD_AGENT_CLIPBOARD_IMAGE_BMP, { "image/bmp", "image/x-bmp", + "image/x-MS-bmp", "image/x-win-bitmap", NULL }, }, diff --git a/SOURCES/0010-randr-Make-resolution-changing-more-robust.patch b/SOURCES/0010-randr-Make-resolution-changing-more-robust.patch new file mode 100644 index 0000000..de59c85 --- /dev/null +++ b/SOURCES/0010-randr-Make-resolution-changing-more-robust.patch @@ -0,0 +1,140 @@ +From 5cf857175d724e399b53d9ce29d09fa7aef5bf36 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Thu, 9 Jan 2014 17:41:07 +0100 +Subject: [PATCH] randr: Make resolution changing more robust + +When running a guest using a KMS QXL driver on a RHEL6 hypervisor, +spice_vdagent would crash on resolution changes with: +X Error of failed request: BadValue (integer parameter out of range for operation) + Major opcode of failed request: 139 (RANDR) + Minor opcode of failed request: 21 (RRSetCrtcConfig) + Value in failed request: 0x0 + Serial number of failed request: 75 + Current serial number in output stream: 75 + +(if using a newer QEMU, this will not crash as the resolution codepath is +totally different, see red_dispatcher_use_client_monitors_config() in +spice-server, when using the UMS QXL driver, the crash will not happen +because of +http://cgit.freedesktop.org/xorg/driver/xf86-video-qxl/commit/?id=907d0ff0 +). + +This crash happens in vdagent_x11_set_monitor_config() because the X server +rejects the request because we are trying to set a CRTC to a size which is +bigger than the current screen (using 'screen' and 'CRTC' as in the RandR +spec at http://www.x.org/releases/X11R7.5/doc/randrproto/randrproto.txt ). + +If we resize the screen before changing the CRTCs resolution, then this +error will no longer happen. However, if we first call XRRSetScreenSize() +and then XRRSetCrtcConfig(), the call to XRRSetScreeSize() will fail when +we try to make the screen smaller as there will be active CRTCs which would +be bigger than the screen. + +In order to solve these issues, we follow the same process as what mutter +does in meta_monitor_manager_xrandr_apply_configuration() +https://git.gnome.org/browse/mutter/tree/src/core/monitor-xrandr.c#n689: + +1. we disable the CRTCs which are off and the ones which are bigger than the + size we want to set the screen to. +2. we resize the screen with a call to XRRSetScreenSize(). +3. we set each CRTCs to their new resolution. + +https://bugzilla.redhat.com/show_bug.cgi?id=1066422 +(cherry picked from commit 9ae51f3702b1fc0d2747e44474c87a818d1e8ec3) +--- + src/vdagent-x11-randr.c | 61 +++++++++++++++++++++++++++++++++++++------------ + 1 file changed, 47 insertions(+), 14 deletions(-) + +diff --git a/src/vdagent-x11-randr.c b/src/vdagent-x11-randr.c +index 5223f88..5fcfcc8 100644 +--- a/src/vdagent-x11-randr.c ++++ b/src/vdagent-x11-randr.c +@@ -688,8 +688,6 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 *x11, + VDAgentMonitorsConfig *mon_config, + int fallback) + { +- int width, height; +- int x, y; + int primary_w, primary_h; + int i, real_num_of_monitors = 0; + VDAgentMonitorsConfig *curr = NULL; +@@ -748,24 +746,38 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 *x11, + for (i = mon_config->num_of_monitors; i < x11->randr.res->noutput; i++) + xrandr_disable_output(x11, i); + ++ /* First, disable disabled CRTCs... */ + for (i = 0; i < mon_config->num_of_monitors; ++i) { + if (!monitor_enabled(&mon_config->monitors[i])) { + xrandr_disable_output(x11, i); +- continue; + } +- /* Try to create the requested resolution */ +- width = mon_config->monitors[i].width; +- height = mon_config->monitors[i].height; +- x = mon_config->monitors[i].x; +- y = mon_config->monitors[i].y; +- if (!xrandr_add_and_set(x11, i, x, y, width, height) && +- enabled_monitors(mon_config) == 1) { +- set_screen_to_best_size(x11, width, height, +- &primary_w, &primary_h); +- goto update; ++ } ++ ++ /* ... and disable the ones that would be bigger than ++ * the new RandR screen once it is resized. If they are enabled the ++ * XRRSetScreenSize call will fail with BadMatch. They will be ++ * reenabled after hanging the screen size. ++ */ ++ for (i = 0; i < curr->num_of_monitors; ++i) { ++ int width, height; ++ int x, y; ++ ++ width = curr->monitors[i].width; ++ height = curr->monitors[i].height; ++ x = curr->monitors[i].x; ++ y = curr->monitors[i].y; ++ ++ if ((x + width > primary_w) || (y + height > primary_h)) { ++ if (x11->debug) ++ syslog(LOG_DEBUG, "Disabling monitor %d: " ++ "%dx%d+%d+%d > (%d,%d)", ++ i, width, height, x, y, primary_w, primary_h); ++ ++ xrandr_disable_output(x11, i); + } + } + ++ /* Then we can resize the RandR screen. */ + if (primary_w != x11->width[0] || primary_h != x11->height[0]) { + if (x11->debug) + syslog(LOG_DEBUG, "Changing screen size to %dx%d", +@@ -793,7 +805,28 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 *x11, + } + } + +-update: ++ /* Finally, we set the new resolutions on RandR CRTCs now that the ++ * RandR screen is big enough to hold these. */ ++ for (i = 0; i < mon_config->num_of_monitors; ++i) { ++ int width, height; ++ int x, y; ++ ++ if (!monitor_enabled(&mon_config->monitors[i])) { ++ continue; ++ } ++ /* Try to create the requested resolution */ ++ width = mon_config->monitors[i].width; ++ height = mon_config->monitors[i].height; ++ x = mon_config->monitors[i].x; ++ y = mon_config->monitors[i].y; ++ if (!xrandr_add_and_set(x11, i, x, y, width, height) && ++ enabled_monitors(mon_config) == 1) { ++ set_screen_to_best_size(x11, width, height, ++ &primary_w, &primary_h); ++ break; ++ } ++ } ++ + update_randr_res(x11, + x11->randr.num_monitors != enabled_monitors(mon_config)); + x11->width[0] = primary_w; diff --git a/SOURCES/0011-Don-t-abort-if-XRRSetCrtcConfig-fails.patch b/SOURCES/0011-Don-t-abort-if-XRRSetCrtcConfig-fails.patch new file mode 100644 index 0000000..2ae000f --- /dev/null +++ b/SOURCES/0011-Don-t-abort-if-XRRSetCrtcConfig-fails.patch @@ -0,0 +1,33 @@ +From 96c00ebf666e044d0b53ad569dde3c24ce7b9b4d Mon Sep 17 00:00:00 2001 +From: Jonathon Jongsma +Date: Thu, 19 Dec 2013 11:31:21 -0600 +Subject: [PATCH] Don't abort if XRRSetCrtcConfig fails + +In certain configurations (Fedora 20 or RHEL7 guests on a RHEL6 host), this call +fails, which cause the vdagent to abort. This patch prevents the crash, though +arbitrary resizing is obviously still non-functional in this situation. + +https://bugzilla.redhat.com/show_bug.cgi?id=1066422 +(cherry picked from commit 6e2e82e6fbb8927d5154f32c83e2b95c08fef18e) +--- + src/vdagent-x11-randr.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/vdagent-x11-randr.c b/src/vdagent-x11-randr.c +index b1f9813..46367bc 100644 +--- a/src/vdagent-x11-randr.c ++++ b/src/vdagent-x11-randr.c +@@ -366,11 +366,11 @@ static int xrandr_add_and_set(struct vdagent_x11 *x11, int output, int x, int y, + x11->randr.monitor_sizes[output].width = width; + x11->randr.monitor_sizes[output].height = height; + outputs[0] = xid; ++ vdagent_x11_set_error_handler(x11, error_handler); + s = XRRSetCrtcConfig(x11->display, x11->randr.res, x11->randr.res->crtcs[output], + CurrentTime, x, y, mode->id, RR_Rotate_0, outputs, + 1); +- +- if (s != RRSetConfigSuccess) { ++ if (vdagent_x11_restore_error_handler(x11) || (s != RRSetConfigSuccess)) { + syslog(LOG_ERR, "failed to XRRSetCrtcConfig"); + x11->set_crtc_config_not_functional = 1; + return 0; diff --git a/SOURCES/0012-Fix-gdm-autostart-path.patch b/SOURCES/0012-Fix-gdm-autostart-path.patch new file mode 100644 index 0000000..6bcea11 --- /dev/null +++ b/SOURCES/0012-Fix-gdm-autostart-path.patch @@ -0,0 +1,40 @@ +From 0758938a5bd824bdd081adf543d6cab927c6d358 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Tue, 4 Feb 2014 17:57:17 +0100 +Subject: [PATCH] Fix gdm autostart path + +gdm 3.1.90 (June 2011) changed the path where .desktop files which should +be autostarted with gdm needs to be located. +This used to be $(datadir)/gdm/autostart/LoginWindow and is now +$(datadir)/gdm/greeter/autostart. +This means that when running gdm in a VM in a recent distribution, +arbitrary resizing the VM window will not cause the resolution to be +adjusted. This used to be working in eg RHEL6. + +This patch installs the .desktop file to both paths in order to work both +with older and newer gdms. + +https://bugzilla.redhat.com/show_bug.cgi?id=1052172 +(cherry picked from commit 7d858d5064fd0c26454b72bf9fe3e0472f31e34f) +--- + Makefile.am | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/Makefile.am b/Makefile.am +index 5515ca0..8a65704 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -42,9 +42,12 @@ noinst_HEADERS = src/glib-compat.h \ + xdgautostartdir = $(sysconfdir)/xdg/autostart + xdgautostart_DATA = $(top_srcdir)/data/spice-vdagent.desktop + +-gdmautostartdir = $(datadir)/gdm/autostart/LoginWindow ++gdmautostartdir = $(datadir)/gdm/greeter/autostart + gdmautostart_DATA = $(top_srcdir)/data/spice-vdagent.desktop + ++gdmautostart2dir = $(datadir)/gdm/autostart/LoginWindow ++gdmautostart2_DATA = $(top_srcdir)/data/spice-vdagent.desktop ++ + install-data-local: + $(mkdir_p) $(DESTDIR)$(localstatedir)/run/spice-vdagentd + diff --git a/SOURCES/0013-data-remove-rsyslog-config-files.patch b/SOURCES/0013-data-remove-rsyslog-config-files.patch new file mode 100644 index 0000000..84f2dfd --- /dev/null +++ b/SOURCES/0013-data-remove-rsyslog-config-files.patch @@ -0,0 +1,56 @@ +From 35fbb9fa6341ed81b5eb6a8049d1982b2ecf4aac Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Fri, 5 Sep 2014 15:16:34 +0200 +Subject: [PATCH] data: remove rsyslog config files + +Many systems don't use rsyslog, others don't need seperate syslog files +for vdagent. + +With systemd journal, It's possible to filter +spice-vdagent/spice-vdagentd log messages out of /var/log/messages: +journalctl SYSLOG_IDENTIFIER=spice-vdagent SLOG_IDENTIFIER=spice-vdagentd + +This simplify spice-vdagent packaging and updates, since there are no +config files to deal with. + +Related: +https://bugzilla.redhat.com/show_bug.cgi?id=1136881 +(cherry picked from commit 072fb03fa47b18dd6cdd3b5c764d59e06fc5815e) +--- + Makefile.am | 4 ---- + data/rsyslog.d/spice-vdagentd.conf | 4 ---- + 2 files changed, 8 deletions(-) + delete mode 100644 data/rsyslog.d/spice-vdagentd.conf + +diff --git a/Makefile.am b/Makefile.am +index 8a65704..a06a259 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -51,9 +51,6 @@ gdmautostart2_DATA = $(top_srcdir)/data/spice-vdagent.desktop + install-data-local: + $(mkdir_p) $(DESTDIR)$(localstatedir)/run/spice-vdagentd + +-rsyslogdir = $(sysconfdir)/rsyslog.d +-rsyslog_DATA = $(top_srcdir)/data/rsyslog.d/spice-vdagentd.conf +- + if INIT_SCRIPT_RED_HAT + initdir = $(sysconfdir)/rc.d/init.d + init_SCRIPTS = $(top_srcdir)/data/spice-vdagentd +@@ -83,7 +80,6 @@ EXTRA_DIST = \ + README.RHEL-5 \ + data/70-spice-vdagentd.rules \ + data/modules-load.d/spice-vdagentd.conf \ +- data/rsyslog.d/spice-vdagentd.conf \ + data/spice-vdagent.desktop \ + data/spice-vdagentd \ + data/spice-vdagentd.service \ +diff --git a/data/rsyslog.d/spice-vdagentd.conf b/data/rsyslog.d/spice-vdagentd.conf +deleted file mode 100644 +index 2437ba0..0000000 +--- a/data/rsyslog.d/spice-vdagentd.conf ++++ /dev/null +@@ -1,4 +0,0 @@ +-# A template to for higher precision timestamps + severity logging +-$template SpiceTmpl,"%TIMESTAMP%.%TIMESTAMP:::date-subseconds% %syslogtag% %syslogseverity-text%:%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" +- +-:programname, startswith, "spice-vdagent" /var/log/spice-vdagent.log;SpiceTmpl diff --git a/SOURCES/0014-vdagent-file-xfers-only-open-the-file-transfer-dir-w.patch b/SOURCES/0014-vdagent-file-xfers-only-open-the-file-transfer-dir-w.patch new file mode 100644 index 0000000..1aa907a --- /dev/null +++ b/SOURCES/0014-vdagent-file-xfers-only-open-the-file-transfer-dir-w.patch @@ -0,0 +1,30 @@ +From 6705c11d7ec4808e2dc70e7a4875323e2dfd0f62 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= +Date: Thu, 28 Aug 2014 16:24:04 +0200 +Subject: [PATCH] vdagent-file-xfers: only open the file transfer dir when all + the files were transferred + +Once transferring multiple files is supported, do not bother the user +opening the file transfer directory for each file transferred, just do it +when the last file transfer is finished. +--- + src/vdagent-file-xfers.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/vdagent-file-xfers.c b/src/vdagent-file-xfers.c +index b792282..4dea6de 100644 +--- a/src/vdagent-file-xfers.c ++++ b/src/vdagent-file-xfers.c +@@ -282,7 +282,8 @@ void vdagent_file_xfers_data(struct vdagent_file_xfers *xfers, + close(task->file_fd); + task->file_fd = -1; + if (xfers->open_save_dir && +- task->file_xfer_nr == task->file_xfer_total) { ++ task->file_xfer_nr == task->file_xfer_total && ++ g_hash_table_size(xfers->xfers) == 1) { + char buf[PATH_MAX]; + snprintf(buf, PATH_MAX, "xdg-open '%s'&", xfers->save_dir); + status = system(buf); +-- +2.1.0 + diff --git a/SOURCES/0015-audio-add-functions-to-set-volume-mute-with-alsa.patch b/SOURCES/0015-audio-add-functions-to-set-volume-mute-with-alsa.patch new file mode 100644 index 0000000..d901932 --- /dev/null +++ b/SOURCES/0015-audio-add-functions-to-set-volume-mute-with-alsa.patch @@ -0,0 +1,269 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Fri, 6 Mar 2015 18:14:21 +0100 +Subject: [PATCH] audio: add functions to set volume/mute with alsa + +This patch includes the vdagent-audio.[ch] files in order to +communicate with backend audio server. + +The two functions provide a way to set volume and mute in the guest +by connecting to default mixer control in alsa which is 'Master' for +playback and 'Capture' for record. +--- + Makefile.am | 12 +++- + configure.ac | 1 + + src/vdagent-audio.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/vdagent-audio.h | 27 +++++++++ + 4 files changed, 205 insertions(+), 3 deletions(-) + create mode 100644 src/vdagent-audio.c + create mode 100644 src/vdagent-audio.h + +diff --git a/Makefile.am b/Makefile.am +index a06a259..2effe4e 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -4,9 +4,14 @@ NULL = + bin_PROGRAMS = src/spice-vdagent + sbin_PROGRAMS = src/spice-vdagentd + +-src_spice_vdagent_CFLAGS = $(X_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) +-src_spice_vdagent_LDADD = $(X_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) +-src_spice_vdagent_SOURCES = src/vdagent.c src/vdagent-x11.c src/vdagent-x11-randr.c src/vdagent-file-xfers.c src/udscs.c ++src_spice_vdagent_CFLAGS = $(X_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) $(ALSA_CFLAGS) ++src_spice_vdagent_LDADD = $(X_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) $(ALSA_LIBS) ++src_spice_vdagent_SOURCES = src/vdagent.c \ ++ src/vdagent-x11.c \ ++ src/vdagent-x11-randr.c \ ++ src/vdagent-file-xfers.c \ ++ src/vdagent-audio.c \ ++ src/udscs.c + + src_spice_vdagentd_CFLAGS = $(DBUS_CFLAGS) $(LIBSYSTEMD_LOGIN_CFLAGS) \ + $(PCIACCESS_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) $(PIE_CFLAGS) +@@ -30,6 +35,7 @@ endif + noinst_HEADERS = src/glib-compat.h \ + src/session-info.h \ + src/udscs.h \ ++ src/vdagent-audio.h \ + src/vdagent-file-xfers.h \ + src/vdagent-virtio-port.h \ + src/vdagent-x11.h \ +diff --git a/configure.ac b/configure.ac +index a1ce6c0..377fc74 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -79,6 +79,7 @@ AC_ARG_ENABLE([static-uinput], + PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.12]) + PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11]) + PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.5]) ++PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22]) + + if test "$with_session_info" = "auto" || test "$with_session_info" = "systemd"; then + PKG_CHECK_MODULES([LIBSYSTEMD_LOGIN], +diff --git a/src/vdagent-audio.c b/src/vdagent-audio.c +new file mode 100644 +index 0000000..6b11cd8 +--- /dev/null ++++ b/src/vdagent-audio.c +@@ -0,0 +1,168 @@ ++/* vdagent-audio.c vdagentd audio handling code ++ ++ Copyright 2015 Red Hat, Inc. ++ ++ This program is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "vdagent-audio.h" ++ ++#define ALSA_MUTE 0 ++#define ALSA_UNMUTE 1 ++ ++static snd_mixer_elem_t * ++get_alsa_default_mixer_by_name(snd_mixer_t **handle, const char *name) ++{ ++ snd_mixer_selem_id_t *sid; ++ int err = 0; ++ ++ if ((err = snd_mixer_open(handle, 0)) < 0) ++ goto fail; ++ ++ if ((err = snd_mixer_attach(*handle, "default")) < 0) ++ goto fail; ++ ++ if ((err = snd_mixer_selem_register(*handle, NULL, NULL)) < 0) ++ goto fail; ++ ++ if ((err = snd_mixer_load(*handle)) < 0) ++ goto fail; ++ ++ snd_mixer_selem_id_alloca(&sid); ++ snd_mixer_selem_id_set_index(sid, 0); ++ snd_mixer_selem_id_set_name(sid, name); ++ return snd_mixer_find_selem(*handle, sid); ++ ++fail: ++ syslog(LOG_WARNING, "%s fail: %s", __func__, snd_strerror(err)); ++ return NULL; ++} ++ ++static bool set_alsa_capture(uint8_t mute, uint8_t nchannels, uint16_t *volume) ++{ ++ snd_mixer_t *handle = NULL; ++ snd_mixer_elem_t *e; ++ long min, max, vol; ++ bool ret = true; ++ int alsa_mute; ++ ++ e = get_alsa_default_mixer_by_name (&handle, "Capture"); ++ if (e == NULL) { ++ syslog(LOG_WARNING, "vdagent-audio: can't get default alsa mixer"); ++ ret = false; ++ goto end; ++ } ++ ++ alsa_mute = (mute) ? ALSA_MUTE : ALSA_UNMUTE; ++ snd_mixer_selem_set_capture_switch_all(e, alsa_mute); ++ ++ snd_mixer_selem_get_capture_volume_range(e, &min, &max); ++ switch (nchannels) { ++ case 1: /* MONO */ ++ vol = CLAMP(volume[0], min, max); ++ snd_mixer_selem_set_capture_volume(e, SND_MIXER_SCHN_MONO, vol); ++ syslog(LOG_DEBUG, "vdagent-audio: (capture-mono) %lu (%%%0.2f)", ++ vol, (float) (100*vol/max)); ++ break; ++ case 2: /* LEFT-RIGHT */ ++ vol = CLAMP(volume[0], min, max); ++ snd_mixer_selem_set_capture_volume(e, SND_MIXER_SCHN_FRONT_LEFT, vol); ++ syslog(LOG_DEBUG, "vdagent-audio: (capture-left) %lu (%%%0.2f)", ++ vol, (float) (100*vol/max)); ++ vol = CLAMP(volume[1], min, max); ++ snd_mixer_selem_set_capture_volume(e, SND_MIXER_SCHN_FRONT_RIGHT, vol); ++ syslog(LOG_DEBUG, "vdagent-audio: (capture-right) %lu (%%%0.2f)", ++ vol, (float) (100*vol/max)); ++ break; ++ default: ++ syslog(LOG_WARNING, "vdagent-audio: number of channels not supported"); ++ ret = false; ++ } ++end: ++ if (handle != NULL) ++ snd_mixer_close(handle); ++ return ret; ++} ++ ++static bool set_alsa_playback (uint8_t mute, uint8_t nchannels, uint16_t *volume) ++{ ++ snd_mixer_t *handle = NULL; ++ snd_mixer_elem_t* e; ++ long min, max, vol; ++ bool ret = true; ++ int alsa_mute; ++ ++ e = get_alsa_default_mixer_by_name (&handle, "Master"); ++ if (e == NULL) { ++ syslog(LOG_WARNING, "vdagent-audio: can't get default alsa mixer"); ++ ret = false; ++ goto end; ++ } ++ ++ alsa_mute = (mute) ? ALSA_MUTE : ALSA_UNMUTE; ++ snd_mixer_selem_set_playback_switch_all(e, alsa_mute); ++ ++ snd_mixer_selem_get_playback_volume_range(e, &min, &max); ++ switch (nchannels) { ++ case 1: /* MONO */ ++ vol = CLAMP(volume[0], min, max); ++ snd_mixer_selem_set_playback_volume(e, SND_MIXER_SCHN_MONO, vol); ++ syslog(LOG_DEBUG, "vdagent-audio: (playback-mono) %lu (%%%0.2f)", ++ vol, (float) (100*vol/max)); ++ break; ++ case 2: /* LEFT-RIGHT */ ++ vol = CLAMP(volume[0], min, max); ++ snd_mixer_selem_set_playback_volume(e, SND_MIXER_SCHN_FRONT_LEFT, vol); ++ syslog(LOG_DEBUG, "vdagent-audio: (playback-left) %lu (%%%0.2f)", ++ vol, (float) (100*vol/max)); ++ vol = CLAMP(volume[1], min, max); ++ snd_mixer_selem_set_playback_volume(e, SND_MIXER_SCHN_FRONT_RIGHT, vol); ++ syslog(LOG_DEBUG, "vdagent-audio: (playback-right) %lu (%%%0.2f)", ++ vol, (float) (100*vol/max)); ++ break; ++ default: ++ syslog(LOG_WARNING, "vdagent-audio: number of channels not supported"); ++ ret = false; ++ } ++end: ++ if (handle != NULL) ++ snd_mixer_close(handle); ++ return ret; ++} ++ ++void vdagent_audio_playback_sync(uint8_t mute, uint8_t nchannels, uint16_t *volume) ++{ ++ syslog(LOG_DEBUG, "%s mute=%s nchannels=%u", ++ __func__, (mute) ? "yes" : "no", nchannels); ++ if (set_alsa_playback (mute, nchannels, volume) == false) ++ syslog(LOG_WARNING, "Fail to sync playback volume"); ++} ++ ++void vdagent_audio_record_sync(uint8_t mute, uint8_t nchannels, uint16_t *volume) ++{ ++ syslog(LOG_DEBUG, "%s mute=%s nchannels=%u", ++ __func__, (mute) ? "yes" : "no", nchannels); ++ if (set_alsa_capture (mute, nchannels, volume) == false) ++ syslog(LOG_WARNING, "Fail to sync record volume"); ++} +diff --git a/src/vdagent-audio.h b/src/vdagent-audio.h +new file mode 100644 +index 0000000..6f29d4b +--- /dev/null ++++ b/src/vdagent-audio.h +@@ -0,0 +1,27 @@ ++/* vdagent-audio.h vdagentd audio handling header ++ ++ Copyright 2015 Red Hat, Inc. ++ ++ This program is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++#ifndef __VDAGENT_AUDIO_H ++#define __VDAGENT_AUDIO_H ++ ++#include ++#include ++ ++void vdagent_audio_playback_sync(uint8_t mute, uint8_t nchannels, uint16_t *volume); ++void vdagent_audio_record_sync(uint8_t mute, uint8_t nchannels, uint16_t *volume); ++ ++#endif diff --git a/SOURCES/0016-vdagent-volume-synchronization-from-client.patch b/SOURCES/0016-vdagent-volume-synchronization-from-client.patch new file mode 100644 index 0000000..368719c --- /dev/null +++ b/SOURCES/0016-vdagent-volume-synchronization-from-client.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Fri, 6 Mar 2015 18:15:35 +0100 +Subject: [PATCH] vdagent: volume synchronization from client. + +Include the capability of volume sync to set volume or mute to default +sink-input/source-output of guest. +--- + src/vdagent.c | 11 +++++++++++ + src/vdagentd-proto.h | 1 + + src/vdagentd.c | 21 +++++++++++++++++++++ + 3 files changed, 33 insertions(+) + +diff --git a/src/vdagent.c b/src/vdagent.c +index c5e09ff..a26af73 100644 +--- a/src/vdagent.c ++++ b/src/vdagent.c +@@ -39,6 +39,7 @@ + #include "udscs.h" + #include "vdagentd-proto.h" + #include "vdagentd-proto-strings.h" ++#include "vdagent-audio.h" + #include "vdagent-x11.h" + #include "vdagent-file-xfers.h" + +@@ -97,6 +98,16 @@ void daemon_read_complete(struct udscs_connection **connp, + (VDAgentFileXferStatusMessage *)data); + free(data); + break; ++ case VDAGENTD_AUDIO_VOLUME_SYNC: { ++ VDAgentAudioVolumeSync *avs = (VDAgentAudioVolumeSync *)data; ++ if (avs->is_playback) { ++ vdagent_audio_playback_sync(avs->mute, avs->nchannels, avs->volume); ++ } else { ++ vdagent_audio_record_sync(avs->mute, avs->nchannels, avs->volume); ++ } ++ free(data); ++ break; ++ } + case VDAGENTD_FILE_XFER_DATA: + vdagent_file_xfers_data(vdagent_file_xfers, + (VDAgentFileXferDataMessage *)data); +diff --git a/src/vdagentd-proto.h b/src/vdagentd-proto.h +index 25e6a36..0dbaaea 100644 +--- a/src/vdagentd-proto.h ++++ b/src/vdagentd-proto.h +@@ -36,6 +36,7 @@ enum { + VDAGENTD_CLIPBOARD_DATA, /* arg1: sel, arg 2: type, data: data */ + VDAGENTD_CLIPBOARD_RELEASE, /* arg1: selection */ + VDAGENTD_VERSION, /* daemon -> client, data: version string */ ++ VDAGENTD_AUDIO_VOLUME_SYNC, + VDAGENTD_FILE_XFER_START, + VDAGENTD_FILE_XFER_STATUS, + VDAGENTD_FILE_XFER_DATA, +diff --git a/src/vdagentd.c b/src/vdagentd.c +index 6280dfa..594f36b 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -96,6 +96,7 @@ static void send_capabilities(struct vdagent_virtio_port *vport, + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_SELECTION); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_SPARSE_MONITORS_CONFIG); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GUEST_LINEEND_LF); ++ VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_AUDIO_VOLUME_SYNC); + + vdagent_virtio_port_write(vport, VDP_CLIENT_PORT, + VD_AGENT_ANNOUNCE_CAPABILITIES, 0, +@@ -151,6 +152,19 @@ static void do_client_monitors(struct vdagent_virtio_port *vport, int port_nr, + (uint8_t *)&reply, sizeof(reply)); + } + ++static void do_client_volume_sync(struct vdagent_virtio_port *vport, int port_nr, ++ VDAgentMessage *message_header, ++ VDAgentAudioVolumeSync *avs) ++{ ++ if (active_session_conn == NULL) { ++ syslog(LOG_DEBUG, "No active session - Can't volume-sync"); ++ return; ++ } ++ ++ udscs_write(active_session_conn, VDAGENTD_AUDIO_VOLUME_SYNC, 0, 0, ++ (uint8_t *)avs, message_header->size); ++} ++ + static void do_client_capabilities(struct vdagent_virtio_port *vport, + VDAgentMessage *message_header, + VDAgentAnnounceCapabilities *caps) +@@ -366,6 +380,13 @@ int virtio_port_read_complete( + vdagent_virtio_port_reset(vport, VDP_CLIENT_PORT); + do_client_disconnect(); + break; ++ case VD_AGENT_AUDIO_VOLUME_SYNC: ++ if (message_header->size < sizeof(VDAgentAudioVolumeSync)) ++ goto size_error; ++ ++ do_client_volume_sync(vport, port_nr, message_header, ++ (VDAgentAudioVolumeSync *)data); ++ break; + default: + syslog(LOG_WARNING, "unknown message type %d, ignoring", + message_header->type); diff --git a/SOURCES/0017-vdagentd-proto-strings-Add-missing-string-for-VDAGEN.patch b/SOURCES/0017-vdagentd-proto-strings-Add-missing-string-for-VDAGEN.patch new file mode 100644 index 0000000..c00c6e3 --- /dev/null +++ b/SOURCES/0017-vdagentd-proto-strings-Add-missing-string-for-VDAGEN.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Pavel Grunt +Date: Tue, 28 Apr 2015 11:09:28 +0200 +Subject: [PATCH] vdagentd-proto-strings: Add missing string for + VDAGENTD_AUDIO_VOLUME_SYNC + +Avoids a crash when running spice-vdagent with debug + +Backtrace: + + #0 0x0000003dcf647e2c in _IO_vfprintf_internal (s=, format=, ap=) at vfprintf.c:1641 + #1 0x0000003dcf6e4e90 in __vsyslog_chk (pri=, flag=-1, fmt=0x40f360 "%p received %s, arg1: %u, arg2: %u, size %u", ap=0x7fffffffddc0) at ../misc/syslog.c:222 + #2 0x0000003dcf6e50c0 in __syslog (pri=, fmt=) at ../misc/syslog.c:119 + #3 0x000000000040c6da in udscs_read_complete (connp=0x610de8) at src/udscs.c:448 + #4 0x000000000040c8d1 in udscs_do_read (connp=0x610de8) at src/udscs.c:500 + #5 0x000000000040c303 in udscs_client_handle_fds (connp=0x610de8, readfds=0x7fffffffe0a0, writefds=0x7fffffffe020) at src/udscs.c:349 + #6 0x0000000000403d74 in main (argc=3, argv=0x7fffffffe248) at src/vdagent.c:365 +--- + src/vdagentd-proto-strings.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/vdagentd-proto-strings.h b/src/vdagentd-proto-strings.h +index e76cb3b..a3fbd32 100644 +--- a/src/vdagentd-proto-strings.h ++++ b/src/vdagentd-proto-strings.h +@@ -30,6 +30,7 @@ static const char * const vdagentd_messages[] = { + "clipboard data", + "clipboard release", + "version", ++ "audio volume sync", + "file xfer start", + "file xfer status", + "file xfer data", diff --git a/SOURCES/0018-vdagent-Return-1-when-virtio-device-cannot-be-opened.patch b/SOURCES/0018-vdagent-Return-1-when-virtio-device-cannot-be-opened.patch new file mode 100644 index 0000000..b8efe4b --- /dev/null +++ b/SOURCES/0018-vdagent-Return-1-when-virtio-device-cannot-be-opened.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Mon, 7 Sep 2015 16:38:10 +0200 +Subject: [PATCH] vdagent: Return '1' when virtio device cannot be opened + +The vdagent process currently exits with an error code set to 0 whenn +the virtio device cannot be opened (for example because it's missing). +This is not consistent with the other failures to startup which set the +exit code to 1. This commit ensures 1 is returned in this situation too. + +Resolves: rhbz#1256704 +--- + src/vdagent.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/vdagent.c b/src/vdagent.c +index a26af73..1336faa 100644 +--- a/src/vdagent.c ++++ b/src/vdagent.c +@@ -238,7 +238,8 @@ int main(int argc, char *argv[]) + LOG_USER); + + if (file_test(portdev) != 0) { +- return 0; ++ syslog(LOG_ERR, "Cannot access vdagent virtio channel %s", portdev); ++ return 1; + } + + if (do_daemonize) diff --git a/SOURCES/0019-build-sys-Enable-large-file-support.patch b/SOURCES/0019-build-sys-Enable-large-file-support.patch new file mode 100644 index 0000000..f43db79 --- /dev/null +++ b/SOURCES/0019-build-sys-Enable-large-file-support.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Thu, 9 Apr 2015 17:24:40 +0200 +Subject: [PATCH] build-sys: Enable large file support + +This is needed on 32 bit machines for drag and drop of large files (>2GB +to work). This fixes https://bugzilla.redhat.com/show_bug.cgi?id=1206663 +--- + configure.ac | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/configure.ac b/configure.ac +index 377fc74..9f9d34c 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -10,6 +10,7 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) + AC_PROG_CC + AM_PROG_CC_C_O + AC_HEADER_STDC ++AC_SYS_LARGEFILE + AC_PROG_INSTALL + AC_PROG_LN_S + AC_DEFINE(_GNU_SOURCE, [1], [Enable GNU extensions]) diff --git a/SOURCES/0020-Add-g_return_if_fail-guards-to-file-xfer-public-func.patch b/SOURCES/0020-Add-g_return_if_fail-guards-to-file-xfer-public-func.patch new file mode 100644 index 0000000..eeb5de9 --- /dev/null +++ b/SOURCES/0020-Add-g_return_if_fail-guards-to-file-xfer-public-func.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Thu, 27 Feb 2014 18:45:15 +0100 +Subject: [PATCH] Add g_return_if_fail() guards to file xfer public functions + +With the next commit, we won't always have a file xfer object available. +This next commit will make sure NULL is never passed to the public file +xfer functions, but it's safer to guard against that anyway in case +this gets broken in the future. + +(cherry picked from commit ec9f11064efee2ad3f0be0d36f5fdbbbe2d51ad9) +--- + src/vdagent-file-xfers.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/src/vdagent-file-xfers.c b/src/vdagent-file-xfers.c +index 4dea6de..d59910b 100644 +--- a/src/vdagent-file-xfers.c ++++ b/src/vdagent-file-xfers.c +@@ -97,6 +97,8 @@ struct vdagent_file_xfers *vdagent_file_xfers_create( + + void vdagent_file_xfers_destroy(struct vdagent_file_xfers *xfers) + { ++ g_return_if_fail(xfers != NULL); ++ + g_hash_table_destroy(xfers->xfers); + g_free(xfers->save_dir); + g_free(xfers); +@@ -107,6 +109,8 @@ AgentFileXferTask *vdagent_file_xfers_get_task( + { + AgentFileXferTask *task; + ++ g_return_val_if_fail(xfers != NULL, NULL); ++ + task = g_hash_table_lookup(xfers->xfers, GUINT_TO_POINTER(id)); + if (task == NULL) + syslog(LOG_ERR, "file-xfer: error can not find task %u", id); +@@ -173,6 +177,8 @@ void vdagent_file_xfers_start(struct vdagent_file_xfers *xfers, + struct stat st; + int i; + ++ g_return_if_fail(xfers != NULL); ++ + if (g_hash_table_lookup(xfers->xfers, GUINT_TO_POINTER(msg->id))) { + syslog(LOG_ERR, "file-xfer: error id %u already exists, ignoring!", + msg->id); +@@ -246,6 +252,8 @@ void vdagent_file_xfers_status(struct vdagent_file_xfers *xfers, + { + AgentFileXferTask *task; + ++ g_return_if_fail(xfers != NULL); ++ + task = vdagent_file_xfers_get_task(xfers, msg->id); + if (!task) + return; +@@ -267,6 +275,8 @@ void vdagent_file_xfers_data(struct vdagent_file_xfers *xfers, + AgentFileXferTask *task; + int len, status = -1; + ++ g_return_if_fail(xfers != NULL); ++ + task = vdagent_file_xfers_get_task(xfers, msg->id); + if (!task) + return; diff --git a/SOURCES/0021-Make-creation-of-vdagent_file_xfers-optional.patch b/SOURCES/0021-Make-creation-of-vdagent_file_xfers-optional.patch new file mode 100644 index 0000000..fcb5cc8 --- /dev/null +++ b/SOURCES/0021-Make-creation-of-vdagent_file_xfers-optional.patch @@ -0,0 +1,76 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Thu, 27 Feb 2014 18:45:24 +0100 +Subject: [PATCH] Make creation of 'vdagent_file_xfers' optional + +This commit only adds if (vdagent_file_xfers != NULL) {} checks before +calling into the file transfer code. This allows to disable file transfer +handling by setting this variable to NULL. + +(cherry picked from commit 7fc4525dcedb280d22feabcd577ec84e5781960f) +--- + src/vdagent.c | 30 ++++++++++++++++++++---------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +diff --git a/src/vdagent.c b/src/vdagent.c +index 1336faa..9586432 100644 +--- a/src/vdagent.c ++++ b/src/vdagent.c +@@ -89,13 +89,17 @@ void daemon_read_complete(struct udscs_connection **connp, + } + break; + case VDAGENTD_FILE_XFER_START: +- vdagent_file_xfers_start(vdagent_file_xfers, +- (VDAgentFileXferStartMessage *)data); ++ if (vdagent_file_xfers != NULL) { ++ vdagent_file_xfers_start(vdagent_file_xfers, ++ (VDAgentFileXferStartMessage *)data); ++ } + free(data); + break; + case VDAGENTD_FILE_XFER_STATUS: +- vdagent_file_xfers_status(vdagent_file_xfers, +- (VDAgentFileXferStatusMessage *)data); ++ if (vdagent_file_xfers != NULL) { ++ vdagent_file_xfers_status(vdagent_file_xfers, ++ (VDAgentFileXferStatusMessage *)data); ++ } + free(data); + break; + case VDAGENTD_AUDIO_VOLUME_SYNC: { +@@ -109,15 +113,19 @@ void daemon_read_complete(struct udscs_connection **connp, + break; + } + case VDAGENTD_FILE_XFER_DATA: +- vdagent_file_xfers_data(vdagent_file_xfers, +- (VDAgentFileXferDataMessage *)data); ++ if (vdagent_file_xfers != NULL) { ++ vdagent_file_xfers_data(vdagent_file_xfers, ++ (VDAgentFileXferDataMessage *)data); ++ } + free(data); + break; + case VDAGENTD_CLIENT_DISCONNECTED: + vdagent_x11_client_disconnected(x11); +- vdagent_file_xfers_destroy(vdagent_file_xfers); +- vdagent_file_xfers = vdagent_file_xfers_create(client, fx_dir, +- fx_open_dir, debug); ++ if (vdagent_file_xfers != NULL) { ++ vdagent_file_xfers_destroy(vdagent_file_xfers); ++ vdagent_file_xfers = vdagent_file_xfers_create(client, fx_dir, ++ fx_open_dir, debug); ++ } + break; + default: + syslog(LOG_ERR, "Unknown message from vdagentd type: %d, ignoring", +@@ -305,7 +313,9 @@ reconnect: + udscs_client_handle_fds(&client, &readfds, &writefds); + } + +- vdagent_file_xfers_destroy(vdagent_file_xfers); ++ if (vdagent_file_xfers != NULL) { ++ vdagent_file_xfers_destroy(vdagent_file_xfers); ++ } + vdagent_x11_destroy(x11, client == NULL); + udscs_destroy_connection(&client); + if (!quit && do_daemonize) diff --git a/SOURCES/0022-Disable-file-xfer-when-no-suitable-destination-dir.patch b/SOURCES/0022-Disable-file-xfer-when-no-suitable-destination-dir.patch new file mode 100644 index 0000000..be5164e --- /dev/null +++ b/SOURCES/0022-Disable-file-xfer-when-no-suitable-destination-dir.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Thu, 27 Mar 2014 18:04:59 +0100 +Subject: [PATCH] Disable file xfer when no suitable destination dir + +Currently, if no suitable destination directory can be found, the file +transfer code defaults to using '.' as the destination directory. As this +is unlikely to work, better to just disable file transfers when we end up +in such a situation. This currently happens when spawning spice-vdagent +from gdm where we don't want file transfers to be available anyway. + +(cherry picked from commit 689dcd35edb55abcdef4d30d92fdcca22d81ee23) +--- + src/vdagent.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/src/vdagent.c b/src/vdagent.c +index 9586432..32c84e5 100644 +--- a/src/vdagent.c ++++ b/src/vdagent.c +@@ -282,13 +282,14 @@ reconnect: + fx_dir = g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP); + else if (!strcmp(fx_dir, "xdg-download")) + fx_dir = g_get_user_special_dir(G_USER_DIRECTORY_DOWNLOAD); +- if (!fx_dir) { ++ if (fx_dir) { ++ vdagent_file_xfers = vdagent_file_xfers_create(client, fx_dir, ++ fx_open_dir, debug); ++ } else { + syslog(LOG_WARNING, +- "warning could not get file xfer save dir, using cwd"); +- fx_dir = "."; ++ "warning could not get file xfer save dir, file transfers will be disabled"); ++ vdagent_file_xfers = NULL; + } +- vdagent_file_xfers = vdagent_file_xfers_create(client, fx_dir, +- fx_open_dir, debug); + + while (client && !quit) { + FD_ZERO(&readfds); diff --git a/SOURCES/0023-Report-an-error-when-file-transfers-are-disabled.patch b/SOURCES/0023-Report-an-error-when-file-transfers-are-disabled.patch new file mode 100644 index 0000000..6ba40a9 --- /dev/null +++ b/SOURCES/0023-Report-an-error-when-file-transfers-are-disabled.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Tue, 8 Apr 2014 16:11:38 +0200 +Subject: [PATCH] Report an error when file transfers are disabled + +This commit sends back a VD_AGENT_FILE_XFER_STATUS_ERROR to clients which +try to transfer files when the agent disabled file transfers (for example +because there is no valid destination directory for the transferred files). + +(cherry picked from commit 9ea18740b8cf4466ebd2f6bca42d1d70dd0ba01c) +--- + src/vdagent-file-xfers.c | 8 ++++++++ + src/vdagent-file-xfers.h | 2 ++ + src/vdagent.c | 9 +++++++++ + 3 files changed, 19 insertions(+) + +diff --git a/src/vdagent-file-xfers.c b/src/vdagent-file-xfers.c +index d59910b..0dc549b 100644 +--- a/src/vdagent-file-xfers.c ++++ b/src/vdagent-file-xfers.c +@@ -316,3 +316,11 @@ void vdagent_file_xfers_data(struct vdagent_file_xfers *xfers, + g_hash_table_remove(xfers->xfers, GUINT_TO_POINTER(msg->id)); + } + } ++ ++void vdagent_file_xfers_error(struct udscs_connection *vdagentd, uint32_t msg_id) ++{ ++ g_return_if_fail(vdagentd != NULL); ++ ++ udscs_write(vdagentd, VDAGENTD_FILE_XFER_STATUS, ++ msg_id, VD_AGENT_FILE_XFER_STATUS_ERROR, NULL, 0); ++} +diff --git a/src/vdagent-file-xfers.h b/src/vdagent-file-xfers.h +index 20783eb..fe5da81 100644 +--- a/src/vdagent-file-xfers.h ++++ b/src/vdagent-file-xfers.h +@@ -37,5 +37,7 @@ void vdagent_file_xfers_status(struct vdagent_file_xfers *xfers, + VDAgentFileXferStatusMessage *msg); + void vdagent_file_xfers_data(struct vdagent_file_xfers *xfers, + VDAgentFileXferDataMessage *msg); ++void vdagent_file_xfers_error(struct udscs_connection *vdagentd, ++ uint32_t msg_id); + + #endif +diff --git a/src/vdagent.c b/src/vdagent.c +index 32c84e5..a0ba79e 100644 +--- a/src/vdagent.c ++++ b/src/vdagent.c +@@ -92,6 +92,9 @@ void daemon_read_complete(struct udscs_connection **connp, + if (vdagent_file_xfers != NULL) { + vdagent_file_xfers_start(vdagent_file_xfers, + (VDAgentFileXferStartMessage *)data); ++ } else { ++ vdagent_file_xfers_error(*connp, ++ ((VDAgentFileXferStartMessage *)data)->id); + } + free(data); + break; +@@ -99,6 +102,9 @@ void daemon_read_complete(struct udscs_connection **connp, + if (vdagent_file_xfers != NULL) { + vdagent_file_xfers_status(vdagent_file_xfers, + (VDAgentFileXferStatusMessage *)data); ++ } else { ++ vdagent_file_xfers_error(*connp, ++ ((VDAgentFileXferStatusMessage *)data)->id); + } + free(data); + break; +@@ -116,6 +122,9 @@ void daemon_read_complete(struct udscs_connection **connp, + if (vdagent_file_xfers != NULL) { + vdagent_file_xfers_data(vdagent_file_xfers, + (VDAgentFileXferDataMessage *)data); ++ } else { ++ vdagent_file_xfers_error(*connp, ++ ((VDAgentFileXferDataMessage *)data)->id); + } + free(data); + break; diff --git a/SOURCES/0024-vdagentd-send-file-xfer-status-generic-version.patch b/SOURCES/0024-vdagentd-send-file-xfer-status-generic-version.patch new file mode 100644 index 0000000..ed41763 --- /dev/null +++ b/SOURCES/0024-vdagentd-send-file-xfer-status-generic-version.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Tue, 3 May 2016 10:25:52 +0200 +Subject: [PATCH] vdagentd: send file-xfer status, generic version + +Change cancel_file_xfer() helper function to file_xfer_status() so we +can send other status to the client. + +Acked-by: Jonathon Jongsma +(cherry picked from commit b5f0352e9e5ea91eff0880674cbc5080e78c9e5b) +--- + src/vdagentd.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/src/vdagentd.c b/src/vdagentd.c +index 594f36b..2c8e973 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -244,12 +244,14 @@ static void do_client_clipboard(struct vdagent_virtio_port *vport, + data, size); + } + +-static void cancel_file_xfer(struct vdagent_virtio_port *vport, +- const char *msg, uint32_t id) ++/* To be used by vdagentd for failures in file-xfer such as when file-xfer was ++ * cancelled or an error happened */ ++static void send_file_xfer_status(struct vdagent_virtio_port *vport, ++ const char *msg, uint32_t id, uint32_t xfer_status) + { + VDAgentFileXferStatusMessage status = { + .id = id, +- .result = VD_AGENT_FILE_XFER_STATUS_CANCELLED, ++ .result = xfer_status, + }; + syslog(LOG_WARNING, msg, id); + if (vport) +@@ -269,10 +271,10 @@ static void do_client_file_xfer(struct vdagent_virtio_port *vport, + case VD_AGENT_FILE_XFER_START: { + VDAgentFileXferStartMessage *s = (VDAgentFileXferStartMessage *)data; + if (!active_session_conn) { +- cancel_file_xfer(vport, ++ send_file_xfer_status(vport, + "Could not find an agent connnection belonging to the " + "active session, cancelling client file-xfer request %u", +- s->id); ++ s->id, VD_AGENT_FILE_XFER_STATUS_CANCELLED); + return; + } + udscs_write(active_session_conn, VDAGENTD_FILE_XFER_START, 0, 0, +@@ -617,8 +619,10 @@ void update_active_session_connection(struct udscs_connection *new_conn) + gboolean remove_active_xfers(gpointer key, gpointer value, gpointer conn) + { + if (value == conn) { +- cancel_file_xfer(virtio_port, "Agent disc; cancelling file-xfer %u", +- GPOINTER_TO_UINT(key)); ++ send_file_xfer_status(virtio_port, ++ "Agent disc; cancelling file-xfer %u", ++ GPOINTER_TO_UINT(key), ++ VD_AGENT_FILE_XFER_STATUS_CANCELLED); + return 1; + } else + return 0; diff --git a/SOURCES/0025-session-info-check-for-a-locked-session.patch b/SOURCES/0025-session-info-check-for-a-locked-session.patch new file mode 100644 index 0000000..c40d19a --- /dev/null +++ b/SOURCES/0025-session-info-check-for-a-locked-session.patch @@ -0,0 +1,308 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Sat, 9 Apr 2016 12:00:08 +0200 +Subject: [PATCH] session-info: check for a locked session + +Each session back-end can return this information to vdagentd when +requested. + +The agent should use this on situations that should not work when +session is locked such as file-transfer-start which is fixed by this +patch. + +systemd-login is the only back-end implementing this function at the +moment and I'll address console-kit back-end in a later patch. + +Also, this patch makes spice-vdagent depend on dbus for getting the +lock information. + +Resolve: https://bugzilla.redhat.com/show_bug.cgi?id=1323623 + +Acked-by: Jonathon Jongsma +(cherry picked from commit 364b6bba068bd694d7c4355b6275f88482d9f3f8) +--- + configure.ac | 17 ++----- + src/console-kit.c | 7 +++ + src/dummy-session-info.c | 5 ++ + src/session-info.h | 3 ++ + src/systemd-login.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++ + src/vdagentd.c | 7 +++ + 6 files changed, 153 insertions(+), 13 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 9f9d34c..9903ea9 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -81,6 +81,7 @@ PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.12]) + PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11]) + PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.5]) + PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22]) ++PKG_CHECK_MODULES([DBUS], [dbus-1]) + + if test "$with_session_info" = "auto" || test "$with_session_info" = "systemd"; then + PKG_CHECK_MODULES([LIBSYSTEMD_LOGIN], +@@ -100,19 +101,9 @@ fi + AM_CONDITIONAL(HAVE_LIBSYSTEMD_LOGIN, test x"$have_libsystemd_login" = "xyes") + + if test "$with_session_info" = "auto" || test "$with_session_info" = "console-kit"; then +- PKG_CHECK_MODULES([DBUS], +- [dbus-1], +- [have_console_kit="yes"], +- [have_console_kit="no"]) +- if test x"$have_console_kit" = "xno" && test "$with_session_info" = "console-kit"; then +- AC_MSG_ERROR([console-kit support explicitly requested, but some required packages are not available]) +- fi +- if test x"$have_console_kit" = "xyes"; then +- AC_DEFINE([HAVE_CONSOLE_KIT], [1], [If defined, vdagentd will be compiled with ConsoleKit support]) +- with_session_info="console-kit" +- else +- with_session_info="none" +- fi ++ AC_DEFINE([HAVE_CONSOLE_KIT], [1], [If defined, vdagentd will be compiled with ConsoleKit support]) ++ have_console_kit="yes" ++ with_session_info="console-kit" + else + have_console_kit="no" + fi +diff --git a/src/console-kit.c b/src/console-kit.c +index 759a81e..260fcc7 100644 +--- a/src/console-kit.c ++++ b/src/console-kit.c +@@ -352,3 +352,10 @@ static char *console_kit_check_active_session_change(struct session_info *ck) + + return ck->active_session; + } ++ ++gboolean session_info_session_is_locked(struct session_info *info) ++{ ++ /* TODO: It could be implemented based on Lock/Unlock signals from Session ++ * interface. */ ++ return FALSE; ++} +diff --git a/src/dummy-session-info.c b/src/dummy-session-info.c +index e188ddc..c09643b 100644 +--- a/src/dummy-session-info.c ++++ b/src/dummy-session-info.c +@@ -44,3 +44,8 @@ char *session_info_session_for_pid(struct session_info *si, uint32_t pid) + { + return NULL; + } ++ ++gboolean session_is_locked(struct session_info *ck) ++{ ++ return FALSE; ++} +diff --git a/src/session-info.h b/src/session-info.h +index 67099de..d660fcf 100644 +--- a/src/session-info.h ++++ b/src/session-info.h +@@ -24,6 +24,7 @@ + + #include + #include ++#include + + struct session_info; + +@@ -36,4 +37,6 @@ const char *session_info_get_active_session(struct session_info *ck); + /* Note result must be free()-ed by caller */ + char *session_info_session_for_pid(struct session_info *ck, uint32_t pid); + ++gboolean session_info_session_is_locked(struct session_info *si); ++ + #endif +diff --git a/src/systemd-login.c b/src/systemd-login.c +index 73db37f..4a365c0 100644 +--- a/src/systemd-login.c ++++ b/src/systemd-login.c +@@ -25,13 +25,121 @@ + #include + #include + #include ++#include + + struct session_info { + int verbose; + sd_login_monitor *mon; + char *session; ++ struct { ++ DBusConnection *system_connection; ++ char *match_session_signals; ++ } dbus; ++ gboolean session_is_locked; + }; + ++#define LOGIND_SESSION_INTERFACE "org.freedesktop.login1.Session" ++#define LOGIND_SESSION_OBJ_TEMPLATE "'/org/freedesktop/login1/session/_3%s'" ++ ++#define SESSION_SIGNAL_LOCK "Lock" ++#define SESSION_SIGNAL_UNLOCK "Unlock" ++ ++/* dbus related */ ++static DBusConnection *si_dbus_get_system_bus(void) ++{ ++ DBusConnection *connection; ++ DBusError error; ++ ++ dbus_error_init(&error); ++ connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error); ++ if (connection == NULL || dbus_error_is_set(&error)) { ++ if (dbus_error_is_set(&error)) { ++ syslog(LOG_WARNING, "Unable to connect to system bus: %s", ++ error.message); ++ dbus_error_free(&error); ++ } else { ++ syslog(LOG_WARNING, "Unable to connect to system bus"); ++ } ++ return NULL; ++ } ++ return connection; ++} ++ ++static void si_dbus_match_remove(struct session_info *si) ++{ ++ DBusError error; ++ if (si->dbus.match_session_signals == NULL) ++ return; ++ ++ dbus_error_init(&error); ++ dbus_bus_remove_match(si->dbus.system_connection, ++ si->dbus.match_session_signals, ++ &error); ++ ++ g_free(si->dbus.match_session_signals); ++ si->dbus.match_session_signals = NULL; ++} ++ ++static void si_dbus_match_rule_update(struct session_info *si) ++{ ++ DBusError error; ++ ++ if (si->dbus.system_connection == NULL || ++ si->session == NULL) ++ return; ++ ++ si_dbus_match_remove(si); ++ ++ si->dbus.match_session_signals = ++ g_strdup_printf ("type='signal',interface='%s',path=" ++ LOGIND_SESSION_OBJ_TEMPLATE, ++ LOGIND_SESSION_INTERFACE, ++ si->session); ++ if (si->verbose) ++ syslog(LOG_DEBUG, "logind match: %s", si->dbus.match_session_signals); ++ ++ dbus_error_init(&error); ++ dbus_bus_add_match(si->dbus.system_connection, ++ si->dbus.match_session_signals, ++ &error); ++ if (dbus_error_is_set(&error)) { ++ syslog(LOG_WARNING, "Unable to add dbus rule match: %s", ++ error.message); ++ dbus_error_free(&error); ++ g_free(si->dbus.match_session_signals); ++ si->dbus.match_session_signals = NULL; ++ } ++} ++ ++static void ++si_dbus_read_signals(struct session_info *si) ++{ ++ DBusMessage *message = NULL; ++ ++ dbus_connection_read_write(si->dbus.system_connection, 0); ++ message = dbus_connection_pop_message(si->dbus.system_connection); ++ while (message != NULL) { ++ const char *member; ++ ++ member = dbus_message_get_member (message); ++ if (g_strcmp0(member, SESSION_SIGNAL_LOCK) == 0) { ++ si->session_is_locked = TRUE; ++ } else if (g_strcmp0(member, SESSION_SIGNAL_UNLOCK) == 0) { ++ si->session_is_locked = FALSE; ++ } else { ++ if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) { ++ syslog(LOG_WARNING, "(systemd-login) received non signal message"); ++ } else if (si->verbose) { ++ syslog(LOG_DEBUG, "(systemd-login) Signal not handled: %s", member); ++ } ++ } ++ ++ dbus_message_unref(message); ++ dbus_connection_read_write(si->dbus.system_connection, 0); ++ message = dbus_connection_pop_message(si->dbus.system_connection); ++ } ++} ++ + struct session_info *session_info_create(int verbose) + { + struct session_info *si; +@@ -42,6 +150,7 @@ struct session_info *session_info_create(int verbose) + return NULL; + + si->verbose = verbose; ++ si->session_is_locked = FALSE; + + r = sd_login_monitor_new("session", &si->mon); + if (r < 0) { +@@ -50,6 +159,7 @@ struct session_info *session_info_create(int verbose) + return NULL; + } + ++ si->dbus.system_connection = si_dbus_get_system_bus(); + return si; + } + +@@ -58,6 +168,8 @@ void session_info_destroy(struct session_info *si) + if (!si) + return; + ++ si_dbus_match_remove(si); ++ dbus_connection_close(si->dbus.system_connection); + sd_login_monitor_unref(si->mon); + free(si->session); + free(si); +@@ -87,6 +199,7 @@ const char *session_info_get_active_session(struct session_info *si) + sd_login_monitor_flush(si->mon); + free(old_session); + ++ si_dbus_match_rule_update(si); + return si->session; + } + +@@ -104,3 +217,17 @@ char *session_info_session_for_pid(struct session_info *si, uint32_t pid) + + return session; + } ++ ++gboolean session_info_session_is_locked(struct session_info *si) ++{ ++ g_return_val_if_fail (si != NULL, FALSE); ++ ++ /* We could also rely on IdleHint property from Session which seems to work ++ * well in rhel7 but it wasn't working well in my own system (F23). I'm ++ * convinced for now that Lock/Unlock signals should be enough but that ++ * means Lock/Unlock being done by logind. That might take a while. ++ * Check: https://bugzilla.gnome.org/show_bug.cgi?id=764773 */ ++ ++ si_dbus_read_signals(si); ++ return si->session_is_locked; ++} +diff --git a/src/vdagentd.c b/src/vdagentd.c +index 2c8e973..2f77773 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -276,6 +276,13 @@ static void do_client_file_xfer(struct vdagent_virtio_port *vport, + "active session, cancelling client file-xfer request %u", + s->id, VD_AGENT_FILE_XFER_STATUS_CANCELLED); + return; ++ } else if (session_info_session_is_locked(session_info)) { ++ syslog(LOG_DEBUG, "Session is locked, skipping file-xfer-start"); ++ send_file_xfer_status(vport, ++ "User's session is locked and cannot start file transfer. " ++ "Cancelling client file-xfer request %u", ++ s->id, VD_AGENT_FILE_XFER_STATUS_ERROR); ++ return; + } + udscs_write(active_session_conn, VDAGENTD_FILE_XFER_START, 0, 0, + data, message_header->size); diff --git a/SOURCES/0026-session-info-check-if-session-belongs-to-user.patch b/SOURCES/0026-session-info-check-if-session-belongs-to-user.patch new file mode 100644 index 0000000..b204aa1 --- /dev/null +++ b/SOURCES/0026-session-info-check-if-session-belongs-to-user.patch @@ -0,0 +1,169 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Thu, 21 Apr 2016 10:32:50 +0200 +Subject: [PATCH] session-info: check if session belongs to user + +session-info back-ends such as console-kit and systemd-login have the +concept of session's class which informs if session belongs to user or +not [0]. We can disable features based on the session class. + +[0] Display-Managers are 'Greeter' and Display lock screens are +'lock-screen' + +This patch introduces session_info_is_user() and disable file-xfer in +case agent's session does not belong to the 'user' class. As the +session-info data is hold by vdagentd, this patch also introduces +VDAGENTD_FILE_XFER_DISABLE message to disable file-xfer that is done +in vdagent. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1328761 + +Acked-by: Jonathon Jongsma +(cherry picked from commit 4c0e9c965e059ba2b884e66f0402e061a9d886a6) +--- + src/console-kit.c | 6 ++++++ + src/dummy-session-info.c | 5 +++++ + src/session-info.h | 1 + + src/systemd-login.c | 26 ++++++++++++++++++++++++++ + src/vdagent.c | 9 +++++++++ + src/vdagentd-proto-strings.h | 1 + + src/vdagentd-proto.h | 1 + + src/vdagentd.c | 9 +++++++++ + 8 files changed, 58 insertions(+) + +diff --git a/src/console-kit.c b/src/console-kit.c +index 260fcc7..573ee49 100644 +--- a/src/console-kit.c ++++ b/src/console-kit.c +@@ -359,3 +359,9 @@ gboolean session_info_session_is_locked(struct session_info *info) + * interface. */ + return FALSE; + } ++ ++gboolean session_info_is_user(struct session_info *info) ++{ ++ /* TODO */ ++ return TRUE; ++} +diff --git a/src/dummy-session-info.c b/src/dummy-session-info.c +index c09643b..0aa154e 100644 +--- a/src/dummy-session-info.c ++++ b/src/dummy-session-info.c +@@ -49,3 +49,8 @@ gboolean session_is_locked(struct session_info *ck) + { + return FALSE; + } ++ ++gboolean session_info_is_user(struct session_info *si) ++{ ++ return TRUE; ++} +diff --git a/src/session-info.h b/src/session-info.h +index d660fcf..823749b 100644 +--- a/src/session-info.h ++++ b/src/session-info.h +@@ -38,5 +38,6 @@ const char *session_info_get_active_session(struct session_info *ck); + char *session_info_session_for_pid(struct session_info *ck, uint32_t pid); + + gboolean session_info_session_is_locked(struct session_info *si); ++gboolean session_info_is_user(struct session_info *si); + + #endif +diff --git a/src/systemd-login.c b/src/systemd-login.c +index 4a365c0..ff9a3be 100644 +--- a/src/systemd-login.c ++++ b/src/systemd-login.c +@@ -231,3 +231,29 @@ gboolean session_info_session_is_locked(struct session_info *si) + si_dbus_read_signals(si); + return si->session_is_locked; + } ++ ++/* This function should only be called after session_info_get_active_session ++ * in order to verify if active session belongs to user (non greeter) */ ++gboolean session_info_is_user(struct session_info *si) ++{ ++ gchar *class = NULL; ++ gboolean ret; ++ ++ g_return_val_if_fail (si != NULL, TRUE); ++ g_return_val_if_fail (si->session != NULL, TRUE); ++ ++ if (sd_session_get_class(si->session, &class) != 0) { ++ syslog(LOG_WARNING, "Unable to get class from session: %s", ++ si->session); ++ return TRUE; ++ } ++ ++ if (si->verbose) ++ syslog(LOG_DEBUG, "(systemd-login) class for %s is %s", ++ si->session, class); ++ ++ ret = (g_strcmp0(class, "user") == 0); ++ g_free(class); ++ ++ return ret; ++} +diff --git a/src/vdagent.c b/src/vdagent.c +index a0ba79e..f952ba1 100644 +--- a/src/vdagent.c ++++ b/src/vdagent.c +@@ -108,6 +108,15 @@ void daemon_read_complete(struct udscs_connection **connp, + } + free(data); + break; ++ case VDAGENTD_FILE_XFER_DISABLE: ++ if (debug) ++ syslog(LOG_DEBUG, "Disabling file-xfers"); ++ ++ if (vdagent_file_xfers != NULL) { ++ vdagent_file_xfers_destroy(vdagent_file_xfers); ++ vdagent_file_xfers = NULL; ++ } ++ break; + case VDAGENTD_AUDIO_VOLUME_SYNC: { + VDAgentAudioVolumeSync *avs = (VDAgentAudioVolumeSync *)data; + if (avs->is_playback) { +diff --git a/src/vdagentd-proto-strings.h b/src/vdagentd-proto-strings.h +index a3fbd32..a56f380 100644 +--- a/src/vdagentd-proto-strings.h ++++ b/src/vdagentd-proto-strings.h +@@ -34,6 +34,7 @@ static const char * const vdagentd_messages[] = { + "file xfer start", + "file xfer status", + "file xfer data", ++ "file xfer disable", + "client disconnected", + }; + +diff --git a/src/vdagentd-proto.h b/src/vdagentd-proto.h +index 0dbaaea..c1c39ad 100644 +--- a/src/vdagentd-proto.h ++++ b/src/vdagentd-proto.h +@@ -40,6 +40,7 @@ enum { + VDAGENTD_FILE_XFER_START, + VDAGENTD_FILE_XFER_STATUS, + VDAGENTD_FILE_XFER_DATA, ++ VDAGENTD_FILE_XFER_DISABLE, + VDAGENTD_CLIENT_DISCONNECTED, /* daemon -> client */ + VDAGENTD_NO_MESSAGES /* Must always be last */ + }; +diff --git a/src/vdagentd.c b/src/vdagentd.c +index 2f77773..59ea8da 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -613,6 +613,15 @@ void update_active_session_connection(struct udscs_connection *new_conn) + active_session_conn = new_conn; + if (debug) + syslog(LOG_DEBUG, "%p is now the active session", new_conn); ++ ++ if (active_session_conn && !session_info_is_user(session_info)) { ++ if (debug) ++ syslog(LOG_DEBUG, "New session agent does not belong to user: " ++ "disabling file-xfer"); ++ udscs_write(active_session_conn, VDAGENTD_FILE_XFER_DISABLE, 0, 0, ++ NULL, 0); ++ } ++ + if (active_session_conn && mon_config) + udscs_write(active_session_conn, VDAGENTD_MONITORS_CONFIG, 0, 0, + (uint8_t *)mon_config, sizeof(VDAgentMonitorsConfig) + diff --git a/SOURCES/0027-systemd-login-check-for-LockedHint-property.patch b/SOURCES/0027-systemd-login-check-for-LockedHint-property.patch new file mode 100644 index 0000000..364c209 --- /dev/null +++ b/SOURCES/0027-systemd-login-check-for-LockedHint-property.patch @@ -0,0 +1,169 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Fri, 27 May 2016 11:42:29 +0200 +Subject: [PATCH] systemd-login: check for LockedHint property + +Property introduced in v230 of systemd. + +Systems that don't have up to date systemd-login will get the +following log message: + +"Properties.Get failed (locked-hint) due Unknown property or interface." + +Resolves: rhbz#1323623 +Acked-by: Pavel Grunt +(cherry picked from commit ec843a21b29d7fa21ba3393b84368bc2e39d3ce7) +--- + src/systemd-login.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 98 insertions(+), 10 deletions(-) + +diff --git a/src/systemd-login.c b/src/systemd-login.c +index ff9a3be..1b0b6f1 100644 +--- a/src/systemd-login.c ++++ b/src/systemd-login.c +@@ -36,14 +36,21 @@ struct session_info { + char *match_session_signals; + } dbus; + gboolean session_is_locked; ++ gboolean session_locked_hint; + }; + ++#define LOGIND_INTERFACE "org.freedesktop.login1" ++ + #define LOGIND_SESSION_INTERFACE "org.freedesktop.login1.Session" +-#define LOGIND_SESSION_OBJ_TEMPLATE "'/org/freedesktop/login1/session/_3%s'" ++#define LOGIND_SESSION_OBJ_TEMPLATE "/org/freedesktop/login1/session/_3%s" ++ ++#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties" + + #define SESSION_SIGNAL_LOCK "Lock" + #define SESSION_SIGNAL_UNLOCK "Unlock" + ++#define SESSION_PROP_LOCKED_HINT "LockedHint" ++ + /* dbus related */ + static DBusConnection *si_dbus_get_system_bus(void) + { +@@ -91,8 +98,8 @@ static void si_dbus_match_rule_update(struct session_info *si) + si_dbus_match_remove(si); + + si->dbus.match_session_signals = +- g_strdup_printf ("type='signal',interface='%s',path=" +- LOGIND_SESSION_OBJ_TEMPLATE, ++ g_strdup_printf ("type='signal',interface='%s',path='" ++ LOGIND_SESSION_OBJ_TEMPLATE"'", + LOGIND_SESSION_INTERFACE, + si->session); + if (si->verbose) +@@ -112,6 +119,84 @@ static void si_dbus_match_rule_update(struct session_info *si) + } + + static void ++si_dbus_read_properties(struct session_info *si) ++{ ++ dbus_bool_t locked_hint, ret; ++ DBusMessageIter iter, iter_variant; ++ gint type; ++ DBusError error; ++ DBusMessage *message = NULL; ++ DBusMessage *reply = NULL; ++ gchar *session_object; ++ const gchar *interface, *property; ++ ++ if (si->session == NULL) ++ return; ++ ++ session_object = g_strdup_printf(LOGIND_SESSION_OBJ_TEMPLATE, si->session); ++ message = dbus_message_new_method_call(LOGIND_INTERFACE, ++ session_object, ++ DBUS_PROPERTIES_INTERFACE, ++ "Get"); ++ g_free (session_object); ++ if (message == NULL) { ++ syslog(LOG_ERR, "Unable to create dbus message"); ++ goto exit; ++ } ++ ++ interface = LOGIND_SESSION_INTERFACE; ++ property = SESSION_PROP_LOCKED_HINT; ++ ret = dbus_message_append_args(message, ++ DBUS_TYPE_STRING, &interface, ++ DBUS_TYPE_STRING, &property, ++ DBUS_TYPE_INVALID); ++ if (!ret) { ++ syslog(LOG_ERR, "Unable to request locked-hint"); ++ goto exit; ++ } ++ ++ dbus_error_init(&error); ++ reply = dbus_connection_send_with_reply_and_block(si->dbus.system_connection, ++ message, ++ -1, ++ &error); ++ if (reply == NULL) { ++ if (dbus_error_is_set(&error)) { ++ syslog(LOG_ERR, "Properties.Get failed (locked-hint) due %s", error.message); ++ dbus_error_free(&error); ++ } else { ++ syslog(LOG_ERR, "Properties.Get failed (locked-hint)"); ++ } ++ goto exit; ++ } ++ ++ dbus_message_iter_init(reply, &iter); ++ type = dbus_message_iter_get_arg_type(&iter); ++ if (type != DBUS_TYPE_VARIANT) { ++ syslog(LOG_ERR, "expected a variant, got a '%c' instead", type); ++ goto exit; ++ } ++ ++ dbus_message_iter_recurse(&iter, &iter_variant); ++ type = dbus_message_iter_get_arg_type(&iter_variant); ++ if (type != DBUS_TYPE_BOOLEAN) { ++ syslog(LOG_ERR, "expected a boolean, got a '%c' instead", type); ++ goto exit; ++ } ++ dbus_message_iter_get_basic(&iter_variant, &locked_hint); ++ ++ si->session_locked_hint = (locked_hint) ? TRUE : FALSE; ++exit: ++ if (reply != NULL) { ++ dbus_message_unref(reply); ++ } ++ ++ if (message != NULL) { ++ dbus_message_unref(message); ++ } ++} ++ ++static void + si_dbus_read_signals(struct session_info *si) + { + DBusMessage *message = NULL; +@@ -220,16 +305,19 @@ char *session_info_session_for_pid(struct session_info *si, uint32_t pid) + + gboolean session_info_session_is_locked(struct session_info *si) + { +- g_return_val_if_fail (si != NULL, FALSE); ++ gboolean locked; + +- /* We could also rely on IdleHint property from Session which seems to work +- * well in rhel7 but it wasn't working well in my own system (F23). I'm +- * convinced for now that Lock/Unlock signals should be enough but that +- * means Lock/Unlock being done by logind. That might take a while. +- * Check: https://bugzilla.gnome.org/show_bug.cgi?id=764773 */ ++ g_return_val_if_fail (si != NULL, FALSE); + + si_dbus_read_signals(si); +- return si->session_is_locked; ++ si_dbus_read_properties(si); ++ ++ locked = (si->session_is_locked || si->session_locked_hint); ++ if (si->verbose) { ++ syslog(LOG_DEBUG, "(systemd-login) session is locked: %s", ++ locked ? "yes" : "no"); ++ } ++ return locked; + } + + /* This function should only be called after session_info_get_active_session diff --git a/SOURCES/0028-Add-systemd-socket-activation.patch b/SOURCES/0028-Add-systemd-socket-activation.patch new file mode 100644 index 0000000..35c4484 --- /dev/null +++ b/SOURCES/0028-Add-systemd-socket-activation.patch @@ -0,0 +1,368 @@ +From fa2594ee2f73901b729651f7ed31e37d141a0863 Mon Sep 17 00:00:00 2001 +From: Jonathon Jongsma +Date: Fri, 16 Jun 2017 09:46:56 -0500 +Subject: [PATCH linux vdagent] Add systemd socket activation + +If we are configured to use the systemd init script, also add support +for systemd socket activation. systemd will listen on the socket that is +used to communicate between the session agent and the system daemon. +When the session agent connects, the system daemon will automatically be +started. The socket will be enabled only if the required virtio-port +device exists. The socket is disabled when the device is removed. + +This has a couple minor advantages to the previous approach: + - For VMS that are not running a graphical desktop (and thus no + session agents are running), the system vdagent daemon won't get + started at all even if the spice virtio port is configured. Only the + socket will be enabled. In the previous approach, the system daemon + was started when the virtio device was added regardless of whether + it was needed or not. + - Solves issues related to switching between systemd targets. With the + previous approach, when a user switches to a different target + ("systemctl isolate multi-user.target"), spice-vdagentd.target was + stopped by systemd (since "isolate" by definition stops all targets + except the one specified). This meant that if the user subsequently + switched back to graphical.target, the spice-vdagentd.target would + still be disabled and vdagent functionality would not work. With + this change, the socket will still be listening after switching to a + different target, so as soon as a session agent tries to connect to + the socket, the system daemon will get restarted. + +Fixes: rhbz#1340160 + +Signed-off-by: Jonathon Jongsma +Acked-by: Victor Toso +--- + Makefile.am | 8 +++---- + configure.ac | 8 +++++++ + data/70-spice-vdagentd.rules | 2 +- + data/spice-vdagentd.service | 8 +++---- + data/spice-vdagentd.socket | 10 ++++++++ + data/spice-vdagentd.target | 2 -- + src/udscs.c | 45 ++++++++++++++++++++++++------------ + src/udscs.h | 12 +++++++++- + src/vdagentd.c | 54 +++++++++++++++++++++++++++++++++++--------- + 9 files changed, 110 insertions(+), 39 deletions(-) + create mode 100644 data/spice-vdagentd.socket + delete mode 100644 data/spice-vdagentd.target + +diff --git a/Makefile.am b/Makefile.am +index 2effe4e..3ba7692 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -14,9 +14,9 @@ src_spice_vdagent_SOURCES = src/vdagent.c \ + src/udscs.c + + src_spice_vdagentd_CFLAGS = $(DBUS_CFLAGS) $(LIBSYSTEMD_LOGIN_CFLAGS) \ +- $(PCIACCESS_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) $(PIE_CFLAGS) ++ $(PCIACCESS_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) $(PIE_CFLAGS) $(LIBSYSTEMD_DAEMON_CFLAGS) + src_spice_vdagentd_LDADD = $(DBUS_LIBS) $(LIBSYSTEMD_LOGIN_LIBS) \ +- $(PCIACCESS_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) $(PIE_LDFLAGS) ++ $(PCIACCESS_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) $(PIE_LDFLAGS) $(LIBSYSTEMD_DAEMON_LIBS) + src_spice_vdagentd_SOURCES = src/vdagentd.c \ + src/vdagentd-uinput.c \ + src/vdagentd-xorg-conf.c \ +@@ -66,7 +66,7 @@ if INIT_SCRIPT_SYSTEMD + systemdunitdir = $(SYSTEMDSYSTEMUNITDIR) + systemdunit_DATA = \ + $(top_srcdir)/data/spice-vdagentd.service \ +- $(top_srcdir)/data/spice-vdagentd.target ++ $(top_srcdir)/data/spice-vdagentd.socket + + udevrulesdir = /lib/udev/rules.d + udevrules_DATA = $(top_srcdir)/data/70-spice-vdagentd.rules +@@ -89,7 +89,7 @@ EXTRA_DIST = \ + data/spice-vdagent.desktop \ + data/spice-vdagentd \ + data/spice-vdagentd.service \ +- data/spice-vdagentd.target \ ++ data/spice-vdagentd.socket \ + data/tmpfiles.d/spice-vdagentd.conf \ + data/xorg.conf.RHEL-5 \ + $(NULL) +diff --git a/configure.ac b/configure.ac +index 9903ea9..3ce2208 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -65,6 +65,14 @@ AC_MSG_RESULT($with_init_script) + if test "x$init_systemd" = "xyes"; then + SYSTEMDSYSTEMUNITDIR=`${PKG_CONFIG} systemd --variable=systemdsystemunitdir` + AC_SUBST(SYSTEMDSYSTEMUNITDIR) ++ # earlier versions of systemd require a separate libsystemd-daemon library ++ PKG_CHECK_MODULES([LIBSYSTEMD_DAEMON], ++ [libsystemd >= 209], ++ [have_libsystemd_daemon="yes"], ++ [have_libsystemd_daemon="no"]) ++ if test "$have_libsystemd_daemon" = "yes"; then ++ AC_DEFINE([WITH_SYSTEMD_SOCKET_ACTIVATION], [1], [If defined, vdagentd will support socket activation with systemd] ) ++ fi + fi + + AC_ARG_ENABLE([pciaccess], +diff --git a/data/70-spice-vdagentd.rules b/data/70-spice-vdagentd.rules +index a1785ba..64b4166 100644 +--- a/data/70-spice-vdagentd.rules ++++ b/data/70-spice-vdagentd.rules +@@ -1 +1 @@ +-ACTION=="add", SUBSYSTEM=="virtio-ports", ENV{DEVLINKS}=="/dev/virtio-ports/com.redhat.spice.0", ENV{SYSTEMD_WANTS}="spice-vdagentd.target" ++ACTION=="add", SUBSYSTEM=="virtio-ports", ENV{DEVLINKS}=="/dev/virtio-ports/com.redhat.spice.0", ENV{SYSTEMD_WANTS}="spice-vdagentd.socket" +diff --git a/data/spice-vdagentd.service b/data/spice-vdagentd.service +index 8c5effe..365b2c1 100644 +--- a/data/spice-vdagentd.service ++++ b/data/spice-vdagentd.service +@@ -1,17 +1,15 @@ + [Unit] + Description=Agent daemon for Spice guests + After=dbus.target +- +-# TODO we should use: +-#Requires=spice-vdagentd.socket ++Requires=spice-vdagentd.socket + + [Service] + Type=forking + EnvironmentFile=-/etc/sysconfig/spice-vdagentd +-ExecStartPre=/bin/rm -f /var/run/spice-vdagentd/spice-vdagent-sock + ExecStart=/usr/sbin/spice-vdagentd $SPICE_VDAGENTD_EXTRA_ARGS + PIDFile=/var/run/spice-vdagentd/spice-vdagentd.pid + PrivateTmp=true ++Restart=on-failure + + [Install] +-WantedBy=spice-vdagentd.target ++Also=spice-vdagentd.socket +diff --git a/data/spice-vdagentd.socket b/data/spice-vdagentd.socket +new file mode 100644 +index 0000000..e34a188 +--- /dev/null ++++ b/data/spice-vdagentd.socket +@@ -0,0 +1,10 @@ ++[Unit] ++Description=Activation socket for spice guest agent daemon ++# only start the socket if the virtio port device exists ++Requisite=dev-virtio\x2dports-com.redhat.spice.0.device ++ ++[Socket] ++ListenStream=/var/run/spice-vdagentd/spice-vdagent-sock ++ ++[Install] ++WantedBy=sockets.target +diff --git a/data/spice-vdagentd.target b/data/spice-vdagentd.target +deleted file mode 100644 +index 1f74931..0000000 +--- a/data/spice-vdagentd.target ++++ /dev/null +@@ -1,2 +0,0 @@ +-[Unit] +-Description=Agent daemon for Spice guests +diff --git a/src/udscs.c b/src/udscs.c +index 288aca2..f04a31c 100644 +--- a/src/udscs.c ++++ b/src/udscs.c +@@ -81,52 +81,67 @@ static void udscs_do_write(struct udscs_connection **connp); + static void udscs_do_read(struct udscs_connection **connp); + + +-struct udscs_server *udscs_create_server(const char *socketname, ++struct udscs_server *udscs_create_server_for_fd(int fd, + udscs_connect_callback connect_callback, + udscs_read_callback read_callback, + udscs_disconnect_callback disconnect_callback, + const char * const type_to_string[], int no_types, int debug) + { +- int c; +- struct sockaddr_un address; + struct udscs_server *server; + + server = calloc(1, sizeof(*server)); + if (!server) + return NULL; + ++ if (fd <= 0) { ++ syslog(LOG_ERR, "Invalid file descriptor: %i", fd); ++ return NULL; ++ } ++ + server->type_to_string = type_to_string; + server->no_types = no_types; + server->debug = debug; ++ server->fd = fd; ++ server->connect_callback = connect_callback; ++ server->read_callback = read_callback; ++ server->disconnect_callback = disconnect_callback; ++ ++ return server; ++} ++ ++struct udscs_server *udscs_create_server(const char *socketname, ++ udscs_connect_callback connect_callback, ++ udscs_read_callback read_callback, ++ udscs_disconnect_callback disconnect_callback, ++ const char * const type_to_string[], int no_types, int debug) ++{ ++ int c; ++ int fd; ++ struct sockaddr_un address; + +- server->fd = socket(PF_UNIX, SOCK_STREAM, 0); +- if (server->fd == -1) { ++ fd = socket(PF_UNIX, SOCK_STREAM, 0); ++ if (fd == -1) { + syslog(LOG_ERR, "creating unix domain socket: %m"); +- free(server); + return NULL; + } + + address.sun_family = AF_UNIX; + snprintf(address.sun_path, sizeof(address.sun_path), "%s", socketname); +- c = bind(server->fd, (struct sockaddr *)&address, sizeof(address)); ++ c = bind(fd, (struct sockaddr *)&address, sizeof(address)); + if (c != 0) { + syslog(LOG_ERR, "bind %s: %m", socketname); +- free(server); + return NULL; + } + +- c = listen(server->fd, 5); ++ c = listen(fd, 5); + if (c != 0) { + syslog(LOG_ERR, "listen: %m"); +- free(server); + return NULL; + } + +- server->connect_callback = connect_callback; +- server->read_callback = read_callback; +- server->disconnect_callback = disconnect_callback; +- +- return server; ++ return udscs_create_server_for_fd(fd, connect_callback, read_callback, ++ disconnect_callback, type_to_string, ++ no_types, debug); + } + + void udscs_destroy_server(struct udscs_server *server) +diff --git a/src/udscs.h b/src/udscs.h +index 89ab617..cb67059 100644 +--- a/src/udscs.h ++++ b/src/udscs.h +@@ -57,6 +57,17 @@ typedef int (*udscs_for_all_clients_callback)(struct udscs_connection **connp, + by explictly calling udscs_destroy_connection */ + typedef void (*udscs_disconnect_callback)(struct udscs_connection *conn); + ++/* Create a server for the given file descriptor. This allows us to use ++ * pre-configured sockets for use with systemd socket activation, etc. ++ * ++ * See udscs_create_server() for more information ++ */ ++struct udscs_server *udscs_create_server_for_fd(int fd, ++ udscs_connect_callback connect_callback, ++ udscs_read_callback read_callback, ++ udscs_disconnect_callback disconnect_callback, ++ const char * const type_to_string[], int no_types, int debug); ++ + /* Create a unix domain socket named name and start listening on it. */ + struct udscs_server *udscs_create_server(const char *socketname, + udscs_connect_callback connect_callback, +@@ -98,7 +109,6 @@ void udscs_client_handle_fds(struct udscs_connection **connp, fd_set *readfds, + + + /* Queue a message for delivery to the client connected through conn. +- + Returns 0 on success -1 on error (only happens when malloc fails) */ + int udscs_write(struct udscs_connection *conn, uint32_t type, uint32_t arg1, + uint32_t arg2, const uint8_t *data, uint32_t size); +diff --git a/src/vdagentd.c b/src/vdagentd.c +index 59ea8da..d5cc33b 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -36,6 +36,10 @@ + #include + #include + ++#ifdef WITH_SYSTEMD_SOCKET_ACTIVATION ++#include ++#endif /* WITH_SYSTEMD_SOCKET_ACTIVATION */ ++ + #include "udscs.h" + #include "vdagentd-proto.h" + #include "vdagentd-proto-strings.h" +@@ -873,6 +877,7 @@ int main(int argc, char *argv[]) + int do_daemonize = 1; + int want_session_info = 1; + struct sigaction act; ++ gboolean own_socket = TRUE; + + for (;;) { + if (-1 == (c = getopt(argc, argv, "-dhxXs:u:"))) +@@ -914,20 +919,43 @@ int main(int argc, char *argv[]) + openlog("spice-vdagentd", do_daemonize ? 0 : LOG_PERROR, LOG_USER); + + /* Setup communication with vdagent process(es) */ +- server = udscs_create_server(VDAGENTD_SOCKET, agent_connect, +- agent_read_complete, agent_disconnect, +- vdagentd_messages, VDAGENTD_NO_MESSAGES, +- debug); ++#ifdef WITH_SYSTEMD_SOCKET_ACTIVATION ++ int n_fds; ++ /* try to retrieve pre-configured sockets from systemd */ ++ n_fds = sd_listen_fds(0); ++ if (n_fds > 1) { ++ syslog(LOG_CRIT, "Received too many sockets from systemd (%i)", n_fds); ++ return 1; ++ } else if (n_fds == 1) { ++ server = udscs_create_server_for_fd(SD_LISTEN_FDS_START, agent_connect, ++ agent_read_complete, ++ agent_disconnect, ++ vdagentd_messages, ++ VDAGENTD_NO_MESSAGES, debug); ++ own_socket = FALSE; ++ } else ++ /* systemd socket activation not enabled, create our own */ ++#endif /* WITH_SYSTEMD_SOCKET_ACTIVATION */ ++ { ++ server = udscs_create_server(VDAGENTD_SOCKET, agent_connect, ++ agent_read_complete, agent_disconnect, ++ vdagentd_messages, VDAGENTD_NO_MESSAGES, ++ debug); ++ } ++ + if (!server) { + syslog(LOG_CRIT, "Fatal could not create server socket %s", + VDAGENTD_SOCKET); + return 1; + } +- if (chmod(VDAGENTD_SOCKET, 0666)) { +- syslog(LOG_CRIT, "Fatal could not change permissions on %s: %m", +- VDAGENTD_SOCKET); +- udscs_destroy_server(server); +- return 1; ++ /* no need to set permissions on a socket that was provided by systemd */ ++ if (own_socket) { ++ if (chmod(VDAGENTD_SOCKET, 0666)) { ++ syslog(LOG_CRIT, "Fatal could not change permissions on %s: %m", ++ VDAGENTD_SOCKET); ++ udscs_destroy_server(server); ++ return 1; ++ } + } + + if (do_daemonize) +@@ -957,8 +985,12 @@ int main(int argc, char *argv[]) + vdagent_virtio_port_destroy(&virtio_port); + session_info_destroy(session_info); + udscs_destroy_server(server); +- if (unlink(VDAGENTD_SOCKET) != 0) +- syslog(LOG_ERR, "unlink %s: %s", VDAGENTD_SOCKET, strerror(errno)); ++ ++ /* leave the socket around if it was provided by systemd */ ++ if (own_socket) { ++ if (unlink(VDAGENTD_SOCKET) != 0) ++ syslog(LOG_ERR, "unlink %s: %s", VDAGENTD_SOCKET, strerror(errno)); ++ } + syslog(LOG_INFO, "vdagentd quiting, returning status %d", retval); + + if (do_daemonize) +-- +2.13.6 + diff --git a/SOURCES/0029-spice-vdagent.desktop-Change-autostart-to-WindowMana.patch b/SOURCES/0029-spice-vdagent.desktop-Change-autostart-to-WindowMana.patch new file mode 100644 index 0000000..d0272ec --- /dev/null +++ b/SOURCES/0029-spice-vdagent.desktop-Change-autostart-to-WindowMana.patch @@ -0,0 +1,39 @@ +From d0aeaff0dae4c7eb7fcb88d2d33c667364e870de Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Tue, 4 Sep 2018 10:51:42 +0200 +Subject: [PATCH] spice-vdagent.desktop: Change autostart to WindowManager + stage + +It is possible that g_get_user_special_dir() return NULL for +G_USER_DIRECTORY_DESKTOP or G_USER_DIRECTORY_DOWNLOAD; This is a sure +thing to happen in case xdg-user-dirs hasn't been run yet. + +Keeping spice-vdagent to run on Initialization stage of +X-GNOME-Autostart-Phase could trigger a race with xdg-user-dirs that +also runs on Initialization, which is the earliest stage possible. + +Moving to spice-vdagent to run WindowManager stage avoids the race +with xdg-user-dirs and still runs before any graphical application. + +Tested also moving to Desktop stage, which is 4th stage (out of 5) and +worked without apparent drawbacks. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1623947 +Signed-off-by: Victor Toso +--- + data/spice-vdagent.desktop | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/data/spice-vdagent.desktop b/data/spice-vdagent.desktop +index d152c12..260dace 100644 +--- a/data/spice-vdagent.desktop ++++ b/data/spice-vdagent.desktop +@@ -5,4 +5,4 @@ Exec=/usr/bin/spice-vdagent + Terminal=false + Type=Application + Categories= +-X-GNOME-Autostart-Phase=Initialization ++X-GNOME-Autostart-Phase=WindowManager +-- +2.17.1 + diff --git a/SOURCES/0030-systemd-Remove-unneded-virtio-port-dependencies.patch b/SOURCES/0030-systemd-Remove-unneded-virtio-port-dependencies.patch new file mode 100644 index 0000000..b824a5c --- /dev/null +++ b/SOURCES/0030-systemd-Remove-unneded-virtio-port-dependencies.patch @@ -0,0 +1,43 @@ +From f3f132795fbbcbd890e30d98d1d3cfe2f7870347 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Tue, 18 Dec 2018 13:46:01 +0100 +Subject: [PATCH] systemd: Remove unneded virtio-port dependencies + +The udev rule already adds SYSTEMD_WANTS=spice-vdagentd.socket +to the relevant virtio devices, which automatically adds Wants=${device} +to spice-vdagentd.socket (see 'systemctl show spice-vdagentd.socket'). +Adding a Requisite/After for these ports is at best redundant, and most +likely wrong as this is causing boot time warnings: + +[ INFO ] dev-virtio\x2dports-com.redhat.spice.0.device is not active. +[DEPEND] Dependency failed for Activation socket for spice guest agent daemon. + +https://bugzilla.redhat.com/show_bug.cgi?id=1545212 + +Signed-off-by: Christophe Fergeau +(cherry picked from commit b07420eea0aaba1b9a375eac03c1dbb565287f11) + +Note: +- Conflict due not having commit below. As this patch removes that, + not worth to backport it. + + 102b2e7 systemd: use "After" with "Requisite" +--- + data/spice-vdagentd.socket | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/data/spice-vdagentd.socket b/data/spice-vdagentd.socket +index e34a188..f14e662 100644 +--- a/data/spice-vdagentd.socket ++++ b/data/spice-vdagentd.socket +@@ -1,7 +1,5 @@ + [Unit] + Description=Activation socket for spice guest agent daemon +-# only start the socket if the virtio port device exists +-Requisite=dev-virtio\x2dports-com.redhat.spice.0.device + + [Socket] + ListenStream=/var/run/spice-vdagentd/spice-vdagent-sock +-- +2.20.1 + diff --git a/SOURCES/0031-systemd-Remove-WantedBy-sockets.service-in-Install.patch b/SOURCES/0031-systemd-Remove-WantedBy-sockets.service-in-Install.patch new file mode 100644 index 0000000..d68ba74 --- /dev/null +++ b/SOURCES/0031-systemd-Remove-WantedBy-sockets.service-in-Install.patch @@ -0,0 +1,36 @@ +From be443adb0f0f22025dbbfba15189a186dbc7cdc3 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Wed, 19 Dec 2018 15:28:31 +0100 +Subject: [PATCH] systemd: Remove WantedBy=sockets.service in [Install] + +.socket systemd units already automatically get a +Before=sockets.service, and the udev rule we have will ensure that when +the appropriate virtio device is there, the socket unit will be started, +so this WantedBy dependency is not needed, and is in part responsible +for these warnings: + +[ INFO ] dev-virtio\x2dports-com.redhat.spice.0.device is not active. +[DEPEND] Dependency failed for Activation socket for spice guest agent daemon. + +https://bugzilla.redhat.com/show_bug.cgi?id=1545212 + +Signed-off-by: Christophe Fergeau +(cherry picked from commit 56d50d21223e6d9aec4a68400d8e36c5953ba3cc) +--- + data/spice-vdagentd.socket | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/data/spice-vdagentd.socket b/data/spice-vdagentd.socket +index f14e662..adace91 100644 +--- a/data/spice-vdagentd.socket ++++ b/data/spice-vdagentd.socket +@@ -3,6 +3,3 @@ Description=Activation socket for spice guest agent daemon + + [Socket] + ListenStream=/var/run/spice-vdagentd/spice-vdagent-sock +- +-[Install] +-WantedBy=sockets.target +-- +2.20.1 + diff --git a/SOURCES/0032-systemd-Update-path-in-unit-file.patch b/SOURCES/0032-systemd-Update-path-in-unit-file.patch new file mode 100644 index 0000000..c598ec1 --- /dev/null +++ b/SOURCES/0032-systemd-Update-path-in-unit-file.patch @@ -0,0 +1,41 @@ +From b69bd2346b92f48546eb7824ead9688fb3f7af77 Mon Sep 17 00:00:00 2001 +From: Christian Hesse +Date: Mon, 14 Jan 2019 12:12:00 +0100 +Subject: [PATCH] systemd: Update path in unit file +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When loading the unit file, systemd 240 logs: + +systemd[1]: /usr/lib/systemd/system/spice-vdagentd.service:9: PIDFile= +references path below legacy directory /var/run/, updating +/var/run/spice-vdagentd/spice-vdagentd.pid → +/run/spice-vdagentd/spice-vdagentd.pid; please update the unit file +accordingly. + +So update the path. + +Signed-off-by: Christian Hesse +Acked-by: Frediano Ziglio +(cherry picked from commit 098268a33c7c8008ccec9050aea8f0763f1c06d5) +--- + data/spice-vdagentd.service | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/data/spice-vdagentd.service b/data/spice-vdagentd.service +index 365b2c1..9c70b30 100644 +--- a/data/spice-vdagentd.service ++++ b/data/spice-vdagentd.service +@@ -7,7 +7,7 @@ Requires=spice-vdagentd.socket + Type=forking + EnvironmentFile=-/etc/sysconfig/spice-vdagentd + ExecStart=/usr/sbin/spice-vdagentd $SPICE_VDAGENTD_EXTRA_ARGS +-PIDFile=/var/run/spice-vdagentd/spice-vdagentd.pid ++PIDFile=/run/spice-vdagentd/spice-vdagentd.pid + PrivateTmp=true + Restart=on-failure + +-- +2.20.1 + diff --git a/SOURCES/0033-udscs-Avoid-file-descriptor-leak.patch b/SOURCES/0033-udscs-Avoid-file-descriptor-leak.patch new file mode 100644 index 0000000..0c0c0a9 --- /dev/null +++ b/SOURCES/0033-udscs-Avoid-file-descriptor-leak.patch @@ -0,0 +1,34 @@ +From 0fa0ce0acdddc5e517bf06df9da33c9cda6d600e Mon Sep 17 00:00:00 2001 +From: Frediano Ziglio +Date: Thu, 15 Nov 2018 21:55:11 +0000 +Subject: [PATCH] udscs: Avoid file descriptor leak + +If connection fails the socket descriptor is not closed causing +a leak. + +Signed-off-by: Frediano Ziglio +Acked-by: Victor Toso +(cherry picked from commit 2d6d0d2acd3248e981361c2f3d8b253da8f04048) + +Note: +- Conflict due g_free() usage upstream while downstream we have free() + being used. +--- + src/udscs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/udscs.c b/src/udscs.c +index f04a31c..96a9f61 100644 +--- a/src/udscs.c ++++ b/src/udscs.c +@@ -192,6 +192,7 @@ struct udscs_connection *udscs_connect(const char *socketname, + if (conn->debug) { + syslog(LOG_DEBUG, "connect %s: %m", socketname); + } ++ close(conn->fd); + free(conn); + return NULL; + } +-- +2.20.1 + diff --git a/SOURCES/0034-x11-invalidate-requests-for-targets-on-grab-from-cli.patch b/SOURCES/0034-x11-invalidate-requests-for-targets-on-grab-from-cli.patch new file mode 100644 index 0000000..44ef0f1 --- /dev/null +++ b/SOURCES/0034-x11-invalidate-requests-for-targets-on-grab-from-cli.patch @@ -0,0 +1,72 @@ +From 3ff64705a7802e4944fcb5e7a027126127043bc8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jakub=20Jank=C5=AF?= +Date: Thu, 21 Feb 2019 21:25:57 +0100 +Subject: [PATCH] x11: invalidate requests for targets on grab from client +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If XSetSelectionOwner() is invoked during the time +we are waiting for the requested clipboard targets, +the targets we eventually receive are no longer valid. + +To solve this, ignore the same count of target notifications +as we expected at the time we received grab from the client. + +Otherwise we end up in a situation when vdagent holds +the clipboard grab in the guest but cannot provide data to the +apps that request it - this can be observed in the log: + + clipboard: received selection request event for target *, while not owning client clipboard + +Signed-off-by: Jakub Janků +Acked-by: Victor Toso +--- + src/vdagent-x11-priv.h | 1 + + src/vdagent-x11.c | 11 +++++++++++ + 2 files changed, 12 insertions(+) + +diff --git a/src/vdagent-x11-priv.h b/src/vdagent-x11-priv.h +index 38f852e..29018a3 100644 +--- a/src/vdagent-x11-priv.h ++++ b/src/vdagent-x11-priv.h +@@ -97,6 +97,7 @@ struct vdagent_x11 { + int xfixes_event_base; + int max_prop_size; + int expected_targets_notifies[256]; ++ int ignore_targets_notifies[256]; + int clipboard_owner[256]; + int clipboard_type_count[256]; + uint32_t clipboard_agent_types[256][256]; +diff --git a/src/vdagent-x11.c b/src/vdagent-x11.c +index 5ac2cf7..3d752c1 100644 +--- a/src/vdagent-x11.c ++++ b/src/vdagent-x11.c +@@ -894,6 +894,12 @@ static void vdagent_x11_handle_targets_notify(struct vdagent_x11 *x11, + + x11->expected_targets_notifies[selection]--; + ++ if (x11->ignore_targets_notifies[selection] > 0) { ++ x11->ignore_targets_notifies[selection]--; ++ VSELPRINTF("ignoring selection notify TARGETS"); ++ return; ++ } ++ + /* If we have more targets_notifies pending, ignore this one, we + are only interested in the targets list of the current owner + (which is the last one we've requested a targets list from) */ +@@ -1194,6 +1200,11 @@ void vdagent_x11_clipboard_grab(struct vdagent_x11 *x11, uint8_t selection, + x11->selection_window, CurrentTime); + vdagent_x11_set_clipboard_owner(x11, selection, owner_client); + ++ /* If there're pending requests for targets, ignore the returned ++ * targets as the XSetSelectionOwner() call above made them invalid */ ++ x11->ignore_targets_notifies[selection] = ++ x11->expected_targets_notifies[selection]; ++ + /* Flush output buffers and consume any pending events */ + vdagent_x11_do_read(x11); + } +-- +2.20.1 + diff --git a/SOURCES/0035-vdagent_x11_target_to_type-Improve-error-logging.patch b/SOURCES/0035-vdagent_x11_target_to_type-Improve-error-logging.patch new file mode 100644 index 0000000..f22aeaa --- /dev/null +++ b/SOURCES/0035-vdagent_x11_target_to_type-Improve-error-logging.patch @@ -0,0 +1,35 @@ +From 291e3fe366197c3958d3bb13486bee786a362d48 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 8 Aug 2013 12:01:48 +0200 +Subject: [PATCH 35/36] vdagent_x11_target_to_type: Improve error logging + +Signed-off-by: Hans de Goede +(cherry picked from commit bad87034bbed85e65e9b8fe479c967a3d0f9c861) +--- + src/vdagent-x11.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/vdagent-x11.c b/src/vdagent-x11.c +index 3d752c1..e72fd24 100644 +--- a/src/vdagent-x11.c ++++ b/src/vdagent-x11.c +@@ -833,6 +833,8 @@ static void vdagent_x11_handle_selection_notify(struct vdagent_x11 *x11, + selection = x11->conversion_req->selection; + type = vdagent_x11_target_to_type(x11, selection, + x11->conversion_req->target); ++ if (type == VD_AGENT_CLIPBOARD_NONE) ++ syslog(LOG_ERR, "internal error conversion_req has bad target"); + if (len == 0) { /* No errors so far */ + len = vdagent_x11_get_selection(x11, event, selection, + x11->conversion_req->target, +@@ -1062,6 +1064,7 @@ static void vdagent_x11_handle_selection_request(struct vdagent_x11 *x11) + type = vdagent_x11_target_to_type(x11, selection, + event->xselectionrequest.target); + if (type == VD_AGENT_CLIPBOARD_NONE) { ++ syslog(LOG_ERR, "guest app requested a non-advertised target"); + vdagent_x11_send_selection_notify(x11, None, NULL); + return; + } +-- +2.20.1 + diff --git a/SOURCES/0036-vdagent-x11-Turn-some-error-messages-into-debugging-.patch b/SOURCES/0036-vdagent-x11-Turn-some-error-messages-into-debugging-.patch new file mode 100644 index 0000000..9290deb --- /dev/null +++ b/SOURCES/0036-vdagent-x11-Turn-some-error-messages-into-debugging-.patch @@ -0,0 +1,62 @@ +From 81c96df492e8f8b01640634fcd79234f63f5228e Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 13 Aug 2013 12:19:54 +0200 +Subject: [PATCH 36/36] vdagent-x11: Turn some error messages into debugging + messages (rhbz#918310) + +Some bad clients, ie autocutsel, don't stick to the icccm spec, causing us to +flood the logs with error messages, turn these into debug messages instead, +so that they are only shown when debuggging / verbose logging is turned on. + +Signed-off-by: Hans de Goede +(cherry picked from commit d39230cee236bc6b8b150c7687d49a46f519bd2b) +--- + src/vdagent-x11.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/src/vdagent-x11.c b/src/vdagent-x11.c +index e72fd24..c925b43 100644 +--- a/src/vdagent-x11.c ++++ b/src/vdagent-x11.c +@@ -761,8 +761,8 @@ static uint32_t vdagent_x11_target_to_type(struct vdagent_x11 *x11, + } + } + +- SELPRINTF("unexpected selection type %s", +- vdagent_x11_get_atom_name(x11, target)); ++ VSELPRINTF("unexpected selection type %s", ++ vdagent_x11_get_atom_name(x11, target)); + return VD_AGENT_CLIPBOARD_NONE; + } + +@@ -834,7 +834,8 @@ static void vdagent_x11_handle_selection_notify(struct vdagent_x11 *x11, + type = vdagent_x11_target_to_type(x11, selection, + x11->conversion_req->target); + if (type == VD_AGENT_CLIPBOARD_NONE) +- syslog(LOG_ERR, "internal error conversion_req has bad target"); ++ SELPRINTF("internal error conversion_req has bad target %s", ++ vdagent_x11_get_atom_name(x11, x11->conversion_req->target)); + if (len == 0) { /* No errors so far */ + len = vdagent_x11_get_selection(x11, event, selection, + x11->conversion_req->target, +@@ -1064,7 +1065,7 @@ static void vdagent_x11_handle_selection_request(struct vdagent_x11 *x11) + type = vdagent_x11_target_to_type(x11, selection, + event->xselectionrequest.target); + if (type == VD_AGENT_CLIPBOARD_NONE) { +- syslog(LOG_ERR, "guest app requested a non-advertised target"); ++ VSELPRINTF("guest app requested a non-advertised target"); + vdagent_x11_send_selection_notify(x11, None, NULL); + return; + } +@@ -1310,7 +1311,7 @@ void vdagent_x11_clipboard_release(struct vdagent_x11 *x11, uint8_t selection) + } + + if (x11->clipboard_owner[selection] != owner_client) { +- SELPRINTF("received release while not owning client clipboard"); ++ VSELPRINTF("received release while not owning client clipboard"); + return; + } + +-- +2.20.1 + diff --git a/SPECS/spice-vdagent.spec b/SPECS/spice-vdagent.spec new file mode 100644 index 0000000..3cb11dd --- /dev/null +++ b/SPECS/spice-vdagent.spec @@ -0,0 +1,289 @@ +Name: spice-vdagent +Version: 0.14.0 +Release: 18%{?dist} +Summary: Agent for Spice guests +Group: Applications/System +License: GPLv3+ +URL: http://spice-space.org/ +Source0: http://spice-space.org/download/releases/%{name}-%{version}.tar.bz2 +# Fixes from upstream git +Patch1: 0001-vdagent-d-Add-printing-of-version-to-h-output.patch +Patch2: 0002-vdagentd-Advertise-VD_AGENT_CAP_GUEST_LINEEND_LF.patch +Patch3: 0003-buildsys-Build-vdagentd-as-pie-relro-when-possible.patch +Patch4: 0004-Not-having-the-virtio-channel-is-not-an-error-instea.patch +Patch5: 0005-vdagent-x11-Release-clipboard-on-client-disconnect-i.patch +#This patch is in the RHEL6 build but omitted on purpose from the RHEL7 +#build, see https://bugzilla.redhat.com/show_bug.cgi?id=1131454#c2 for +#details +#Patch6: 0006-randr-set-physical-screen-size-to-keep-a-constant-96.patch +Patch7: 0007-clipboard-target_to_type-fix-inner-loop-variable-nam.patch +Patch8: 0008-Reply-to-TIMESTAMP-requests.patch +Patch9: 0009-Handle-STRING-selection-type.patch +Patch10: 0010-randr-Make-resolution-changing-more-robust.patch +Patch11: 0011-Don-t-abort-if-XRRSetCrtcConfig-fails.patch +Patch12: 0012-Fix-gdm-autostart-path.patch +Patch13: 0013-data-remove-rsyslog-config-files.patch +Patch14: 0014-vdagent-file-xfers-only-open-the-file-transfer-dir-w.patch +Patch15: 0015-audio-add-functions-to-set-volume-mute-with-alsa.patch +Patch16: 0016-vdagent-volume-synchronization-from-client.patch +Patch17: 0017-vdagentd-proto-strings-Add-missing-string-for-VDAGEN.patch +Patch18: 0018-vdagent-Return-1-when-virtio-device-cannot-be-opened.patch +Patch19: 0019-build-sys-Enable-large-file-support.patch +Patch20: 0020-Add-g_return_if_fail-guards-to-file-xfer-public-func.patch +Patch21: 0021-Make-creation-of-vdagent_file_xfers-optional.patch +Patch22: 0022-Disable-file-xfer-when-no-suitable-destination-dir.patch +Patch23: 0023-Report-an-error-when-file-transfers-are-disabled.patch +Patch24: 0024-vdagentd-send-file-xfer-status-generic-version.patch +Patch25: 0025-session-info-check-for-a-locked-session.patch +Patch26: 0026-session-info-check-if-session-belongs-to-user.patch +Patch27: 0027-systemd-login-check-for-LockedHint-property.patch +Patch28: 0028-Add-systemd-socket-activation.patch +Patch29: 0029-spice-vdagent.desktop-Change-autostart-to-WindowMana.patch +Patch30: 0030-systemd-Remove-unneded-virtio-port-dependencies.patch +Patch31: 0031-systemd-Remove-WantedBy-sockets.service-in-Install.patch +Patch32: 0032-systemd-Update-path-in-unit-file.patch +Patch33: 0033-udscs-Avoid-file-descriptor-leak.patch +Patch34: 0034-x11-invalidate-requests-for-targets-on-grab-from-cli.patch +Patch35: 0035-vdagent_x11_target_to_type-Improve-error-logging.patch +Patch36: 0036-vdagent-x11-Turn-some-error-messages-into-debugging-.patch + + +BuildRequires: systemd-devel glib2-devel spice-protocol >= 0.12.6 +BuildRequires: libpciaccess-devel libXrandr-devel libXinerama-devel +BuildRequires: libXfixes-devel systemd-units desktop-file-utils libtool +BuildRequires: alsa-lib-devel dbus-devel +Requires(post): systemd-units +Requires(preun): systemd-units +Requires(postun): systemd-units +Requires: dbus systemd >= 219-21 + +%description +Spice agent for Linux guests offering the following features: + +Features: +* Client mouse mode (no need to grab mouse by client, no mouse lag) + this is handled by the daemon by feeding mouse events into the kernel + via uinput. This will only work if the active X-session is running a + spice-vdagent process so that its resolution can be determined. +* Automatic adjustment of the X-session resolution to the client resolution +* Support of copy and paste (text and images) between the active X-session + and the client + + +%prep +%setup -q +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 +%patch25 -p1 +%patch26 -p1 +%patch27 -p1 +%patch28 -p1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +%patch33 -p1 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 +autoreconf -fi + + +%build +%configure --with-session-info=systemd --with-init-script=systemd +make %{?_smp_mflags} V=2 + + +%install +make install DESTDIR=$RPM_BUILD_ROOT V=2 +# rhbz#963201 +rm $RPM_BUILD_ROOT%{_sysconfdir}/modules-load.d/spice-vdagentd.conf + + +%post +%systemd_post spice-vdagentd.service spice-vdagentd.socket + +%preun +%systemd_preun spice-vdagentd.service spice-vdagentd.socket + +%postun +%systemd_postun_with_restart spice-vdagentd.service spice-vdagentd.socket + + +%files +%doc COPYING ChangeLog README TODO +/lib/udev/rules.d/70-spice-vdagentd.rules +%{_unitdir}/spice-vdagentd.service +%{_unitdir}/spice-vdagentd.socket +%{_prefix}/lib/tmpfiles.d/spice-vdagentd.conf +%{_bindir}/spice-vdagent +%{_sbindir}/spice-vdagentd +%{_var}/run/spice-vdagentd +%{_sysconfdir}/xdg/autostart/spice-vdagent.desktop +# For /usr/share/gdm/autostart/LoginWindow/spice-vdagent.desktop +# We own the dir too, otherwise we must Require gdm +%{_datadir}/gdm +%{_mandir}/man1/%{name}*.1* + + +%changelog +* Mon Apr 8 2019 Victor Toso - 0.14.0-18 +- Fix clipboard logs on requests for targets on grab from client + Resolves: rhbz#1594876 +- Make some clipboard logs debug instead of error + Resolves: rhbz#1686008 + +* Fri Mar 15 2019 Victor Toso - 0.14.0-17 +- Fix 'Dependency failed for Activation socket' message + Resolves: rhbz#1545212 +- Fix socket leak + Resolves: rhbz#1650596 + +* Fri Sep 7 2018 Victor Toso - 0.14.0-16 +- Change session agent initialization stage to WindowManager + Resolves: rhbz#1623947 + +* Fri Nov 17 2017 Jonathon Jongsma - 0.14.0-15 +- Add systemd socket activation + Resolves: rhbz#1340160 + +* Fri Jul 8 2016 Victor Toso - 0.14.0-14 +- Do not allow drag-and-drop on (gdm) login screen + Resolves: rhbz#1328761 +- Do not allow drag-and-drop on locked screen + Resolves: rhbz#1323623 + +* Thu Apr 28 2016 Christophe Fergeau - 0.14.0-13 +- Enable large file support + Resolves: rhbz#1331490 + +* Thu Apr 28 2016 Christophe Fergeau - 0.14.0-12 +- Apply patches forgotten in previous build.. + Related: rhbz#1264102, rhbz#1256704 + +* Thu Apr 28 2016 Christophe Fergeau - 0.14.0-11 +- Add client to guest audio volume synchronization + Resolves: rhbz#1264102 +- Exit with error when virtio channel device is missing + Resolves: rhbz#1256704 + +* Fri Jun 05 2015 Jonathon Jongsma - 0.14.0-10 +- Don't open a separate file manager for each file transfered + Resolves: rhbz#1168324 + +* Tue Sep 23 2014 Christophe Fergeau 0.14.0-9 +- Don't install rsyslog config file. This can cause duplicate logging + to syslog in rhel6->rhel7 upgrades, and is not really useful anyway + as the same functionality can be achieved with journald + Resolves: rhbz#1136881 + +* Tue Aug 19 2014 Christophe Fergeau 0.14.0-8 +- Fix copy and paste issues with vncclient + Resolves: rhbz#1130218 +- Make vdagent more robust against xrandr failures + Resolves: rhbz#1066422 +- Fix autostart of vdagent in gdm + Resolves: rhbz#1052172 + +* Fri Jan 24 2014 Daniel Mach - 0.14.0-7 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 0.14.0-6 +- Mass rebuild 2013-12-27 + +* Tue Sep 10 2013 Hans de Goede - 0.14.0-5 +- Silence session agent error logging when not running in a vm (rhbz#999804) +- Release guest clipboard ownership on client disconnect (rhbz#1003977) + +* Sun Aug 04 2013 Fedora Release Engineering - 0.14.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Wed Jul 3 2013 Hans de Goede - 0.14.0-3 +- Advertise clipboard line-endings for copy and paste line-ending conversion +- Build spice-vdagentd as pie + relro + +* Mon May 20 2013 Hans de Goede - 0.14.0-2 +- Drop the no longer needed /etc/modules-load.d/spice-vdagentd.conf (#963201) + +* Fri Apr 12 2013 Hans de Goede - 0.14.0-1 +- New upstream release 0.14.0 +- Adds support for file transfers from client to guest +- Adds manpages for spice-vdagent and spice-vdagentd + +* Fri Feb 15 2013 Fedora Release Engineering - 0.12.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Tue Jan 8 2013 Hans de Goede - 0.12.1-1 +- New upstream release 0.12.1 +- Fixes various issues with dynamic monitor / resolution support + +* Mon Nov 12 2012 Hans de Goede - 0.12.0-2 +- Fix setting of mode on non arbitrary resolution capable X driver +- Fix wrong mouse coordinates on vms with multiple qxl devices + +* Sat Sep 1 2012 Hans de Goede - 0.12.0-1 +- New upstream release 0.12.0 +- This moves the tmpfiles.d to /usr/lib/tmpfiles.d (rhbz#840194) +- This adds a systemd .service file (rhbz#848102) + +* Sat Jul 21 2012 Fedora Release Engineering - 0.10.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Mar 27 2012 Hans de Goede - 0.10.1-1 +- New upstream release 0.10.1 + +* Thu Mar 22 2012 Hans de Goede - 0.10.0-1 +- New upstream release 0.10.0 +- This supports using systemd-logind instead of console-kit (rhbz#756398) + +* Sat Jan 14 2012 Fedora Release Engineering - 0.8.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Mon Jul 18 2011 Hans de Goede 0.8.1-1 +- New upstream release 0.8.1 + +* Fri Jul 15 2011 Hans de Goede 0.8.0-2 +- Make the per session agent process automatically reconnect to the system + spice-vdagentd when the system daemon gets restarted + +* Tue Apr 19 2011 Hans de Goede 0.8.0-1 +- New upstream release 0.8.0 + +* Mon Mar 07 2011 Hans de Goede 0.6.3-6 +- Fix setting of the guest resolution from a multi monitor client + +* Wed Feb 09 2011 Fedora Release Engineering - 0.6.3-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Mon Jan 10 2011 Hans de Goede 0.6.3-4 +- Make sysvinit script exit cleanly when not running on a spice enabled vm + +* Fri Nov 19 2010 Hans de Goede 0.6.3-3 +- Put the pid and log files into their own subdir (#648553) + +* Mon Nov 8 2010 Hans de Goede 0.6.3-2 +- Fix broken multiline description in initscript lsb header (#648549) + +* Sat Oct 30 2010 Hans de Goede 0.6.3-1 +- Initial Fedora package