From ac8c26f633b01bb32cdf347f9dbd5a80c6712925 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 16 Jul 2013 20:19:40 +0200 Subject: char: io_channel_send: don't lose written bytes 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 --- qemu-char.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) (limited to 'qemu-char.c') diff --git a/qemu-char.c b/qemu-char.c index 800d6a62f9..c86ce4ba2e 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -720,35 +720,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 -- cgit v1.2.1