Improved the fix that ensures that the generator gets notified about an
authorWayne Davison <wayned@samba.org>
Sun, 31 Aug 2008 16:03:50 +0000 (09:03 -0700)
committerWayne Davison <wayned@samba.org>
Sun, 31 Aug 2008 16:43:39 +0000 (09:43 -0700)
I/O error for the incremental directory that generated the error.  The
PROTOCOL_VERSION was bumped to 31 to implement this.

NEWS
OLDNEWS
flist.c
generator.c
io.c
main.c
rsync.c
rsync.h

diff --git a/NEWS b/NEWS
index 02be935..6703aa6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,5 @@
 NEWS for rsync 3.1.0 (UNRELEASED)
-Protocol: 30 (unchanged)
+Protocol: 31 (changed)
 Changes since 3.0.4:
 
   BUG FIXES:
diff --git a/OLDNEWS b/OLDNEWS
index bb0f17d..33348a1 100644 (file)
--- a/OLDNEWS
+++ b/OLDNEWS
@@ -2841,7 +2841,7 @@ Changes since 2.4.6:
 \f
 Partial Protocol History
        RELEASE DATE    VER.    DATE OF COMMIT* PROTOCOL
-       ?? ??? 2008     3.1.0                   30
+       ?? ??? 2008     3.1.0   31 Aug 2008     31
        29 Jun 2008     3.0.3                   30
        08 Apr 2008     3.0.2                   30
        03 Apr 2008     3.0.1                   30
diff --git a/flist.c b/flist.c
index d11437f..92e89a2 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -1916,7 +1916,12 @@ void send_extra_file_list(int f, int at_least)
                        dp = F_DIR_NODE_P(file);
                }
 
-               write_byte(f, 0);
+               if (protocol_version < 31 || io_error == save_io_error || ignore_errors)
+                       write_byte(f, 0);
+               else {
+                       write_shortint(f, XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST);
+                       write_int(f, io_error);
+               }
 
                if (need_unsorted_flist) {
                        if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
@@ -1957,7 +1962,7 @@ void send_extra_file_list(int f, int at_least)
        }
 
   finish:
-       if (io_error != save_io_error && !ignore_errors)
+       if (io_error != save_io_error && protocol_version == 30 && !ignore_errors)
                send_msg_int(MSG_IO_ERROR, io_error);
 }
 
@@ -2213,7 +2218,13 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                stats.flist_buildtime = 1;
        start_tv = end_tv;
 
-       write_byte(f, 0); /* Indicate end of file list */
+       /* Indicate end of file list */
+       if (protocol_version < 31 || io_error == 0 || ignore_errors)
+               write_byte(f, 0);
+       else {
+               write_shortint(f, XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST);
+               write_int(f, io_error);
+       }
 
 #ifdef SUPPORT_HARD_LINKS
        if (preserve_hard_links && protocol_version >= 30 && !inc_recurse)
@@ -2251,7 +2262,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 && !ignore_errors)
+       else if (io_error && protocol_version == 30 && !ignore_errors)
                send_msg_int(MSG_IO_ERROR, io_error);
 
        if (disable_buffering)
@@ -2322,10 +2333,22 @@ struct file_list *recv_file_list(int f)
        while ((flags = read_byte(f)) != 0) {
                struct file_struct *file;
 
-               flist_expand(flist, 1);
-
                if (protocol_version >= 28 && (flags & XMIT_EXTENDED_FLAGS))
                        flags |= read_byte(f) << 8;
+
+               if (flags == (XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST)) {
+                       int err;
+                       if (protocol_version < 31) {
+                               rprintf(FERROR, "Invalid flist flag: %x\n", flags);
+                               exit_cleanup(RERR_PROTOCOL);
+                       }
+                       err = read_int(f);
+                       if (!ignore_errors)
+                               io_error |= err;
+                       break;
+               }
+
+               flist_expand(flist, 1);
                file = recv_file_entry(flist, flags, f);
 
                if (inc_recurse && S_ISDIR(file->mode)) {
@@ -2389,10 +2412,9 @@ struct file_list *recv_file_list(int f)
 
        if (protocol_version < 30) {
                /* Recv the io_error flag */
-               if (ignore_errors)
-                       read_int(f);
-               else
-                       io_error |= read_int(f);
+               int err = read_int(f);
+               if (!ignore_errors)
+                       io_error |= err;
        } else if (inc_recurse && flist->ndx_start == 1) {
                if (!file_total || strcmp(flist->sorted[flist->low]->basename, ".") != 0)
                        flist->parent_ndx = -1;
index 5c3653f..80e9826 100644 (file)
@@ -86,7 +86,6 @@ 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,10 +2235,6 @@ 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 && !flist_eof)
-                                               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 cc2561f..1752d86 100644 (file)
--- a/io.c
+++ b/io.c
@@ -63,7 +63,6 @@ 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;
@@ -377,8 +376,6 @@ 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,9 +410,6 @@ 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);
@@ -1063,8 +1057,6 @@ 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 dc3c533..c32457d 100644 (file)
--- a/main.c
+++ b/main.c
@@ -64,11 +64,8 @@ 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;
@@ -768,8 +765,6 @@ 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 f26f212..2d8e5e4 100644 (file)
--- a/rsync.c
+++ b/rsync.c
@@ -48,8 +48,6 @@ 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
@@ -254,15 +252,8 @@ 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 (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;
-                       }
+               if (ndx >= 0)
                        break;
-               }
-               check_for_io_err = 0;
                if (ndx == NDX_DONE)
                        return ndx;
                if (!inc_recurse || am_sender) {
@@ -306,10 +297,6 @@ 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)
diff --git a/rsync.h b/rsync.h
index 320d340..c23e523 100644 (file)
--- a/rsync.h
+++ b/rsync.h
@@ -60,6 +60,7 @@
 #define XMIT_RDEV_MINOR_8_pre30 (1<<11)        /* protocols 28 - 29  */
 #define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - now */
 #define XMIT_HLINK_FIRST (1<<12)       /* protocols 30 - now (HLINKED files only) */
+#define XMIT_IO_ERROR_ENDLIST (1<<12)  /* protocols 31 - now (w/XMIT_EXTENDED_FLAGS) */
 
 /* These flags are used in the live flist data. */
 
                             == ((unsigned)(b2) & (unsigned)(mask)))
 
 /* update this if you make incompatible changes */
-#define PROTOCOL_VERSION 30
+#define PROTOCOL_VERSION 31
 
 /* This is used when working on a new protocol version in CVS, and should
  * be a new non-zero value for each CVS change that affects the protocol.
- * It must ALWAYS be 0 when the protocol goes final! */
-#define SUBPROTOCOL_VERSION 0
+ * It must ALWAYS be 0 when the protocol goes final (and NEVER before)! */
+#define SUBPROTOCOL_VERSION 1
 
 /* We refuse to interoperate with versions that are not in this range.
  * Note that we assume we'll work with later versions: the onus is on