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 <lersek@redhat.com>
Reviewed-by: Amit Shah <amit.shah@redhat.com>
Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Message-id: 1373998781-29561-2-git-send-email-lersek@redhat.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
			
			
This commit is contained in:
		
							parent
							
								
									0d185e6388
								
							
						
					
					
						commit
						ac8c26f633
					
				
							
								
								
									
										39
									
								
								qemu-char.c
								
								
								
								
							
							
						
						
									
										39
									
								
								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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue