From: Wayne Davison Date: Sat, 2 Aug 2008 16:14:36 +0000 (-0700) Subject: Added logic to the receiving side to ensure that the --delete-during X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/commitdiff_plain/f303b749f2843433c9acd8218a4b9096d0d1bb8d Added logic to the receiving side to ensure that the --delete-during code will not delete in a directory prior to receiving an I/O error for that directory (or not receiving it, as the case may be). --- diff --git a/generator.c b/generator.c index 5a57a0f3..8290e603 100644 --- a/generator.c +++ b/generator.c @@ -86,6 +86,7 @@ extern int unsort_ndx; extern int max_delete; extern int force_delete; extern int one_file_system; +extern int check_for_io_err; extern struct stats stats; extern dev_t filesystem_dev; extern mode_t orig_umask; @@ -2236,6 +2237,10 @@ void generate_files(int f_out, const char *local_name) dirdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); } else dirdev = MAKEDEV(0, 0); + /* We must be sure we've had a chance to receive an I/O + * error for this directory before we delete in it. */ + while (check_for_io_err && !cur_flist->next) + wait_for_receiver(); delete_in_dir(fbuf, fp, &dirdev); } else change_local_filter_dir(fbuf, strlen(fbuf), F_DEPTH(fp)); diff --git a/io.c b/io.c index 60685757..fe9bcec1 100644 --- a/io.c +++ b/io.c @@ -63,6 +63,7 @@ int allowed_lull = 0; int ignore_timeout = 0; int batch_fd = -1; int msgdone_cnt = 0; +int check_for_io_err = 0; /* Ignore an EOF error if non-zero. See whine_about_eof(). */ int kluge_around_eof = 0; @@ -379,6 +380,8 @@ static void read_msg_fd(void) len = tag & 0xFFFFFF; tag = (tag >> 24) - MPLEX_BASE; + check_for_io_err = 0; + switch (tag) { case MSG_DONE: if (len < 0 || len > 1 || !am_generator) { @@ -413,6 +416,9 @@ static void read_msg_fd(void) } flist = recv_file_list(fd); flist->parent_ndx = IVAL(buf,0); + /* If the sender is going to send us an MSG_IO_ERROR value, it + * will always be the very next message following MSG_FLIST. */ + check_for_io_err = 1; #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links) match_hard_links(flist); @@ -1060,6 +1066,8 @@ static int readfd_unbuffered(int fd, char *buf, size_t len) msg_bytes = tag & 0xFFFFFF; tag = (tag >> 24) - MPLEX_BASE; + check_for_io_err = 0; + switch (tag) { case MSG_DATA: if (msg_bytes > iobuf_in_siz) { diff --git a/main.c b/main.c index c32457d4..dc3c5334 100644 --- a/main.c +++ b/main.c @@ -64,8 +64,11 @@ extern int whole_file; extern int read_batch; extern int write_batch; extern int batch_fd; +extern int flist_eof; extern int filesfrom_fd; +extern int delete_during; extern int connect_timeout; +extern int check_for_io_err; extern pid_t cleanup_child_pid; extern unsigned int module_dirlen; extern struct stats stats; @@ -765,6 +768,8 @@ static int do_recv(int f_in, int f_out, char *local_name) exit_cleanup(RERR_IPC); } + check_for_io_err = inc_recurse && delete_during && !flist_eof; + if (pid == 0) { close(error_pipe[0]); if (f_in != f_out) diff --git a/rsync.c b/rsync.c index e1c061c9..21f5288f 100644 --- a/rsync.c +++ b/rsync.c @@ -48,6 +48,8 @@ extern int flist_eof; extern int msgs2stderr; extern int keep_dirlinks; extern int make_backups; +extern int delete_during; +extern int check_for_io_err; extern struct file_list *cur_flist, *first_flist, *dir_flist; extern struct chmod_mode_struct *daemon_chmod_modes; #ifdef ICONV_OPTION @@ -252,8 +254,15 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr, while (1) { ndx = read_ndx(f_in); - if (ndx >= 0) + if (ndx >= 0) { + if (check_for_io_err) { + /* Let generator know there was no I/O error. */ + send_msg_int(MSG_IO_ERROR, 0); + check_for_io_err = 0; + } break; + } + check_for_io_err = 0; if (ndx == NDX_DONE) return ndx; if (!inc_recurse || am_sender) @@ -287,6 +296,10 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr, stop_flist_forward(); if (!msgs2stderr) negate_output_levels(); /* restore info/debug output */ + /* If the sender is going to send us an MSG_IO_ERROR value, it + * will always be the very next message following a file list. */ + if (delete_during) + check_for_io_err = 1; } iflags = protocol_version >= 29 ? read_shortint(f_in)