From ddc3793752ae726e761173ce214ab895b936d15a Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Fri, 19 Jul 2013 13:05:22 +0200 Subject: char: io_channel_send: don't lose written bytes RH-Author: Laszlo Ersek Message-id: <1374239123-4841-2-git-send-email-lersek@redhat.com> Patchwork-id: 52615 O-Subject: [RHEL-7 qemu-kvm PATCH 1/2] char: io_channel_send: don't lose written bytes Bugzilla: 970047 RH-Acked-by: Amit Shah RH-Acked-by: Markus Armbruster RH-Acked-by: Luiz Capitulino The g_io_channel_write_chars() documentation states, bytes_written: The number of bytes written. This can be nonzero even if the return value is not G_IO_STATUS_NORMAL. [...] io_channel_send() could lose such bytes before. Furthermore, the (status == G_IO_STATUS_EOF) condition used to evaluate to constant false whenever it was reached. When that condition actually held, it always led to -1 / EINVAL. This patch (almost) distinguishes G_IO_STATUS_EOF only when no bytes have been written, and then treats it as an error. Signed-off-by: Laszlo Ersek Reviewed-by: Amit Shah Reviewed-by: Anthony Liguori Message-id: 1373998781-29561-2-git-send-email-lersek@redhat.com Signed-off-by: Anthony Liguori (cherry picked from commit ac8c26f633b01bb32cdf347f9dbd5a80c6712925) diff --git a/qemu-char.c b/qemu-char.c index efe706d..c01deae 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -722,35 +722,32 @@ static GIOChannel *io_channel_from_socket(int fd) static int io_channel_send(GIOChannel *fd, const void *buf, size_t len) { - GIOStatus status; - size_t offset; + size_t offset = 0; + GIOStatus status = G_IO_STATUS_NORMAL; - offset = 0; - while (offset < len) { - gsize bytes_written; + while (offset < len && status == G_IO_STATUS_NORMAL) { + gsize bytes_written = 0; status = g_io_channel_write_chars(fd, buf + offset, len - offset, &bytes_written, NULL); - if (status != G_IO_STATUS_NORMAL) { - if (status == G_IO_STATUS_AGAIN) { - /* If we've written any data, return a partial write. */ - if (offset) { - break; - } - errno = EAGAIN; - } else { - errno = EINVAL; - } - - return -1; - } else if (status == G_IO_STATUS_EOF) { - break; - } - offset += bytes_written; } - return offset; + if (offset > 0) { + return offset; + } + switch (status) { + case G_IO_STATUS_NORMAL: + g_assert(len == 0); + return 0; + case G_IO_STATUS_AGAIN: + errno = EAGAIN; + return -1; + default: + break; + } + errno = EINVAL; + return -1; } #ifndef _WIN32