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>
This commit is contained in:
parent
f60a1cdca5
commit
c5f2bce5ee
37
ui/console.c
37
ui/console.c
@ -33,6 +33,7 @@
|
|||||||
#include "chardev/char-fe.h"
|
#include "chardev/char-fe.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "exec/memory.h"
|
#include "exec/memory.h"
|
||||||
|
#include "io/channel-file.h"
|
||||||
|
|
||||||
#define DEFAULT_BACKSCROLL 512
|
#define DEFAULT_BACKSCROLL 512
|
||||||
#define CONSOLE_CURSOR_PERIOD 500
|
#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 width = pixman_image_get_width(ds->image);
|
||||||
int height = pixman_image_get_height(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 y;
|
||||||
int ret;
|
|
||||||
pixman_image_t *linebuf;
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
trace_ppm_save(fd, ds);
|
trace_ppm_save(fd, ds);
|
||||||
f = fdopen(fd, "wb");
|
|
||||||
ret = fprintf(f, "P6\n%d %d\n%d\n", width, height, 255);
|
header = g_strdup_printf("P6\n%d %d\n%d\n", width, height, 255);
|
||||||
if (ret < 0) {
|
if (qio_channel_write_all(QIO_CHANNEL(ioc),
|
||||||
linebuf = NULL;
|
header, strlen(header), errp) < 0) {
|
||||||
goto end;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width);
|
linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width);
|
||||||
for (y = 0; y < height; y++) {
|
for (y = 0; y < height; y++) {
|
||||||
qemu_pixman_linebuf_fill(linebuf, ds->image, width, 0, y);
|
qemu_pixman_linebuf_fill(linebuf, ds->image, width, 0, y);
|
||||||
clearerr(f);
|
if (qio_channel_write_all(QIO_CHANNEL(ioc),
|
||||||
ret = fwrite(pixman_image_get_data(linebuf), 1,
|
(char *)pixman_image_get_data(linebuf),
|
||||||
pixman_image_get_stride(linebuf), f);
|
pixman_image_get_stride(linebuf), errp) < 0) {
|
||||||
(void)ret;
|
return false;
|
||||||
success = !ferror(f);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
return true;
|
||||||
if (!success) {
|
|
||||||
error_setg(errp, "failed to write to PPM file: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
qemu_pixman_image_unref(linebuf);
|
|
||||||
fclose(f);
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_screendump(const char *filename, bool has_device, const char *device,
|
void qmp_screendump(const char *filename, bool has_device, const char *device,
|
||||||
|
Loading…
Reference in New Issue
Block a user