/* * Socket and pipe I/O utilities used in rsync. * * Copyright (C) 1996-2001 Andrew Tridgell * Copyright (C) 1996 Paul Mackerras * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org> * Copyright (C) 2003-2022 Wayne Davison * * 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 * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, visit the http://fsf.org website. */ /* Rsync provides its own multiplexing system, which is used to send * stderr and stdout over a single socket. * * 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(). */ #include "rsync.h"#include "ifuncs.h"#include "inums.h" #include <poll.h> /* Readiness bits we act on. poll() can report POLLERR/POLLHUP/POLLNVAL even * when they were not requested, and POLLPRI stands in for select()'s old * exception set. */#define POLL_RD_BITS (POLLIN | POLLPRI | POLLERR | POLLHUP)#define POLL_WR_BITS (POLLOUT | POLLERR | POLLHUP) /** If no timeout is specified then use a 60 second I/O timeout */#define SELECT_TIMEOUT 60 extern int bwlimit;extern size_t bwlimit_writemax;extern int io_timeout;extern int am_server;extern int am_sender;extern int am_receiver;extern int am_generator;extern int local_server;extern int msgs2stderr;extern int inc_recurse;extern int io_error;extern int batch_fd;extern int eol_nulls;extern int flist_eof;extern int file_total;extern int file_old_total;extern int list_only;extern int read_batch;extern int compat_flags;extern int protect_args;extern int checksum_seed;extern int xfer_sum_len;extern int daemon_connection;extern int protocol_version;extern int remove_source_files;extern int write_batch;extern int preserve_hard_links;extern BOOL extra_flist_sending_enabled;extern BOOL flush_ok_after_signal;extern struct stats stats;extern time_t stop_at_utime;extern struct file_list *cur_flist;#ifdef ICONV_OPTIONextern int filesfrom_convert;extern iconv_t ic_send, ic_recv;#endif int csum_length = SHORT_SUM_LENGTH; /* initial value */int allowed_lull = 0;int msgdone_cnt = 0;int forward_flist_data = 0;BOOL flist_receiving_enabled = False; /* Ignore an EOF error if non-zero. See whine_about_eof(). */int kluge_around_eof = 0;int got_kill_signal = -1; /* is set to 0 only after multiplexed I/O starts */volatile sig_atomic_t got_sigusr2 = 0; /* set by the async-signal-safe SIGUSR2 handler */ int sock_f_in = -1;int sock_f_out = -1; int64 total_data_read = 0;int64 total_data_written = 0; char num_dev_ino_buf[4 + 8 + 8]; static struct { xbuf in, out, msg; int in_fd; int out_fd; /* Both "out" and "msg" go to this fd. */ int in_multiplexed; unsigned out_empty_len; size_t raw_data_header_pos; /* in the out xbuf */ size_t raw_flushing_ends_before; /* in the out xbuf */ size_t raw_input_ends_before; /* in the in xbuf */} iobuf = { .in_fd = -1, .out_fd = -1 }; static time_t last_io_in;static time_t last_io_out; /* Absolute wall-clock bound for peer-controlled daemon handshake reads. * This is deliberately separate from io_timeout: the latter is an idle * transfer timeout and may be supplied by the module or client. */static time_t daemon_handshake_deadline; /* Wall-clock bound the client puts on establishing a daemon connection made * through a remote shell (daemon_connection == 1): spawning the helper, its * connect()/TLS handshake, and the exchange of the daemon greeting all happen * before any buffered I/O begins, so --contimeout can time the whole phase the * same way the socket path times its connect(). */static time_t client_connect_deadline; static int write_batch_monitor_in = -1;static int write_batch_monitor_out = -1; static int ff_forward_fd = -1;static int ff_reenable_multiplex = -1;static char ff_lastchar = '\0';static xbuf ff_xb = EMPTY_XBUF;#ifdef ICONV_OPTIONstatic xbuf iconv_buf = EMPTY_XBUF;#endifstatic int select_timeout = SELECT_TIMEOUT; /* Turn select_timeout (in seconds) into a poll() millisecond count, keeping it * positive and bounded. A negative count means "wait forever" to poll(), which * would bypass our keepalives and timeout enforcement entirely. */static int poll_timeout_ms(void){ int secs = select_timeout; if (secs <= 0 || secs > SELECT_TIMEOUT) secs = SELECT_TIMEOUT; return secs * 1000;} static int handshake_poll_timeout_ms(void){ time_t now, left; int timeout = poll_timeout_ms(); if (!daemon_handshake_deadline && !client_connect_deadline) return timeout; now = time(NULL); if (daemon_handshake_deadline) { left = daemon_handshake_deadline - now; if (left <= 0) { rprintf(FERROR, "[%s] daemon handshake timeout -- exiting\n", who_am_i()); exit_cleanup(RERR_TIMEOUT); } if (left <= INT_MAX / 1000 && left * 1000 < timeout) timeout = (int)left * 1000; } if (client_connect_deadline) { left = client_connect_deadline - now; if (left <= 0) { rprintf(FERROR, "[%s] connection timed out -- exiting\n", who_am_i()); exit_cleanup(RERR_CONTIMEOUT); } if (left <= INT_MAX / 1000 && left * 1000 < timeout) timeout = (int)left * 1000; } return timeout;} static int active_filecnt = 0;static OFF_T active_bytecnt = 0;static int first_message = 1; static const char int_byte_extra[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* (00 - 3F)/4 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* (40 - 7F)/4 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* (80 - BF)/4 */ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6, /* (C0 - FF)/4 */}; /* Our I/O buffers are sized with no bits on in the lowest byte of the "size" * (indeed, our rounding of sizes in 1024-byte units assures more than this). * This allows the code that is storing bytes near the physical end of a * circular buffer to temporarily reduce the buffer's size (in order to make * some storing idioms easier), while also making it simple to restore the * buffer's actual size when the buffer's "pos" wraps around to the start (we * just round the buffer's size up again). */ #define IOBUF_WAS_REDUCED(siz) ((siz) & 0xFF)#define IOBUF_RESTORE_SIZE(siz) (((siz) | 0xFF) + 1) #define IN_MULTIPLEXED (iobuf.in_multiplexed != 0)#define IN_MULTIPLEXED_AND_READY (iobuf.in_multiplexed > 0)#define OUT_MULTIPLEXED (iobuf.out_empty_len != 0) #define PIO_NEED_INPUT (1<<0) /* The *_NEED_* flags are mutually exclusive. */#define PIO_NEED_OUTROOM (1<<1)#define PIO_NEED_MSGROOM (1<<2) #define PIO_CONSUME_INPUT (1<<4) /* Must becombined with PIO_NEED_INPUT. */ #define PIO_INPUT_AND_CONSUME (PIO_NEED_INPUT | PIO_CONSUME_INPUT)#define PIO_NEED_FLAGS (PIO_NEED_INPUT | PIO_NEED_OUTROOM | PIO_NEED_MSGROOM) #define REMOTE_OPTION_ERROR "rsync: on remote machine: -"#define REMOTE_OPTION_ERROR2 ": unknown option" #define FILESFROM_BUFLEN 2048 enum festatus { FES_SUCCESS, FES_REDO, FES_NO_SEND }; static flist_ndx_list redo_list, hlink_list; static void read_a_msg(void);static void drain_multiplex_messages(void);static void sleep_for_bwlimit(int bytes_written); static void check_timeout(BOOL allow_keepalive, int keepalive_flags){ time_t t, chk; /* On the receiving side, the generator is now the one that decides * when a timeout has occurred. When it is sifting through a lot of * files looking for work, it will be sending keep-alive messages to * the sender, and even though the receiver won't be sending/receiving * anything (not even keep-alive messages), the successful writes to * the sender will keep things going. If the receiver is actively * receiving data, it will ensure that the generator knows that it is * not idle by sending the generator keep-alive messages (since the * generator might be blocked trying to send checksums, it needs to * know that the receiver is active). Thus, as long as one or the * other is successfully doing work, the generator will not timeout. */ if (!io_timeout) return; t = time(NULL); if (allow_keepalive) { /* This may put data into iobuf.msg w/o flushing. */ maybe_send_keepalive(t, keepalive_flags); } if (!last_io_in) last_io_in = t; if (am_receiver) return; chk = MAX(last_io_out, last_io_in); if (t - chk >= io_timeout) { if (am_server) msgs2stderr = 1; rprintf(FERROR, "[%s] io timeout after %d seconds -- exiting\n", who_am_i(), (int)(t-chk)); exit_cleanup(RERR_TIMEOUT); }} /* It's almost always an error to get an EOF when we're trying to read from the * network, because the protocol is (for the most part) self-terminating. * * There is one case for the receiver when it is at the end of the transfer * (hanging around reading any keep-alive packets that might come its way): if * the sender dies before the generator's kill-signal comes through, we can end * up here needing to loop until the kill-signal arrives. In this situation, * kluge_around_eof will be < 0. * * There is another case for older protocol versions (< 24) where the module * listing was not terminated, so we must ignore an EOF error in that case and * exit. In this situation, kluge_around_eof will be > 0. */static NORETURN void whine_about_eof(BOOL allow_kluge){ if (kluge_around_eof && allow_kluge) { int i; if (kluge_around_eof > 0) exit_cleanup(0); /* The receiver is waiting here for the generator's SIGUSR2; act on it * (exit cleanly) the moment it arrives rather than sleeping the full * 10s and then erroring. The async-signal-safe handler only sets the * flag, so this loop must poll it. */ for (i = 10*1000/20; i--; ) { if (got_sigusr2) receive_sigusr2(); msleep(20); } } rprintf(FERROR, RSYNC_NAME ": connection unexpectedly closed " "(%s bytes received so far) [%s]\n", big_num(stats.total_read), who_am_i()); exit_cleanup(RERR_STREAMIO);} /* Do a safe read, handling any needed looping and error handling. * Returns the count of the bytes read, which will only be different * from "len" if we encountered an EOF. This routine is not used on * the socket except very early in the transfer. */static size_t safe_read(int fd, char *buf, size_t len){ size_t got = 0; assert(fd != iobuf.in_fd); while (1) { struct pollfd pfd; int cnt; if (got_sigusr2) /* receiver told to wrap up (e.g. a --read-batch fd) */ receive_sigusr2(); /* We use poll() rather than select() so that a high-numbered fd * (>= FD_SETSIZE) cannot overflow an fd_set bitmap. */ pfd.fd = fd; pfd.events = POLLIN | POLLPRI; pfd.revents = 0; cnt = poll(&pfd, 1, handshake_poll_timeout_ms()); if (cnt <= 0) { if (cnt < 0 && errno != EINTR && errno != EAGAIN) { rsyserr(FERROR, errno, "safe_read poll failed"); exit_cleanup(RERR_FILEIO); } check_timeout(1, MSK_ALLOW_FLUSH); continue; } /* An invalid fd is reported here rather than via poll()'s return. */ if (pfd.revents & POLLNVAL) { rsyserr(FERROR, EBADF, "safe_read poll failed"); exit_cleanup(RERR_FILEIO); } if (pfd.revents & POLL_RD_BITS) { ssize_t n = read(fd, buf + got, len - got); if (DEBUG_GTE(IO, 2)) { rprintf(FINFO, "[%s] safe_read(%d)=%" SIZE_T_FMT_MOD "d\n", who_am_i(), fd, (SIZE_T_FMT_CAST)n); } if (n == 0) break; if (n < 0) { if (errno == EINTR) continue; rsyserr(FERROR, errno, "safe_read failed to read %" SIZE_T_FMT_MOD "d bytes", (SIZE_T_FMT_CAST)len); exit_cleanup(RERR_STREAMIO); } if ((got += (size_t)n) == len) break; } } return got;} static const char *what_fd_is(int fd){ static char buf[20]; if (fd == sock_f_out) return "socket"; else if (fd == iobuf.out_fd) return "message fd"; else if (fd == batch_fd) return "batch file"; else { snprintf(buf, sizeof buf, "fd %d", fd); return buf; }} /* Do a safe write, handling any needed looping and error handling. * Returns only if everything was successfully written. This routine * is not used on the socket except very early in the transfer. */static void safe_write(int fd, const char *buf, size_t len){ ssize_t n; assert(fd != iobuf.out_fd); if (got_sigusr2) /* receiver told to wrap up before this (batch) write */ receive_sigusr2(); n = write(fd, buf, len); if ((size_t)n == len) return; if (n < 0) { if (errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN) { write_failed: rsyserr(FERROR, errno, "safe_write failed to write %" SIZE_T_FMT_MOD "d bytes to %s", (SIZE_T_FMT_CAST)len, what_fd_is(fd)); exit_cleanup(RERR_STREAMIO); } } else { buf += n; len -= n; } while (len) { struct pollfd pfd; int cnt; if (got_sigusr2) /* receiver told to wrap up (e.g. a --write-batch fd) */ receive_sigusr2(); /* poll() avoids the FD_SETSIZE limit that select() imposes. */ pfd.fd = fd; pfd.events = POLLOUT; pfd.revents = 0; cnt = poll(&pfd, 1, poll_timeout_ms()); if (cnt <= 0) { if (cnt < 0 && errno != EINTR && errno != EAGAIN) { rsyserr(FERROR, errno, "safe_write poll failed on %s", what_fd_is(fd)); exit_cleanup(RERR_FILEIO); } if (io_timeout) maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH); continue; } if (pfd.revents & POLLNVAL) { rsyserr(FERROR, EBADF, "safe_write poll failed on %s", what_fd_is(fd)); exit_cleanup(RERR_FILEIO); } if (pfd.revents & POLL_WR_BITS) { n = write(fd, buf, len); if (n < 0) { if (errno == EINTR) continue; goto write_failed; } buf += n; len -= n; } }} /* This is only called when files-from data is known to be available. We read * a chunk of data and put it into the output buffer. */static void forward_filesfrom_data(void){ ssize_t len; len = read(ff_forward_fd, ff_xb.buf + ff_xb.len, ff_xb.size - ff_xb.len); if (len <= 0) { if (len == 0 || errno != EINTR) { /* Send end-of-file marker */ ff_forward_fd = -1; write_buf(iobuf.out_fd, "\0\0", ff_lastchar ? 2 : 1); free_xbuf(&ff_xb); if (ff_reenable_multiplex >= 0) io_start_multiplex_out(ff_reenable_multiplex); free_implied_include_partial_string(); } return; } if (DEBUG_GTE(IO, 2)) { rprintf(FINFO, "[%s] files-from read=%" SIZE_T_FMT_MOD "d\n", who_am_i(), (SIZE_T_FMT_CAST)len); } #ifdef ICONV_OPTION len += ff_xb.len;#endif if (!eol_nulls) { char *s = ff_xb.buf + len; /* Transform CR and/or LF into '\0' */ while (s-- > ff_xb.buf) { if (*s == '\n' || *s == '\r') *s = '\0'; } } if (ff_lastchar) ff_xb.pos = 0; else { char *s = ff_xb.buf; /* Last buf ended with a '\0', so don't let this buf start with one. */ while (len && *s == '\0') s++, len--; ff_xb.pos = s - ff_xb.buf; } Lines 1–500 of 2757. Load more
/* * Socket and pipe I/O utilities used in rsync. * * Copyright (C) 1996-2001 Andrew Tridgell * Copyright (C) 1996 Paul Mackerras * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org> * Copyright (C) 2003-2022 Wayne Davison * * 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 * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, visit the http://fsf.org website. */ /* Rsync provides its own multiplexing system, which is used to send * stderr and stdout over a single socket. * * 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(). */ #include "rsync.h" #include "ifuncs.h" #include "inums.h" #include <poll.h> /* Readiness bits we act on. poll() can report POLLERR/POLLHUP/POLLNVAL even * when they were not requested, and POLLPRI stands in for select()'s old * exception set. */ #define POLL_RD_BITS (POLLIN | POLLPRI | POLLERR | POLLHUP) #define POLL_WR_BITS (POLLOUT | POLLERR | POLLHUP) /** If no timeout is specified then use a 60 second I/O timeout */ #define SELECT_TIMEOUT 60 extern int bwlimit; extern size_t bwlimit_writemax; extern int io_timeout; extern int am_server; extern int am_sender; extern int am_receiver; extern int am_generator; extern int local_server; extern int msgs2stderr; extern int inc_recurse; extern int io_error; extern int batch_fd; extern int eol_nulls; extern int flist_eof; extern int file_total; extern int file_old_total; extern int list_only; extern int read_batch; extern int compat_flags; extern int protect_args; extern int checksum_seed; extern int xfer_sum_len; extern int daemon_connection; extern int protocol_version; extern int remove_source_files; extern int write_batch; extern int preserve_hard_links; extern BOOL extra_flist_sending_enabled; extern BOOL flush_ok_after_signal; extern struct stats stats; extern time_t stop_at_utime; extern struct file_list *cur_flist; #ifdef ICONV_OPTION extern int filesfrom_convert; extern iconv_t ic_send, ic_recv; #endif int csum_length = SHORT_SUM_LENGTH; /* initial value */ int allowed_lull = 0; int msgdone_cnt = 0; int forward_flist_data = 0; BOOL flist_receiving_enabled = False; /* Ignore an EOF error if non-zero. See whine_about_eof(). */ int kluge_around_eof = 0; int got_kill_signal = -1; /* is set to 0 only after multiplexed I/O starts */ volatile sig_atomic_t got_sigusr2 = 0; /* set by the async-signal-safe SIGUSR2 handler */ int sock_f_in = -1; int sock_f_out = -1; int64 total_data_read = 0; int64 total_data_written = 0; char num_dev_ino_buf[4 + 8 + 8]; static struct { xbuf in, out, msg; int in_fd; int out_fd; /* Both "out" and "msg" go to this fd. */ int in_multiplexed; unsigned out_empty_len; size_t raw_data_header_pos; /* in the out xbuf */ size_t raw_flushing_ends_before; /* in the out xbuf */ size_t raw_input_ends_before; /* in the in xbuf */ } iobuf = { .in_fd = -1, .out_fd = -1 }; static time_t last_io_in; static time_t last_io_out; /* Absolute wall-clock bound for peer-controlled daemon handshake reads. * This is deliberately separate from io_timeout: the latter is an idle * transfer timeout and may be supplied by the module or client. */ static time_t daemon_handshake_deadline; /* Wall-clock bound the client puts on establishing a daemon connection made * through a remote shell (daemon_connection == 1): spawning the helper, its * connect()/TLS handshake, and the exchange of the daemon greeting all happen * before any buffered I/O begins, so --contimeout can time the whole phase the * same way the socket path times its connect(). */ static time_t client_connect_deadline; static int write_batch_monitor_in = -1; static int write_batch_monitor_out = -1; static int ff_forward_fd = -1; static int ff_reenable_multiplex = -1; static char ff_lastchar = '\0'; static xbuf ff_xb = EMPTY_XBUF; #ifdef ICONV_OPTION static xbuf iconv_buf = EMPTY_XBUF; #endif static int select_timeout = SELECT_TIMEOUT; /* Turn select_timeout (in seconds) into a poll() millisecond count, keeping it * positive and bounded. A negative count means "wait forever" to poll(), which * would bypass our keepalives and timeout enforcement entirely. */ static int poll_timeout_ms(void) { int secs = select_timeout; if (secs <= 0 || secs > SELECT_TIMEOUT) secs = SELECT_TIMEOUT; return secs * 1000; } static int handshake_poll_timeout_ms(void) { time_t now, left; int timeout = poll_timeout_ms(); if (!daemon_handshake_deadline && !client_connect_deadline) return timeout; now = time(NULL); if (daemon_handshake_deadline) { left = daemon_handshake_deadline - now; if (left <= 0) { rprintf(FERROR, "[%s] daemon handshake timeout -- exiting\n", who_am_i()); exit_cleanup(RERR_TIMEOUT); } if (left <= INT_MAX / 1000 && left * 1000 < timeout) timeout = (int)left * 1000; } if (client_connect_deadline) { left = client_connect_deadline - now; if (left <= 0) { rprintf(FERROR, "[%s] connection timed out -- exiting\n", who_am_i()); exit_cleanup(RERR_CONTIMEOUT); } if (left <= INT_MAX / 1000 && left * 1000 < timeout) timeout = (int)left * 1000; } return timeout; } static int active_filecnt = 0; static OFF_T active_bytecnt = 0; static int first_message = 1; static const char int_byte_extra[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* (00 - 3F)/4 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* (40 - 7F)/4 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* (80 - BF)/4 */ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6, /* (C0 - FF)/4 */ }; /* Our I/O buffers are sized with no bits on in the lowest byte of the "size" * (indeed, our rounding of sizes in 1024-byte units assures more than this). * This allows the code that is storing bytes near the physical end of a * circular buffer to temporarily reduce the buffer's size (in order to make * some storing idioms easier), while also making it simple to restore the * buffer's actual size when the buffer's "pos" wraps around to the start (we * just round the buffer's size up again). */ #define IOBUF_WAS_REDUCED(siz) ((siz) & 0xFF) #define IOBUF_RESTORE_SIZE(siz) (((siz) | 0xFF) + 1) #define IN_MULTIPLEXED (iobuf.in_multiplexed != 0) #define IN_MULTIPLEXED_AND_READY (iobuf.in_multiplexed > 0) #define OUT_MULTIPLEXED (iobuf.out_empty_len != 0) #define PIO_NEED_INPUT (1<<0) /* The *_NEED_* flags are mutually exclusive. */ #define PIO_NEED_OUTROOM (1<<1) #define PIO_NEED_MSGROOM (1<<2) #define PIO_CONSUME_INPUT (1<<4) /* Must becombined with PIO_NEED_INPUT. */ #define PIO_INPUT_AND_CONSUME (PIO_NEED_INPUT | PIO_CONSUME_INPUT) #define PIO_NEED_FLAGS (PIO_NEED_INPUT | PIO_NEED_OUTROOM | PIO_NEED_MSGROOM) #define REMOTE_OPTION_ERROR "rsync: on remote machine: -" #define REMOTE_OPTION_ERROR2 ": unknown option" #define FILESFROM_BUFLEN 2048 enum festatus { FES_SUCCESS, FES_REDO, FES_NO_SEND }; static flist_ndx_list redo_list, hlink_list; static void read_a_msg(void); static void drain_multiplex_messages(void); static void sleep_for_bwlimit(int bytes_written); static void check_timeout(BOOL allow_keepalive, int keepalive_flags) { time_t t, chk; /* On the receiving side, the generator is now the one that decides * when a timeout has occurred. When it is sifting through a lot of * files looking for work, it will be sending keep-alive messages to * the sender, and even though the receiver won't be sending/receiving * anything (not even keep-alive messages), the successful writes to * the sender will keep things going. If the receiver is actively * receiving data, it will ensure that the generator knows that it is * not idle by sending the generator keep-alive messages (since the * generator might be blocked trying to send checksums, it needs to * know that the receiver is active). Thus, as long as one or the * other is successfully doing work, the generator will not timeout. */ if (!io_timeout) return; t = time(NULL); if (allow_keepalive) { /* This may put data into iobuf.msg w/o flushing. */ maybe_send_keepalive(t, keepalive_flags); } if (!last_io_in) last_io_in = t; if (am_receiver) return; chk = MAX(last_io_out, last_io_in); if (t - chk >= io_timeout) { if (am_server) msgs2stderr = 1; rprintf(FERROR, "[%s] io timeout after %d seconds -- exiting\n", who_am_i(), (int)(t-chk)); exit_cleanup(RERR_TIMEOUT); } } /* It's almost always an error to get an EOF when we're trying to read from the * network, because the protocol is (for the most part) self-terminating. * * There is one case for the receiver when it is at the end of the transfer * (hanging around reading any keep-alive packets that might come its way): if * the sender dies before the generator's kill-signal comes through, we can end * up here needing to loop until the kill-signal arrives. In this situation, * kluge_around_eof will be < 0. * * There is another case for older protocol versions (< 24) where the module * listing was not terminated, so we must ignore an EOF error in that case and * exit. In this situation, kluge_around_eof will be > 0. */ static NORETURN void whine_about_eof(BOOL allow_kluge) { if (kluge_around_eof && allow_kluge) { int i; if (kluge_around_eof > 0) exit_cleanup(0); /* The receiver is waiting here for the generator's SIGUSR2; act on it * (exit cleanly) the moment it arrives rather than sleeping the full * 10s and then erroring. The async-signal-safe handler only sets the * flag, so this loop must poll it. */ for (i = 10*1000/20; i--; ) { if (got_sigusr2) receive_sigusr2(); msleep(20); } } rprintf(FERROR, RSYNC_NAME ": connection unexpectedly closed " "(%s bytes received so far) [%s]\n", big_num(stats.total_read), who_am_i()); exit_cleanup(RERR_STREAMIO); } /* Do a safe read, handling any needed looping and error handling. * Returns the count of the bytes read, which will only be different * from "len" if we encountered an EOF. This routine is not used on * the socket except very early in the transfer. */ static size_t safe_read(int fd, char *buf, size_t len) { size_t got = 0; assert(fd != iobuf.in_fd); while (1) { struct pollfd pfd; int cnt; if (got_sigusr2) /* receiver told to wrap up (e.g. a --read-batch fd) */ receive_sigusr2(); /* We use poll() rather than select() so that a high-numbered fd * (>= FD_SETSIZE) cannot overflow an fd_set bitmap. */ pfd.fd = fd; pfd.events = POLLIN | POLLPRI; pfd.revents = 0; cnt = poll(&pfd, 1, handshake_poll_timeout_ms()); if (cnt <= 0) { if (cnt < 0 && errno != EINTR && errno != EAGAIN) { rsyserr(FERROR, errno, "safe_read poll failed"); exit_cleanup(RERR_FILEIO); } check_timeout(1, MSK_ALLOW_FLUSH); continue; } /* An invalid fd is reported here rather than via poll()'s return. */ if (pfd.revents & POLLNVAL) { rsyserr(FERROR, EBADF, "safe_read poll failed"); exit_cleanup(RERR_FILEIO); } if (pfd.revents & POLL_RD_BITS) { ssize_t n = read(fd, buf + got, len - got); if (DEBUG_GTE(IO, 2)) { rprintf(FINFO, "[%s] safe_read(%d)=%" SIZE_T_FMT_MOD "d\n", who_am_i(), fd, (SIZE_T_FMT_CAST)n); } if (n == 0) break; if (n < 0) { if (errno == EINTR) continue; rsyserr(FERROR, errno, "safe_read failed to read %" SIZE_T_FMT_MOD "d bytes", (SIZE_T_FMT_CAST)len); exit_cleanup(RERR_STREAMIO); } if ((got += (size_t)n) == len) break; } } return got; } static const char *what_fd_is(int fd) { static char buf[20]; if (fd == sock_f_out) return "socket"; else if (fd == iobuf.out_fd) return "message fd"; else if (fd == batch_fd) return "batch file"; else { snprintf(buf, sizeof buf, "fd %d", fd); return buf; } } /* Do a safe write, handling any needed looping and error handling. * Returns only if everything was successfully written. This routine * is not used on the socket except very early in the transfer. */ static void safe_write(int fd, const char *buf, size_t len) { ssize_t n; assert(fd != iobuf.out_fd); if (got_sigusr2) /* receiver told to wrap up before this (batch) write */ receive_sigusr2(); n = write(fd, buf, len); if ((size_t)n == len) return; if (n < 0) { if (errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN) { write_failed: rsyserr(FERROR, errno, "safe_write failed to write %" SIZE_T_FMT_MOD "d bytes to %s", (SIZE_T_FMT_CAST)len, what_fd_is(fd)); exit_cleanup(RERR_STREAMIO); } } else { buf += n; len -= n; } while (len) { struct pollfd pfd; int cnt; if (got_sigusr2) /* receiver told to wrap up (e.g. a --write-batch fd) */ receive_sigusr2(); /* poll() avoids the FD_SETSIZE limit that select() imposes. */ pfd.fd = fd; pfd.events = POLLOUT; pfd.revents = 0; cnt = poll(&pfd, 1, poll_timeout_ms()); if (cnt <= 0) { if (cnt < 0 && errno != EINTR && errno != EAGAIN) { rsyserr(FERROR, errno, "safe_write poll failed on %s", what_fd_is(fd)); exit_cleanup(RERR_FILEIO); } if (io_timeout) maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH); continue; } if (pfd.revents & POLLNVAL) { rsyserr(FERROR, EBADF, "safe_write poll failed on %s", what_fd_is(fd)); exit_cleanup(RERR_FILEIO); } if (pfd.revents & POLL_WR_BITS) { n = write(fd, buf, len); if (n < 0) { if (errno == EINTR) continue; goto write_failed; } buf += n; len -= n; } } } /* This is only called when files-from data is known to be available. We read * a chunk of data and put it into the output buffer. */ static void forward_filesfrom_data(void) { ssize_t len; len = read(ff_forward_fd, ff_xb.buf + ff_xb.len, ff_xb.size - ff_xb.len); if (len <= 0) { if (len == 0 || errno != EINTR) { /* Send end-of-file marker */ ff_forward_fd = -1; write_buf(iobuf.out_fd, "\0\0", ff_lastchar ? 2 : 1); free_xbuf(&ff_xb); if (ff_reenable_multiplex >= 0) io_start_multiplex_out(ff_reenable_multiplex); free_implied_include_partial_string(); } return; } if (DEBUG_GTE(IO, 2)) { rprintf(FINFO, "[%s] files-from read=%" SIZE_T_FMT_MOD "d\n", who_am_i(), (SIZE_T_FMT_CAST)len); } #ifdef ICONV_OPTION len += ff_xb.len; #endif if (!eol_nulls) { char *s = ff_xb.buf + len; /* Transform CR and/or LF into '\0' */ while (s-- > ff_xb.buf) { if (*s == '\n' || *s == '\r') *s = '\0'; } } if (ff_lastchar) ff_xb.pos = 0; else { char *s = ff_xb.buf; /* Last buf ended with a '\0', so don't let this buf start with one. */ while (len && *s == '\0') s++, len--; ff_xb.pos = s - ff_xb.buf; }