Added logic to the receiving side to ensure that the --delete-during
authorWayne Davison <wayned@samba.org>
Sat, 2 Aug 2008 16:14:36 +0000 (09:14 -0700)
committerWayne Davison <wayned@samba.org>
Sat, 2 Aug 2008 16:14:36 +0000 (09:14 -0700)
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).

generator.c
io.c
main.c
rsync.c

index 5a57a0f..8290e60 100644 (file)
@@ -86,6 +86,7 @@ extern int unsort_ndx;
 extern int max_delete;
 extern int force_delete;
 extern int one_file_system;
 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;
 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);
                                                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));
                                        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 6068575..fe9bcec 100644 (file)
--- 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 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;
 
 /* 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;
 
        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) {
        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);
                }
                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);
 #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;
 
                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) {
                switch (tag) {
                case MSG_DATA:
                        if (msg_bytes > iobuf_in_siz) {
diff --git a/main.c b/main.c
index c32457d..dc3c533 100644 (file)
--- 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 read_batch;
 extern int write_batch;
 extern int batch_fd;
+extern int flist_eof;
 extern int filesfrom_fd;
 extern int filesfrom_fd;
+extern int delete_during;
 extern int connect_timeout;
 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;
 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);
        }
 
                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)
        if (pid == 0) {
                close(error_pipe[0]);
                if (f_in != f_out)
diff --git a/rsync.c b/rsync.c
index e1c061c..21f5288 100644 (file)
--- 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 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
 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);
 
        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;
                        break;
+               }
+               check_for_io_err = 0;
                if (ndx == NDX_DONE)
                        return ndx;
                if (!inc_recurse || am_sender)
                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 */
                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)
        }
 
        iflags = protocol_version >= 29 ? read_shortint(f_in)