diff options
author | Marc-André Lureau <marcandre.lureau@redhat.com> | 2019-11-08 17:31:43 +0400 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@redhat.com> | 2020-01-02 16:29:32 +0400 |
commit | c5f2bce5ee75ec3267b025f2053bac728da9a6c3 (patch) | |
tree | b721e4e5bdd337a8aafa104f43a9a324343fb53b /ui/console.c | |
parent | f60a1cdca52dd9cf49aad768471d9e0ea6751f76 (diff) | |
download | qemu-c5f2bce5ee75ec3267b025f2053bac728da9a6c3.zip qemu-c5f2bce5ee75ec3267b025f2053bac728da9a6c3.tar.gz qemu-c5f2bce5ee75ec3267b025f2053bac728da9a6c3.tar.bz2 |
screendump: replace FILE with QIOChannel and fix close()/qemu_close()
The file opened for ppm_save() may be a /dev/fdset, in which case a
dup fd is added to the fdset. It should be removed by calling
qemu_close(), instead of the implicit close() on fclose().
I don't see a convenient way to solve that with stdio streams, so I
switched the code to QIOChannel which uses qemu_close().
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Diffstat (limited to 'ui/console.c')
-rw-r--r-- | ui/console.c | 37 |
1 files changed, 16 insertions, 21 deletions
diff --git a/ui/console.c b/ui/console.c index 77d62fe..82c0b72 100644 --- a/ui/console.c +++ b/ui/console.c @@ -33,6 +33,7 @@ #include "chardev/char-fe.h" #include "trace.h" #include "exec/memory.h" +#include "io/channel-file.h" #define DEFAULT_BACKSCROLL 512 #define CONSOLE_CURSOR_PERIOD 500 @@ -313,36 +314,30 @@ static bool ppm_save(int fd, DisplaySurface *ds, Error **errp) { int width = pixman_image_get_width(ds->image); int height = pixman_image_get_height(ds->image); - FILE *f; + g_autoptr(Object) ioc = OBJECT(qio_channel_file_new_fd(fd)); + g_autofree char *header = NULL; + g_autoptr(pixman_image_t) linebuf = NULL; int y; - int ret; - pixman_image_t *linebuf; - bool success = false; trace_ppm_save(fd, ds); - f = fdopen(fd, "wb"); - ret = fprintf(f, "P6\n%d %d\n%d\n", width, height, 255); - if (ret < 0) { - linebuf = NULL; - goto end; + + header = g_strdup_printf("P6\n%d %d\n%d\n", width, height, 255); + if (qio_channel_write_all(QIO_CHANNEL(ioc), + header, strlen(header), errp) < 0) { + return false; } + linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width); for (y = 0; y < height; y++) { qemu_pixman_linebuf_fill(linebuf, ds->image, width, 0, y); - clearerr(f); - ret = fwrite(pixman_image_get_data(linebuf), 1, - pixman_image_get_stride(linebuf), f); - (void)ret; - success = !ferror(f); + if (qio_channel_write_all(QIO_CHANNEL(ioc), + (char *)pixman_image_get_data(linebuf), + pixman_image_get_stride(linebuf), errp) < 0) { + return false; + } } -end: - if (!success) { - error_setg(errp, "failed to write to PPM file: %s", strerror(errno)); - } - qemu_pixman_image_unref(linebuf); - fclose(f); - return success; + return true; } void qmp_screendump(const char *filename, bool has_device, const char *device, |