X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/ba525f770c3133683c894ac08f13286a97ab4315..2042c632512e47cb7bfa3aa6131b89c2e9829820:/io.c diff --git a/io.c b/io.c index 1899cb9d..afe837f1 100644 --- a/io.c +++ b/io.c @@ -28,6 +28,7 @@ * io_start_multiplex_out() and io_start_multiplex_in(). */ #include "rsync.h" +#include "ifuncs.h" /** If no timeout is specified then use a 60 second select timeout */ #define SELECT_TIMEOUT 60 @@ -52,7 +53,7 @@ extern int protocol_version; extern int remove_source_files; extern int preserve_hard_links; extern struct stats stats; -extern struct file_list *cur_flist, *first_flist; +extern struct file_list *cur_flist; #ifdef ICONV_OPTION extern int filesfrom_convert; extern iconv_t ic_send, ic_recv; @@ -99,7 +100,7 @@ static char ff_lastchar; #ifdef ICONV_OPTION static xbuf iconv_buf = EMPTY_XBUF; #endif -static int defer_forwarding_messages = 0; +static int defer_forwarding_messages = 0, defer_forwarding_keep = 0; static int select_timeout = SELECT_TIMEOUT; static int active_filecnt = 0; static OFF_T active_bytecnt = 0; @@ -180,7 +181,6 @@ static void got_flist_entry_status(enum festatus status, const char *buf) struct file_list *flist = flist_for_ndx(ndx); assert(flist != NULL); - assert(ndx >= flist->ndx_start); if (remove_source_files) { active_filecnt--; @@ -196,8 +196,10 @@ static void got_flist_entry_status(enum festatus status, const char *buf) send_msg(MSG_SUCCESS, buf, 4, 0); if (preserve_hard_links) { struct file_struct *file = flist->files[ndx - flist->ndx_start]; - if (F_IS_HLINKED(file)) + if (F_IS_HLINKED(file)) { flist_ndx_push(&hlink_list, ndx); + flist->in_progress++; + } } break; case FES_REDO: @@ -387,6 +389,12 @@ static void read_msg_fd(void) goto invalid_msg; flist_eof = 1; break; + case MSG_IO_ERROR: + if (len != 4) + goto invalid_msg; + readfd(fd, buf, len); + io_error |= IVAL(buf, 0); + break; case MSG_DELETED: if (len >= (int)sizeof buf || !am_generator) goto invalid_msg; @@ -432,7 +440,7 @@ static void read_msg_fd(void) no_flush--; msg_fd_in = fd; - if (!--defer_forwarding_messages) + if (!--defer_forwarding_messages && !no_flush) msg_flush(); } @@ -472,7 +480,9 @@ static void mplex_write(int fd, enum msgcode code, const char *buf, size_t len, else memcpy(buffer + 4, buf, n); + defer_forwarding_keep = 1; /* defer_forwarding_messages++ on return */ writefd_unbuffered(fd, buffer, n+4); + defer_forwarding_keep = 0; len -= n; buf += n; @@ -484,22 +494,18 @@ static void mplex_write(int fd, enum msgcode code, const char *buf, size_t len, INIT_CONST_XBUF(outbuf, buffer); INIT_XBUF(inbuf, (char*)buf, len, -1); - defer_forwarding_messages++; do { iconvbufs(ic_send, &inbuf, &outbuf, ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE); writefd_unbuffered(fd, outbuf.buf, outbuf.len); } while (inbuf.len); - if (!--defer_forwarding_messages) - msg_flush(); } else #endif - if (len) { - defer_forwarding_messages++; + if (len) writefd_unbuffered(fd, buf, len); - if (!--defer_forwarding_messages) - msg_flush(); - } + + if (!--defer_forwarding_messages && !no_flush) + msg_flush(); } int send_msg(enum msgcode code, const char *buf, int len, int convert) @@ -674,7 +680,11 @@ static int read_timeout(int fd, char *buf, size_t len) } } else if (io_filesfrom_f_in >= 0) { if (FD_ISSET(io_filesfrom_f_in, &r_fds)) { +#ifdef ICONV_OPTION xbuf *ibuf = filesfrom_convert ? &iconv_buf : &ff_buf; +#else + xbuf *ibuf = &ff_buf; +#endif int l = read(io_filesfrom_f_in, ibuf->buf, ibuf->size); if (l <= 0) { if (l == 0 || errno != EINTR) { @@ -685,6 +695,7 @@ static int read_timeout(int fd, char *buf, size_t len) io_filesfrom_f_in = -1; } } else { +#ifdef ICONV_OPTION if (filesfrom_convert) { iconv_buf.pos = 0; iconv_buf.len = l; @@ -692,6 +703,7 @@ static int read_timeout(int fd, char *buf, size_t len) ICB_EXPAND_OUT|ICB_INCLUDE_BAD|ICB_INCLUDE_INCOMPLETE); l = ff_buf.len; } +#endif if (!eol_nulls) { char *s = ff_buf.buf + l; /* Transform CR and/or LF into '\0' */ @@ -771,7 +783,11 @@ int read_line(int fd, char *buf, size_t bufsiz, int flags) #endif start: +#ifdef ICONV_OPTION s = flags & RL_CONVERT ? iconv_buf.buf : buf; +#else + s = buf; +#endif eob = s + bufsiz - 1; while (1) { cnt = read(fd, &ch, 1); @@ -830,8 +846,11 @@ int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls, int dot_pos = 0; int argc = 0; char **argv, *p; - int rl_flags = (rl_nulls ? RL_EOL_NULLS : 0) - | (protect_args && ic_recv != (iconv_t)-1 ? RL_CONVERT : 0); + int rl_flags = (rl_nulls ? RL_EOL_NULLS : 0); + +#ifdef ICONV_OPTION + rl_flags |= (protect_args && ic_recv != (iconv_t)-1 ? RL_CONVERT : 0); +#endif if (!(argv = new_array(char *, maxargs))) out_of_memory("read_args"); @@ -1027,6 +1046,7 @@ static int readfd_unbuffered(int fd, char *buf, size_t len) if (msg_bytes != 4) goto invalid_msg; read_loop(fd, line, msg_bytes); + send_msg_int(MSG_IO_ERROR, IVAL(line, 0)); io_error |= IVAL(line, 0); break; case MSG_DELETED: @@ -1490,7 +1510,8 @@ static void writefd_unbuffered(int fd, const char *buf, size_t len) } no_flush--; - if (!(defer_forwarding_messages -= defer_inc)) + defer_inc -= defer_forwarding_keep; + if (!(defer_forwarding_messages -= defer_inc) && !no_flush) msg_flush(); } @@ -1840,6 +1861,8 @@ void start_write_batch(int fd) * actual communication so far depends on whether a daemon * is involved. */ write_int(batch_fd, protocol_version); + if (protocol_version >= 30) + write_byte(batch_fd, inc_recurse); write_int(batch_fd, checksum_seed); if (am_sender)