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
					
				
							
								
								
									
										41
									
								
								qemu-char.c
								
								
								
								
							
							
						
						
									
										41
									
								
								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)
 | 
					static int io_channel_send(GIOChannel *fd, const void *buf, size_t len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GIOStatus status;
 | 
					    size_t offset = 0;
 | 
				
			||||||
    size_t offset;
 | 
					    GIOStatus status = G_IO_STATUS_NORMAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    offset = 0;
 | 
					    while (offset < len && status == G_IO_STATUS_NORMAL) {
 | 
				
			||||||
    while (offset < len) {
 | 
					        gsize bytes_written = 0;
 | 
				
			||||||
        gsize bytes_written;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        status = g_io_channel_write_chars(fd, buf + offset, len - offset,
 | 
					        status = g_io_channel_write_chars(fd, buf + offset, len - offset,
 | 
				
			||||||
                                          &bytes_written, NULL);
 | 
					                                          &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;
 | 
					        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
 | 
					#ifndef _WIN32
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue