Thanks Acked-by: Jonathon Jongsma <jjongsma@xxxxxxxxxx> On Thu, 2016-05-26 at 10:20 +0100, Frediano Ziglio wrote: > This allows compression using external programs or any type > of filters. > > To use it set SPICE_WORKER_RECORD_FILTER environment to the > filter command you want to use. The command is executed with > g_spawn_async_with_pipes (which uses execve) so is not a shell > command although the command is parsed using g_shell_parse_argv > which split arguments as shell does. > > One easy way to use it is to just use a compressor like gzip with > > export SPICE_WORKER_RECORD_FILENAME=/tmp/qemu_record.gz > export SPICE_WORKER_RECORD_FILTER=gzip > qemu ... > > The filter will receive the recording on standard input and is > supposed to write in output filename (which is the standard output). > You can use additional arguments in SPICE_WORKER_RECORD_FILTER to > specify for instance compression level. > > Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> > --- > server/red-record-qxl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 45 insertions(+) > > Changes from v2: > - clarify comment removed unneeded and confusing notes; > - rename out_setup to child_output_setup; > - add some comments. > > diff --git a/server/red-record-qxl.c b/server/red-record-qxl.c > index 5337699..c6cd963 100644 > --- a/server/red-record-qxl.c > +++ b/server/red-record-qxl.c > @@ -21,6 +21,8 @@ > > #include <stdbool.h> > #include <inttypes.h> > +#include <fcntl.h> > +#include <glib.h> > #include "red-worker.h" > #include "red-common.h" > #include "memslot.h" > @@ -834,10 +836,26 @@ void red_record_qxl_command(RedRecord *record, > RedMemSlotInfo *slots, > } > } > > +/** > + * Redirects child output to the file specified > + */ > +static void child_output_setup(gpointer user_data) > +{ > + int fd = GPOINTER_TO_INT(user_data); > + > + while (dup2(fd, STDOUT_FILENO) < 0 && errno == EINTR) > + continue; > + close(fd); > + > + // make sure file is not closed calling exec() > + fcntl(STDOUT_FILENO, F_SETFD, 0); > +} > + > RedRecord *red_record_new(const char *filename) > { > static const char header[] = "SPICE_REPLAY 1\n"; > > + const char *filter; > FILE *f; > RedRecord *record; > > @@ -846,6 +864,33 @@ RedRecord *red_record_new(const char *filename) > spice_error("failed to open recording file %s\n", filename); > } > > + filter = getenv("SPICE_WORKER_RECORD_FILTER"); > + if (filter) { > + gint argc; > + gchar **argv = NULL; > + GError *error = NULL; > + GPid child_pid; > + gboolean ret; > + gint fd_in; > + > + ret = g_shell_parse_argv(filter, &argc, &argv, &error); > + > + if (ret) > + ret = g_spawn_async_with_pipes(NULL, argv, NULL, > G_SPAWN_SEARCH_PATH, > + child_output_setup, > GINT_TO_POINTER(fileno(f)), &child_pid, > + &fd_in, NULL, NULL, &error); > + > + g_strfreev(argv); > + if (!ret) { > + g_error_free(error); > + fclose(f); > + spice_error("failed to setup filter for replay"); > + } > + while (dup2(fd_in, fileno(f)) < 0 && errno == EINTR) > + continue; > + close(fd_in); > + } > + > if (fwrite(header, sizeof(header)-1, 1, f) != 1) { > spice_error("failed to write replay header"); > } _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel