From: Wayne Davison Date: Mon, 21 Dec 2009 22:37:47 +0000 (-0800) Subject: Pass the 'f' compatibility flag to the server (via -e) X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/commitdiff_plain/de6ab501b6471132247a48dbb3c4c0e8465430ec Pass the 'f' compatibility flag to the server (via -e) so that 3.0.7 knows we support the safer flist-xfer method. --- diff --git a/NEWS b/NEWS index 090f2f14..d707a401 100644 --- a/NEWS +++ b/NEWS @@ -30,10 +30,6 @@ Changes since 3.0.4: BUG FIXES: - - Fixed a bug in incremental recursion transfers where an I/O error might - not get noticed in time for the receiving side to disable deletions - (requires protocol 31). - - Changed the way --progress overwrites its prior output in order to make it nearly impossible for the progress to get overwritten by an error. diff --git a/compat.c b/compat.c index f5cfbd4b..cb7a0e13 100644 --- a/compat.c +++ b/compat.c @@ -24,6 +24,7 @@ int remote_protocol = 0; int file_extra_cnt = 0; /* count of file-list extras that everyone gets */ int inc_recurse = 0; +int use_safe_inc_flist = 0; extern int am_server; extern int am_sender; @@ -72,6 +73,7 @@ int filesfrom_convert = 0; #define CF_INC_RECURSE (1<<0) #define CF_SYMLINK_TIMES (1<<1) #define CF_SYMLINK_ICONV (1<<2) +#define CF_SAFE_FLIST (1<<3) static const char *client_info; @@ -254,10 +256,11 @@ void setup_protocol(int f_out,int f_in) #ifdef ICONV_OPTION compat_flags |= CF_SYMLINK_ICONV; #endif + if (local_server || strchr(client_info, 'f') != NULL) + compat_flags |= CF_SAFE_FLIST; write_byte(f_out, compat_flags); - } else { + } else compat_flags = read_byte(f_in); - } /* The inc_recurse var MUST be set to 0 or 1. */ inc_recurse = compat_flags & CF_INC_RECURSE ? 1 : 0; if (am_sender) { @@ -281,6 +284,7 @@ void setup_protocol(int f_out,int f_in) read_batch ? "batch file" : "connection"); exit_cleanup(RERR_SYNTAX); } + use_safe_inc_flist = (compat_flags & CF_SAFE_FLIST) || protocol_version >= 31; need_messages_from_generator = 1; #ifdef CAN_SET_SYMLINK_TIMES } else if (!am_sender) { diff --git a/flist.c b/flist.c index ac0a903f..6d450bfa 100644 --- a/flist.c +++ b/flist.c @@ -50,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; @@ -65,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; @@ -1872,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]; @@ -1987,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) { @@ -2313,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 @@ -2357,7 +2376,7 @@ 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) @@ -2443,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); }