mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-01-04 00:06:29 +00:00
replay: allows to specify a filter for record output
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@redhat.com> Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
This commit is contained in:
parent
751a0aeb51
commit
82caf14025
@ -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");
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user