X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/20caffd2b361bcad51692998411e4cc566c04b40..e89a0fc094c1edc4382e1b218c7f3fd50676101d:/flist.c diff --git a/flist.c b/flist.c index 5a1ab9dc..6d450bfa 100644 --- a/flist.c +++ b/flist.c @@ -42,7 +42,6 @@ extern int xfer_dirs; extern int filesfrom_fd; extern int one_file_system; extern int copy_dirlinks; -extern int keep_dirlinks; extern int preserve_uid; extern int preserve_gid; extern int preserve_acls; @@ -51,6 +50,7 @@ extern int preserve_links; extern int preserve_hard_links; extern int preserve_devices; extern int preserve_specials; +extern int delete_during; extern int missing_args; extern int uid_ndx; extern int gid_ndx; @@ -66,6 +66,7 @@ extern int copy_unsafe_links; extern int protocol_version; extern int sanitize_paths; extern int munge_symlinks; +extern int use_safe_inc_flist; extern int need_unsorted_flist; extern int sender_symlink_iconv; extern int output_needs_newline; @@ -731,7 +732,7 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x INIT_CONST_XBUF(outbuf, thisname); INIT_XBUF(inbuf, lastname, basename_len, (size_t)-1); - if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) { + if (iconvbufs(ic_recv, &inbuf, &outbuf, ICB_INIT) < 0) { io_error |= IOERR_GENERAL; rprintf(FERROR_UTF8, "[%s] cannot convert filename: %s (%s)\n", @@ -1049,7 +1050,7 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x read_sbuf(f, inbuf.buf, inbuf.len); INIT_XBUF(outbuf, bp, 0, alloc_len); - if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) { + if (iconvbufs(ic_recv, &inbuf, &outbuf, ICB_INIT) < 0) { io_error |= IOERR_GENERAL; rprintf(FERROR_XFER, "[%s] cannot convert symlink data for: %s (%s)\n", @@ -1464,14 +1465,14 @@ static struct file_struct *send_file_name(int f, struct file_list *flist, if (file->dirname) { INIT_XBUF_STRLEN(inbuf, (char*)file->dirname); outbuf.size -= 2; /* Reserve room for '/' & 1 more char. */ - if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) + if (iconvbufs(ic_send, &inbuf, &outbuf, ICB_INIT) < 0) goto convert_error; outbuf.size += 2; fbuf[outbuf.len++] = '/'; } INIT_XBUF_STRLEN(inbuf, (char*)file->basename); - if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) { + if (iconvbufs(ic_send, &inbuf, &outbuf, ICB_INIT) < 0) { convert_error: io_error |= IOERR_GENERAL; rprintf(FERROR_XFER, @@ -1485,7 +1486,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist, if (symlink_len && sender_symlink_iconv) { INIT_XBUF(inbuf, (char*)symlink_name, symlink_len, (size_t)-1); INIT_CONST_XBUF(outbuf, symlink_buf); - if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) { + if (iconvbufs(ic_send, &inbuf, &outbuf, ICB_INIT) < 0) { io_error |= IOERR_GENERAL; f_name(file, fbuf); rprintf(FERROR_XFER, @@ -1873,6 +1874,15 @@ done: filter_list = save_filter_list; } +static NORETURN void fatal_unsafe_io_error(void) +{ + /* This (sadly) can only happen when pushing data because + * the sender does not know about what kind of delete + * is in effect on the receiving side when pulling. */ + rprintf(FERROR_XFER, "FATAL I/O ERROR: dying to avoid a --delete-during issue with a pre-3.0.7 receiver.\n"); + exit_cleanup(RERR_UNSUPPORTED); +} + static void send1extra(int f, struct file_struct *file, struct file_list *flist) { char fbuf[MAXPATHLEN]; @@ -1988,11 +1998,15 @@ void send_extra_file_list(int f, int at_least) dp = F_DIR_NODE_P(file); } - if (protocol_version < 31 || io_error == save_io_error || ignore_errors) + if (io_error == save_io_error || ignore_errors) write_byte(f, 0); - else { + else if (use_safe_inc_flist) { write_shortint(f, XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST); write_varint(f, io_error); + } else { + if (delete_during) + fatal_unsafe_io_error(); + write_byte(f, 0); } if (need_unsorted_flist) { @@ -2051,7 +2065,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) struct timeval start_tv, end_tv; int64 start_write; int use_ff_fd = 0; - int disable_buffering; + int disable_buffering, reenable_multiplex = -1; int flags = recurse ? FLAG_CONTENT_DIR : 0; int reading_remotely = filesfrom_host != NULL; int rl_flags = (reading_remotely ? 0 : RL_DUMP_COMMENTS) @@ -2092,6 +2106,12 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) full_fname(argv[0])); exit_cleanup(RERR_FILESELECT); } + if (protocol_version < 31) { + /* Older protocols send the files-from data w/o packaging + * it in multiplexed I/O packets, so temporarily switch + * to buffered I/O to match this behavior. */ + reenable_multiplex = io_end_multiplex_in(MPLX_TO_BUFFERED); + } use_ff_fd = 1; } @@ -2297,6 +2317,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS); } + if (reenable_multiplex >= 0) + io_start_multiplex_in(reenable_multiplex); + gettimeofday(&end_tv, NULL); stats.flist_buildtime = (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000 + (end_tv.tv_usec - start_tv.tv_usec) / 1000; @@ -2305,11 +2328,15 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) start_tv = end_tv; /* Indicate end of file list */ - if (protocol_version < 31 || io_error == 0 || ignore_errors) + if (io_error == 0 || ignore_errors) write_byte(f, 0); - else { + else if (use_safe_inc_flist) { write_shortint(f, XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST); write_varint(f, io_error); + } else { + if (delete_during && inc_recurse) + fatal_unsafe_io_error(); + write_byte(f, 0); } #ifdef SUPPORT_HARD_LINKS @@ -2341,6 +2368,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) flist->sorted = flist->files; flist_sort_and_clean(flist, 0); file_total += flist->used; + file_old_total += flist->used; if (numeric_ids <= 0 && !inc_recurse) send_id_list(f); @@ -2348,11 +2376,11 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) /* send the io_error flag */ if (protocol_version < 30) write_int(f, ignore_errors ? 0 : io_error); - else if (io_error && protocol_version == 30 && !ignore_errors) + else if (!use_safe_inc_flist && io_error && !ignore_errors) send_msg_int(MSG_IO_ERROR, io_error); if (disable_buffering) - io_end_buffering_out(True); + io_end_buffering_out(IOBUF_FREE_BUFS); stats.flist_size = stats.total_written - start_write; stats.num_files = flist->used; @@ -2434,7 +2462,7 @@ struct file_list *recv_file_list(int f) if (flags == (XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST)) { int err; - if (protocol_version < 31) { + if (!use_safe_inc_flist) { rprintf(FERROR, "Invalid flist flag: %x\n", flags); exit_cleanup(RERR_PROTOCOL); }