Need to make sure that the destination file doesn't exist before we
[rsync/rsync-patches.git] / g2r-basis-filename.diff
index 0ff296a..b27f8e0 100644 (file)
@@ -1,5 +1,3 @@
-Depends-On-Patch: partial-dir.diff
-
 Added a pipe from the generator to the receiver that communicates
 what basis file we used to generate the file data (if it was not
 the default name).  This optimizes away the basis-file search in
@@ -9,41 +7,50 @@ support for multiple --compare-dest options).
 
 You must run "make proto" before compiling.
 
---- orig/generator.c   2004-07-28 09:58:28
-+++ generator.c        2004-07-28 10:14:15
-@@ -259,9 +259,9 @@ static void generate_and_send_sums(int f
+--- orig/generator.c   2004-09-20 19:50:13
++++ generator.c        2004-09-20 19:57:58
+@@ -254,14 +254,15 @@ static void generate_and_send_sums(int f
   * out.  It might be wrong.
   */
  static void recv_generator(char *fname, struct file_struct *file, int i,
 -                         int f_out)
 +                         int f_out, int f_out_name)
  {
--      int fd;
-+      int fd = -1;
-       STRUCT_STAT st;
+-      int fd, f_copy;
++      int fd = -1, f_copy;
+       STRUCT_STAT st, partial_st;
+       struct file_struct *back_file;
        int statret, stat_errno;
-       char *fnamecmp;
-@@ -437,13 +437,16 @@ static void recv_generator(char *fname, 
+       char *fnamecmp, *partialptr, *backupptr;
+       char fnamecmpbuf[MAXPATHLEN];
++      uchar fnamecmp_type;
+       if (list_only)
+               return;
+@@ -423,6 +424,7 @@ static void recv_generator(char *fname, 
+       }
+       fnamecmp = fname;
++      fnamecmp_type = G2R_FNAME;
+       if (statret == -1 && compare_dest != NULL) {
+               /* try the file at compare_dest instead */
+@@ -439,10 +441,14 @@ static void recv_generator(char *fname, 
                                                        safe_fname(fname));
                                        }
                                        fnamecmp = fnamecmpbuf;
--                              }
-+                              } else
-+                                      *fnamecmpbuf = '\0';
++                                      fnamecmp_type = 0;
+                               }
                        } else
  #endif
++                      {
                                fnamecmp = fnamecmpbuf;
++                              fnamecmp_type = 0;
++                      }
                        statret = 0;
--              }
--      }
-+              } else
-+                      *fnamecmpbuf = '\0';
-+      } else
-+              *fnamecmpbuf = '\0';
-       if (statret == 0 && !S_ISREG(st.st_mode)) {
-               if (delete_file(fname) != 0)
-@@ -455,11 +458,9 @@ static void recv_generator(char *fname, 
+               }
+       }
+@@ -465,11 +471,9 @@ static void recv_generator(char *fname, 
        if (statret == -1) {
                if (preserve_hard_links && hard_link_check(file, HL_SKIP))
                        return;
@@ -58,32 +65,33 @@ You must run "make proto" before compiling.
                        rsyserr(FERROR, stat_errno,
                                "recv_generator: failed to stat %s",
                                full_fname(fname));
-@@ -467,13 +468,13 @@ static void recv_generator(char *fname, 
+@@ -477,13 +481,13 @@ static void recv_generator(char *fname, 
                return;
        }
  
 -      if (opt_ignore_existing && fnamecmp == fname) {
-+      if (opt_ignore_existing && !*fnamecmpbuf) {
++      if (opt_ignore_existing && fnamecmp_type == G2R_FNAME) {
                if (verbose > 1)
                        rprintf(FINFO, "%s exists\n", safe_fname(fname));
                return;
        }
  
 -      if (update_only && fnamecmp == fname
-+      if (update_only && !*fnamecmpbuf
++      if (update_only && fnamecmp_type == G2R_FNAME
            && cmp_modtime(st.st_mtime, file->modtime) > 0) {
                if (verbose > 1)
                        rprintf(FINFO, "%s is newer\n", safe_fname(fname));
-@@ -481,21 +482,17 @@ static void recv_generator(char *fname, 
+@@ -491,26 +495,23 @@ static void recv_generator(char *fname, 
        }
  
-       if (skip_file(fname, file, &st)) {
+       if (skip_file(fnamecmp, file, &st)) {
 -              if (fnamecmp == fname)
-+              if (!*fnamecmpbuf)
++              if (fnamecmp_type == G2R_FNAME)
                        set_perms(fname, file, &st, PERMS_REPORT);
                return;
        }
  
+ prepare_to_open:
 -      if (dry_run || read_batch) {
 -              write_int(f_out,i);
 -              return;
@@ -93,16 +101,21 @@ You must run "make proto" before compiling.
 -              write_int(f_out,i);
 -              write_sum_head(f_out, NULL);
 -              return;
-+      if (dry_run || whole_file) {
++      if (dry_run || whole_file > 0) {
 +              statret = -1;
 +              goto notify_others;
        }
 +      if (read_batch)
 +              goto notify_others;
  
-       if (partial_dir) {
-               STRUCT_STAT st2;
-@@ -516,9 +513,8 @@ static void recv_generator(char *fname, 
+       if (partialptr) {
+               st = partial_st;
+               fnamecmp = partialptr;
++              fnamecmp_type = G2R_PARTIAL_DIR;
+       }
+       /* open the file */
+@@ -523,9 +524,8 @@ prepare_to_open:
                /* pretend the file didn't exist */
                if (preserve_hard_links && hard_link_check(file, HL_SKIP))
                        return;
@@ -113,40 +126,52 @@ You must run "make proto" before compiling.
 +              goto notify_others;
        }
  
-       if (verbose > 3) {
-@@ -529,14 +525,41 @@ static void recv_generator(char *fname, 
+       if (inplace && make_backups) {
+@@ -552,6 +552,7 @@ prepare_to_open:
+                       close(fd);
+                       return;
+               }
++              fnamecmp_type = G2R_BACKUP;
+       } else {
+               backupptr = NULL;
+               back_file = NULL;
+@@ -566,22 +567,38 @@ prepare_to_open:
        if (verbose > 2)
                rprintf(FINFO, "generating and sending sums for %d\n", i);
  
 -      write_int(f_out,i);
--      generate_and_send_sums(fd, st.st_size, f_out);
+-      generate_and_send_sums(fd, st.st_size, f_out, f_copy);
+-
+-      if (f_copy >= 0) {
+-              close(f_copy);
+-              set_perms(backupptr, back_file, NULL, 0);
+-              if (verbose > 1)
+-                      rprintf(FINFO, "backed up %s to %s\n", fname, backupptr);
+-              free(back_file);
 +notify_others:
 +      if (f_out_name >= 0) {
-+              uchar lenbuf[3], *lb = lenbuf;
-+              int len = statret == -1 ? 0 : strlen(fnamecmpbuf);
-+              if (len > 0x7F) {
-+#if MAXPATHLEN > 0x7FFF
-+                      *lb++ = len / 0x10000 + 0x80;
-+                      *lb++ = len / 0x100;
-+#else
-+                      *lb++ = len / 0x100 + 0x80;
-+#endif
-+              }
-+              *lb = len;
-+              write_buf(f_out_name, lenbuf, lb - lenbuf + 1);
-+              if (len)
-+                      write_buf(f_out_name, fnamecmpbuf, len);
++              write_byte(f_out_name, fnamecmp_type);
 +              io_flush(NORMAL_FLUSH); /* XXX make this more efficient! */
-+      }
-+
+       }
+-      close(fd);
 +      write_int(f_out, i);
 +
 +      if (dry_run || read_batch)
 +              return;
--      close(fd);
++
 +      if (statret == 0) {
-+              generate_and_send_sums(fd, st.st_size, f_out);
++              generate_and_send_sums(fd, st.st_size, f_out, f_copy);
++
++              if (f_copy >= 0) {
++                      close(f_copy);
++                      set_perms(backupptr, back_file, NULL, 0);
++                      if (verbose > 1) {
++                              rprintf(FINFO, "backed up %s to %s\n",
++                                      fname, backupptr);
++                      }
++                      free(back_file);
++              }
 +
 +              close(fd);
 +      } else
@@ -160,7 +185,7 @@ You must run "make proto" before compiling.
  {
        int i;
        int phase = 0;
-@@ -577,7 +600,7 @@ void generate_files(int f_out, struct fi
+@@ -622,7 +639,7 @@ void generate_files(int f_out, struct fi
                }
  
                recv_generator(local_name ? local_name : f_name_to(file, fbuf),
@@ -169,7 +194,7 @@ You must run "make proto" before compiling.
        }
  
        phase++;
-@@ -594,7 +617,7 @@ void generate_files(int f_out, struct fi
+@@ -639,7 +656,7 @@ void generate_files(int f_out, struct fi
        while ((i = get_redo_num()) != -1) {
                struct file_struct *file = flist->files[i];
                recv_generator(local_name ? local_name : f_name_to(file, fbuf),
@@ -178,7 +203,7 @@ You must run "make proto" before compiling.
        }
  
        phase++;
-@@ -613,7 +636,7 @@ void generate_files(int f_out, struct fi
+@@ -658,7 +675,7 @@ void generate_files(int f_out, struct fi
                if (!file->basename || !S_ISDIR(file->mode))
                        continue;
                recv_generator(local_name ? local_name : f_name(file),
@@ -187,9 +212,9 @@ You must run "make proto" before compiling.
        }
  
        if (verbose > 2)
---- orig/main.c        2004-07-24 16:52:09
+--- orig/main.c        2004-09-18 01:49:33
 +++ main.c     2004-07-22 00:10:43
-@@ -58,6 +58,7 @@ extern int filesfrom_fd;
+@@ -59,6 +59,7 @@ extern int filesfrom_fd;
  extern pid_t cleanup_child_pid;
  extern char *files_from;
  extern char *remote_filesfrom_file;
@@ -197,7 +222,7 @@ You must run "make proto" before compiling.
  extern char *rsync_path;
  extern char *shell_cmd;
  extern char *batch_name;
-@@ -456,7 +457,8 @@ static int do_recv(int f_in,int f_out,st
+@@ -461,7 +462,8 @@ static int do_recv(int f_in,int f_out,st
  {
        int pid;
        int status = 0;
@@ -205,9 +230,9 @@ You must run "make proto" before compiling.
 +      int error_pipe[2], name_pipe[2];
 +      BOOL need_name_pipe = compare_dest && !dry_run;
  
-       if (preserve_hard_links)
-               init_hard_links(flist);
-@@ -467,8 +469,9 @@ static int do_recv(int f_in,int f_out,st
+       /* The receiving side mustn't obey this, or an existing symlink that
+        * points to an identical file won't be replaced by the referent. */
+@@ -476,8 +478,9 @@ static int do_recv(int f_in,int f_out,st
                        delete_files(flist);
        }
  
@@ -219,7 +244,7 @@ You must run "make proto" before compiling.
                exit_cleanup(RERR_SOCKETIO);
        }
  
-@@ -476,6 +479,11 @@ static int do_recv(int f_in,int f_out,st
+@@ -485,6 +488,11 @@ static int do_recv(int f_in,int f_out,st
  
        if ((pid = do_fork()) == 0) {
                close(error_pipe[0]);
@@ -231,7 +256,7 @@ You must run "make proto" before compiling.
                if (f_in != f_out)
                        close(f_out);
  
-@@ -485,7 +493,7 @@ static int do_recv(int f_in,int f_out,st
+@@ -494,7 +502,7 @@ static int do_recv(int f_in,int f_out,st
                /* set place to send errors */
                set_msg_fd_out(error_pipe[1]);
  
@@ -240,7 +265,7 @@ You must run "make proto" before compiling.
                io_flush(FULL_FLUSH);
                report(f_in);
  
-@@ -503,6 +511,11 @@ static int do_recv(int f_in,int f_out,st
+@@ -513,6 +521,11 @@ static int do_recv(int f_in,int f_out,st
                stop_write_batch();
  
        close(error_pipe[1]);
@@ -252,7 +277,7 @@ You must run "make proto" before compiling.
        if (f_in != f_out)
                close(f_in);
  
-@@ -510,7 +523,7 @@ static int do_recv(int f_in,int f_out,st
+@@ -520,7 +533,7 @@ static int do_recv(int f_in,int f_out,st
  
        set_msg_fd_in(error_pipe[0]);
  
@@ -261,40 +286,9 @@ You must run "make proto" before compiling.
  
        get_redo_num(); /* Read final MSG_DONE and any prior messages. */
        report(-1);
---- orig/receiver.c    2004-07-27 23:26:20
-+++ receiver.c 2004-07-23 21:59:07
-@@ -325,6 +325,30 @@ static int receive_data(int f_in, char *
- }
-+static char *read_gen_name(int fd, char *buf, char *realname)
-+{
-+      int len = read_byte(fd);
-+      if (len & 0x80) {
-+#if MAXPATHLEN > 32767
-+              uchar lenbuf[2];
-+              read_buf(fd, (char *)lenbuf, 2);
-+              len = (len & ~0x80) * 0x10000 + lenbuf[0] * 0x100 + lenbuf[1];
-+#else
-+              len = (len & ~0x80) * 0x100 + read_byte(fd);
-+#endif
-+      }
-+      if (len) {
-+              if (len >= MAXPATHLEN) {
-+                      rprintf(FERROR, "bogus data on generator name pipe\n");
-+                      exit_cleanup(RERR_PROTOCOL);
-+              }
-+              read_sbuf(fd, buf, len);
-+              return buf;
-+      }
-+      return realname;
-+}
-+
-+
- static void discard_receive_data(int f_in, OFF_T length)
- {
-       receive_data(f_in, NULL, -1, 0, NULL, -1, length);
-@@ -335,7 +359,8 @@ static void discard_receive_data(int f_i
+--- orig/receiver.c    2004-09-21 09:40:27
++++ receiver.c 2004-09-07 21:57:20
+@@ -329,7 +329,8 @@ static void discard_receive_data(int f_i
   * main routine for receiver process.
   *
   * Receiver process runs on the same host as the generator process. */
@@ -304,69 +298,83 @@ You must run "make proto" before compiling.
  {
        int next_gen_i = -1;
        int fd1,fd2;
-@@ -364,8 +389,15 @@ int recv_files(int f_in, struct file_lis
+@@ -358,8 +359,13 @@ int recv_files(int f_in, struct file_lis
                i = read_int(f_in);
                if (i == -1) {
                        if (read_batch) {
 -                              if (next_gen_i != flist->count)
 -                                      while (read_int(batch_gen_fd) != -1) {}
-+                              while (next_gen_i < flist->count) {
-+                                      if (f_in_name >= 0 && next_gen_i >= 0) {
-+                                              read_gen_name(f_in_name,
-+                                                      fnamecmpbuf, NULL);
-+                                      }
-+                                      next_gen_i = read_int(batch_gen_fd);
-+                                      if (next_gen_i < 0)
-+                                              break;
++                              if (next_gen_i != flist->count) {
++                                      do {
++                                              if (f_in_name >= 0
++                                                  && next_gen_i >= 0)
++                                                      read_byte(f_in_name);
++                                      } while (read_int(batch_gen_fd) != -1);
 +                              }
                                next_gen_i = -1;
                        }
  
-@@ -413,6 +445,10 @@ int recv_files(int f_in, struct file_lis
+@@ -407,6 +413,8 @@ int recv_files(int f_in, struct file_lis
  
                if (read_batch) {
                        while (i > next_gen_i) {
-+                              if (f_in_name >= 0 && next_gen_i >= 0) {
-+                                      read_gen_name(f_in_name, fnamecmpbuf,
-+                                                    NULL);
-+                              }
++                              if (f_in_name >= 0 && next_gen_i >= 0)
++                                      read_byte(f_in_name);
                                next_gen_i = read_int(batch_gen_fd);
                                if (next_gen_i == -1)
                                        next_gen_i = flist->count;
-@@ -423,8 +459,14 @@ int recv_files(int f_in, struct file_lis
+@@ -417,6 +425,7 @@ int recv_files(int f_in, struct file_lis
                                discard_receive_data(f_in, file->length);
                                continue;
                        }
 +                      next_gen_i = -1;
                }
  
-+              if (f_in_name >= 0)
-+                      fnamecmp = read_gen_name(f_in_name, fnamecmpbuf, fname);
-+              else
-+                      fnamecmp = fname;
-+
                if (server_exclude_list.head
-                   && check_exclude(&server_exclude_list, fname,
-                                    S_ISDIR(file->mode)) < 0) {
-@@ -437,13 +479,7 @@ int recv_files(int f_in, struct file_lis
-                       continue;
+@@ -426,35 +435,31 @@ int recv_files(int f_in, struct file_lis
+                       exit_cleanup(RERR_PROTOCOL);
                }
  
 -              if (partial_dir) {
 -                      if ((partialptr = partial_dir_fname(fname)) != NULL)
 -                              fnamecmp = partialptr;
 -                      else
--                              fnamecmp = fname;
--              } else
--                      fnamecmp = partialptr = fname;
 +              partialptr = partial_dir ? partial_dir_fname(fname) : fname;
++
++              if (f_in_name >= 0) {
++                      switch (read_byte(f_in_name)) {
++                      case G2R_FNAME:
+                               fnamecmp = fname;
++                              break;
++                      case G2R_PARTIAL_DIR:
++                              fnamecmp = partialptr ? partialptr : fname;
++                              break;
++                      case G2R_BACKUP:
++                              fnamecmp = get_backup_name(fname);
++                              break;
++                      default:
++                              pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
++                                       compare_dest, fname);
++                              fnamecmp = fnamecmpbuf;
++                              break;
++                      }
+               } else
+-                      fnamecmp = partialptr = fname;
+-
+-              if (inplace && make_backups) {
+-                      if (!(fnamecmp = get_backup_name(fname)))
+-                              fnamecmp = partialptr;
+-              }
++                      fnamecmp = fname;
  
                /* open the file */
                fd1 = do_open(fnamecmp, O_RDONLY, 0);
-@@ -453,14 +489,6 @@ int recv_files(int f_in, struct file_lis
-                       fd1 = do_open(fnamecmp, O_RDONLY, 0);
-               }
  
+-              if (fd1 == -1 && fnamecmp != fname) {
+-                      fnamecmp = fname;
+-                      fd1 = do_open(fnamecmp, O_RDONLY, 0);
+-              }
+-
 -              if (fd1 == -1 && compare_dest != NULL) {
 -                      /* try the file at compare_dest instead */
 -                      pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
@@ -378,3 +386,16 @@ You must run "make proto" before compiling.
                if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
                        rsyserr(FERROR, errno, "fstat %s failed",
                                full_fname(fnamecmp));
+--- orig/rsync.h       2004-09-22 08:47:31
++++ rsync.h    2004-09-07 21:52:22
+@@ -119,6 +119,10 @@
+ #define PDIR_CREATE   1
+ #define PDIR_DELETE   0
++#define G2R_FNAME     0x80
++#define G2R_PARTIAL_DIR       0x81
++#define G2R_BACKUP    0x82
++
+ /* Log-message categories.  FLOG is only used on the daemon side to
+  * output messages to the log file. */