From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54366) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uz9oT-0003aF-12 for qemu-devel@nongnu.org; Tue, 16 Jul 2013 14:17:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Uz9oM-00078I-Pr for qemu-devel@nongnu.org; Tue, 16 Jul 2013 14:17:24 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37373) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uz9oM-000783-GP for qemu-devel@nongnu.org; Tue, 16 Jul 2013 14:17:18 -0400 From: Laszlo Ersek Date: Tue, 16 Jul 2013 20:19:40 +0200 Message-Id: <1373998781-29561-2-git-send-email-lersek@redhat.com> In-Reply-To: <1373998781-29561-1-git-send-email-lersek@redhat.com> References: <1373998781-29561-1-git-send-email-lersek@redhat.com> Subject: [Qemu-devel] [PATCH 1/2] char: io_channel_send: don't lose written bytes List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Anthony Liguori , Luiz Capitulino , qemu-devel@nongnu.org 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 --- qemu-char.c | 41 +++++++++++++++++++---------------------- 1 files changed, 19 insertions(+), 22 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 800d6a6..c86ce4b 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 -- 1.7.1