X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/a57873b71028ac790cc81f41468514d008d5c771..b35d0d8e9ae9c5407c9f781b545f8a66b9caa9d0:/io.c diff --git a/io.c b/io.c index e57d0708..ed6a70c3 100644 --- a/io.c +++ b/io.c @@ -2,7 +2,7 @@ Copyright (C) 1996-2001 by Andrew Tridgell Copyright (C) Paul Mackerras 1996 - Copyright (C) 2001 by Martin Pool + Copyright (C) 2001, 2002 by Martin Pool This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,11 +19,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* - socket and pipe IO utilities used in rsync +/** + * @file io.c + * + * Socket and pipe IO utilities used in rsync. + * + * rsync provides its own multiplexing system, which is used to send + * stderr and stdout over a single socket. We need this because + * stdout normally carries the binary data stream, and stderr all our + * error messages. + * + * For historical reasons this is off during the start of the + * connection, but it's switched on quite early using + * io_start_multiplex_out() and io_start_multiplex_in(). + **/ - tridge, June 1996 - */ #include "rsync.h" /* if no timeout is specified then use a 60 second select timeout */ @@ -49,7 +59,7 @@ int kludge_around_eof = False; static int io_error_fd = -1; -static void read_loop(int fd, char *buf, int len); +static void read_loop(int fd, char *buf, size_t len); static void check_timeout(void) { @@ -86,7 +96,7 @@ void io_set_error_fd(int fd) static void read_error_fd(void) { char buf[200]; - int n; + size_t n; int fd = io_error_fd; int tag, len; @@ -103,7 +113,8 @@ static void read_error_fd(void) while (len) { n = len; - if (n > (sizeof(buf)-1)) n = sizeof(buf)-1; + if (n > (sizeof(buf)-1)) + n = sizeof(buf)-1; read_loop(fd, buf, n); rwrite((enum logcode)tag, buf, n); len -= n; @@ -163,7 +174,7 @@ static void die_from_readerr (int err) * give a better explanation. We can tell whether the connection has * started by looking e.g. at whether the remote version is known yet. */ -static int read_timeout (int fd, char *buf, int len) +static int read_timeout (int fd, char *buf, size_t len) { int n, ret=0; @@ -236,7 +247,7 @@ static int read_timeout (int fd, char *buf, int len) /*! Continue trying to read len bytes - don't return until len has been read. */ -static void read_loop (int fd, char *buf, int len) +static void read_loop (int fd, char *buf, size_t len) { while (len) { int n = read_timeout(fd, buf, len); @@ -253,10 +264,10 @@ static void read_loop (int fd, char *buf, int len) * * Never returns <= 0. */ -static int read_unbuffered(int fd, char *buf, int len) +static int read_unbuffered(int fd, char *buf, size_t len) { - static int remaining; - int tag, ret=0; + static size_t remaining; + int tag, ret = 0; char line[1024]; if (!io_multiplexing_in || fd != multiplex_in_fd) @@ -271,23 +282,24 @@ static int read_unbuffered(int fd, char *buf, int len) continue; } - read_loop (fd, line, 4); + read_loop(fd, line, 4); tag = IVAL(line, 0); remaining = tag & 0xFFFFFF; tag = tag >> 24; - if (tag == MPLEX_BASE) continue; + if (tag == MPLEX_BASE) + continue; tag -= MPLEX_BASE; if (tag != FERROR && tag != FINFO) { - rprintf(FERROR,"unexpected tag %d\n", tag); + rprintf(FERROR, "unexpected tag %d\n", tag); exit_cleanup(RERR_STREAMIO); } - if (remaining > sizeof(line)-1) { - rprintf(FERROR,"multiplexing overflow %d\n\n", + if (remaining > sizeof(line) - 1) { + rprintf(FERROR, "multiplexing overflow %d\n\n", remaining); exit_cleanup(RERR_STREAMIO); } @@ -295,7 +307,7 @@ static int read_unbuffered(int fd, char *buf, int len) read_loop(fd, line, remaining); line[remaining] = 0; - rprintf((enum logcode)tag,"%s", line); + rprintf((enum logcode) tag, "%s", line); remaining = 0; } @@ -303,12 +315,13 @@ static int read_unbuffered(int fd, char *buf, int len) } + /* do a buffered read from fd. don't return until all N bytes have been read. If all N can't be read then exit with an error */ -static void readfd (int fd, char *buffer, int N) +static void readfd (int fd, char *buffer, size_t N) { int ret; - int total=0; + size_t total=0; while (total < N) { io_flush(); @@ -356,12 +369,12 @@ int64 read_longint(int f) return ret; } -void read_buf(int f,char *buf,int len) +void read_buf(int f,char *buf,size_t len) { readfd(f,buf,len); } -void read_sbuf(int f,char *buf,int len) +void read_sbuf(int f,char *buf,size_t len) { read_buf (f,buf,len); buf[len] = 0; @@ -374,10 +387,11 @@ unsigned char read_byte(int f) return c; } -/* write len bytes to fd */ -static void writefd_unbuffered(int fd,char *buf,int len) +/* Write len bytes to fd. This underlies the multiplexing system, + * which is always called by application code. */ +static void writefd_unbuffered(int fd,char *buf,size_t len) { - int total = 0; + size_t total = 0; fd_set w_fds, r_fds; int fd_count, count; struct timeval tv; @@ -424,7 +438,8 @@ static void writefd_unbuffered(int fd,char *buf,int len) } if (FD_ISSET(fd, &w_fds)) { - int ret, n = len-total; + int ret; + size_t n = len-total; ret = write(fd,buf+total,n); if (ret == -1 && errno == EINTR) { @@ -438,8 +453,11 @@ static void writefd_unbuffered(int fd,char *buf,int len) } if (ret <= 0) { - rprintf(FERROR, - "error writing %d unbuffered bytes" + /* Don't try to write errors back + * across the stream */ + io_multiplexing_close(); + rprintf(FERROR, RSYNC_NAME + ": error writing %d unbuffered bytes" " - exiting: %s\n", len, strerror(errno)); exit_cleanup(RERR_STREAMIO); @@ -483,10 +501,10 @@ void io_start_buffering(int fd) /* write an message to a multiplexed stream. If this fails then rsync exits */ -static void mplex_write(int fd, enum logcode code, char *buf, int len) +static void mplex_write(int fd, enum logcode code, char *buf, size_t len) { char buffer[4096]; - int n = len; + size_t n = len; SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len); @@ -523,8 +541,7 @@ void io_flush(void) } -/* XXX: fd is ignored, which seems a little strange. */ -void io_end_buffering(int fd) +void io_end_buffering(void) { io_flush(); if (!io_multiplexing_out) { @@ -533,7 +550,7 @@ void io_end_buffering(int fd) } } -static void writefd(int fd,char *buf,int len) +static void writefd(int fd,char *buf,size_t len) { stats.total_written += len; @@ -545,7 +562,7 @@ static void writefd(int fd,char *buf,int len) } while (len) { - int n = MIN(len, IO_BUFFER_SIZE-io_buffer_count); + int n = MIN((int) len, IO_BUFFER_SIZE-io_buffer_count); if (n > 0) { memcpy(io_buffer+io_buffer_count, buf, n); buf += n; @@ -587,7 +604,7 @@ void write_longint(int f, int64 x) writefd(f,b,8); } -void write_buf(int f,char *buf,int len) +void write_buf(int f,char *buf,size_t len) { writefd(f,buf,len); } @@ -606,12 +623,19 @@ void write_byte(int f,unsigned char c) -int read_line(int f, char *buf, int maxlen) +/** + * Read a line of up to @p maxlen characters into @p buf. Does not + * contain a trailing newline or carriage return. + * + * @return 1 for success; 0 for io error or truncation. + **/ +int read_line(int f, char *buf, size_t maxlen) { while (maxlen) { buf[0] = 0; read_buf(f, buf, 1); - if (buf[0] == 0) return 0; + if (buf[0] == 0) + return 0; if (buf[0] == '\n') { buf[0] = 0; break; @@ -664,7 +688,7 @@ void io_start_multiplex_in(int fd) } /* write an message to the multiplexed error stream */ -int io_multiplex_write(enum logcode code, char *buf, int len) +int io_multiplex_write(enum logcode code, char *buf, size_t len) { if (!io_multiplexing_out) return 0;