Has been applied to CVS.
authorWayne Davison <wayned@samba.org>
Fri, 16 Jul 2004 20:07:06 +0000 (20:07 +0000)
committerWayne Davison <wayned@samba.org>
Fri, 16 Jul 2004 20:07:06 +0000 (20:07 +0000)
inplace.diff [deleted file]

diff --git a/inplace.diff b/inplace.diff
deleted file mode 100644 (file)
index 7200d2b..0000000
+++ /dev/null
@@ -1,394 +0,0 @@
-Patch from Mark Curtis to implement the --inplace option.
-Improved by Wayne Davison.
-
-Run these commands after applying the patch:
-
-    autoconf
-    autoheader
-    ./configure
-    make
-
-Optional:
-
-    make rsync.1
-
---- orig/configure.in  2004-04-30 18:04:07
-+++ configure.in       2004-07-03 20:19:54
-@@ -442,7 +442,7 @@ dnl AC_FUNC_MEMCMP
- AC_FUNC_UTIME_NULL
- AC_FUNC_ALLOCA
- AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod mkfifo \
--    fchmod fstat strchr readlink link utime utimes strftime mtrace \
-+    fchmod fstat strchr readlink link utime utimes strftime mtrace ftruncate \
-     memmove lchown vsnprintf snprintf asprintf setsid glob strpbrk \
-     strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid)
---- orig/match.c       2004-07-15 02:21:10
-+++ match.c    2004-07-16 19:39:08
-@@ -23,6 +23,7 @@ extern int verbose;
- extern int am_server;
- extern int do_progress;
- extern int checksum_seed;
-+extern int inplace;
- typedef unsigned short tag;
-@@ -200,6 +201,12 @@ static void hash_search(int f,struct sum
-                       if (l != s->sums[i].len)
-                               continue;
-+                      /* inplace: ensure chunk's offset is either >= our
-+                       * offset or that the data didn't move. */
-+                      if (inplace && s->sums[i].offset < offset
-+                          && !(s->sums[i].flags & SUMFLG_SAME_OFFSET))
-+                              continue;
-+
-                       if (verbose > 3)
-                               rprintf(FINFO,"potential match at %.0f target=%.0f %.0f sum=%08x\n",
-                                       (double)offset,(double)j,(double)i,sum);
-@@ -215,15 +222,41 @@ static void hash_search(int f,struct sum
-                               continue;
-                       }
-+                      /* If inplace is enabled, the best possible match is
-+                       * one with an identical offset, so we prefer that over
-+                       * the following want_i optimization. */
-+                      if (inplace) {
-+                              do {
-+                                      size_t i2 = targets[j].i;
-+                                      if (s->sums[i2].offset != offset)
-+                                              continue;
-+                                      if (i2 != i) {
-+                                              if (sum != s->sums[i2].sum1)
-+                                                      break;
-+                                              if (memcmp(sum2, s->sums[i2].sum2,
-+                                                         s->s2length) != 0)
-+                                                      break;
-+                                              i = i2;
-+                                      }
-+                                      /* This chunk was at the same offset on
-+                                       * both the sender and the receiver. */
-+                                      s->sums[i].flags |= SUMFLG_SAME_OFFSET;
-+                                      goto set_want_i;
-+                              } while (++j < s->count && targets[j].t == t);
-+                      }
-+
-                       /* we've found a match, but now check to see
-                        * if want_i can hint at a better match. */
-                       if (i != want_i && want_i < s->count
-+                          && (!inplace || s->sums[want_i].offset >= offset
-+                           || s->sums[want_i].flags & SUMFLG_SAME_OFFSET)
-                           && sum == s->sums[want_i].sum1
-                           && memcmp(sum2, s->sums[want_i].sum2, s->s2length) == 0) {
-                               /* we've found an adjacent match - the RLL coder
-                                * will be happy */
-                               i = want_i;
-                       }
-+                  set_want_i:
-                       want_i = i + 1;
-                       matched(f,s,buf,offset,i);
---- orig/options.c     2004-07-16 19:35:29
-+++ options.c  2004-07-03 20:19:54
-@@ -94,6 +94,7 @@ int ignore_errors = 0;
- int modify_window = 0;
- int blocking_io = -1;
- int checksum_seed = 0;
-+int inplace = 0;
- unsigned int block_size = 0;
-@@ -148,6 +149,7 @@ char *bind_address;
- static void print_rsync_version(enum logcode f)
- {
-       char const *got_socketpair = "no ";
-+      char const *have_inplace = "no ";
-       char const *hardlinks = "no ";
-       char const *links = "no ";
-       char const *ipv6 = "no ";
-@@ -157,6 +159,10 @@ static void print_rsync_version(enum log
-       got_socketpair = "";
- #endif
-+#if HAVE_FTRUNCATE
-+      have_inplace = "";
-+#endif
-+
- #if SUPPORT_HARD_LINKS
-       hardlinks = "";
- #endif
-@@ -182,8 +188,8 @@ static void print_rsync_version(enum log
-       /* Note that this field may not have type ino_t.  It depends
-        * on the complicated interaction between largefile feature
-        * macros. */
--      rprintf(f, "              %sIPv6, %d-bit system inums, %d-bit internal inums\n",
--              ipv6,
-+      rprintf(f, "              %sinplace, %sIPv6, %d-bit system inums, %d-bit internal inums\n",
-+              have_inplace, ipv6,
-               (int) (sizeof dumstat->st_ino * 8),
-               (int) (sizeof (uint64) * 8));
- #ifdef MAINTAINER_MODE
-@@ -233,6 +239,7 @@ void usage(enum logcode F)
-   rprintf(F,"     --backup-dir            make backups into this directory\n");
-   rprintf(F,"     --suffix=SUFFIX         backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
-   rprintf(F," -u, --update                update only (don't overwrite newer files)\n");
-+  rprintf(F,"     --inplace               update the destination file inplace (see man page)\n");
-   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
-   rprintf(F," -l, --links                 copy symlinks as symlinks\n");
-   rprintf(F," -L, --copy-links            copy the referent of all symlinks\n");
-@@ -340,6 +347,7 @@ static struct poptOption long_options[] 
-   {"sparse",          'S', POPT_ARG_NONE,   &sparse_files, 0, 0, 0 },
-   {"cvs-exclude",     'C', POPT_ARG_NONE,   &cvs_exclude, 0, 0, 0 },
-   {"update",          'u', POPT_ARG_NONE,   &update_only, 0, 0, 0 },
-+  {"inplace",          0,  POPT_ARG_NONE,   &inplace, 0, 0, 0 },
-   {"keep-dirlinks",   'K', POPT_ARG_NONE,   &keep_dirlinks, 0, 0, 0 },
-   {"links",           'l', POPT_ARG_NONE,   &preserve_links, 0, 0, 0 },
-   {"copy-links",      'L', POPT_ARG_NONE,   &copy_links, 0, 0, 0 },
-@@ -754,6 +762,18 @@ int parse_arguments(int *argc, const cha
-                       bwlimit_writemax = 512;
-       }
-+      if (inplace) {
-+#if HAVE_FTRUNCATE
-+              if (keep_partial)
-+                      keep_partial = 0;
-+#else
-+              snprintf(err_buf, sizeof err_buf,
-+                       "inplace is not supported on this %s\n",
-+                       am_server ? "server" : "client");
-+              return 0;
-+#endif
-+      }
-+
-       if (files_from) {
-               char *colon;
-               if (*argc != 2 && !(am_server && am_sender && *argc == 1)) {
-@@ -971,6 +991,9 @@ void server_options(char **args,int *arg
-       if (opt_ignore_existing && am_sender)
-               args[ac++] = "--ignore-existing";
-+      if (inplace)
-+              args[ac++] = "--inplace";
-+
-       if (tmpdir) {
-               args[ac++] = "--temp-dir";
-               args[ac++] = tmpdir;
---- orig/receiver.c    2004-07-14 17:12:06
-+++ receiver.c 2004-07-03 20:19:54
-@@ -48,6 +48,7 @@ extern int ignore_errors;
- extern int orig_umask;
- extern int keep_partial;
- extern int checksum_seed;
-+extern int inplace;
- static void delete_one(char *fn, int is_dir)
- {
-@@ -255,16 +256,30 @@ static int receive_data(int f_in,struct 
-                       sum_update(map,len);
-               }
--              if (fd != -1 && write_file(fd, map, len) != (int)len) {
--                      rsyserr(FERROR, errno, "write failed on %s",
--                              full_fname(fname));
--                      exit_cleanup(RERR_FILEIO);
-+              if (!inplace || offset != offset2) {
-+                      if (fd != -1 && write_file(fd, map, len) != (int)len) {
-+                              rsyserr(FERROR, errno, "write failed on %s",
-+                                      full_fname(fname));
-+                              exit_cleanup(RERR_FILEIO);
-+                      }
-+              } else {
-+                      flush_write_file(fd);
-+                      if (do_lseek(fd,(OFF_T)len,SEEK_CUR) != offset+len) {
-+                              rprintf(FERROR, "lseek failed on %s: %s, %lli, %lli, %i\n",
-+                                      full_fname(fname), strerror(errno), do_lseek(fd,0,SEEK_CUR), (offset+len), i);
-+                              exit_cleanup(RERR_FILEIO);
-+                      }
-               }
-               offset += len;
-       }
-       flush_write_file(fd);
-+#ifdef HAVE_FTRUNCATE
-+      if (inplace)
-+              ftruncate(fd, offset);
-+#endif
-+
-       if (do_progress)
-               end_progress(total_size);
-@@ -414,44 +429,59 @@ int recv_files(int f_in, struct file_lis
-               } else
-                       mapbuf = NULL;
--              if (!get_tmpname(fnametmp,fname)) {
--                      if (mapbuf)
--                              unmap_file(mapbuf);
--                      if (fd1 != -1)
--                              close(fd1);
--                      continue;
--              }
-+              /* We now check to see if we are writing file "inplace" */
-+              if (inplace)  {
-+                      fd2 = do_open(fnamecmp, O_WRONLY|O_CREAT, 0);
-+                      if (fd2 == -1) {
-+                              rsyserr(FERROR, errno, "open %s failed",
-+                                      full_fname(fnamecmp));
-+                              receive_data(f_in,mapbuf,-1,NULL,file->length);
-+                              if (mapbuf)
-+                                      unmap_file(mapbuf);
-+                              if (fd1 != -1)
-+                                      close(fd1);
-+                              continue;
-+                      }
-+              } else {
-+                      if (!get_tmpname(fnametmp,fname)) {
-+                              if (mapbuf)
-+                                      unmap_file(mapbuf);
-+                              if (fd1 != -1)
-+                                      close(fd1);
-+                              continue;
-+                      }
--              strlcpy(template, fnametmp, sizeof template);
-+                      strlcpy(template, fnametmp, sizeof template);
--              /* we initially set the perms without the
--               * setuid/setgid bits to ensure that there is no race
--               * condition. They are then correctly updated after
--               * the lchown. Thanks to snabb@epipe.fi for pointing
--               * this out.  We also set it initially without group
--               * access because of a similar race condition. */
--              fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
--
--              /* in most cases parent directories will already exist
--               * because their information should have been previously
--               * transferred, but that may not be the case with -R */
--              if (fd2 == -1 && relative_paths && errno == ENOENT &&
--                  create_directory_path(fnametmp, orig_umask) == 0) {
--                      strlcpy(fnametmp, template, sizeof fnametmp);
-+                      /* we initially set the perms without the
-+                       * setuid/setgid bits to ensure that there is no race
-+                       * condition. They are then correctly updated after
-+                       * the lchown. Thanks to snabb@epipe.fi for pointing
-+                       * this out.  We also set it initially without group
-+                       * access because of a similar race condition. */
-                       fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
--              }
--              if (fd2 == -1) {
--                      rsyserr(FERROR, errno, "mkstemp %s failed",
--                              full_fname(fnametmp));
--                      receive_data(f_in,mapbuf,-1,NULL,file->length);
--                      if (mapbuf)
--                              unmap_file(mapbuf);
--                      if (fd1 != -1)
--                              close(fd1);
--                      continue;
--              }
--              cleanup_set(fnametmp, fname, file, mapbuf, fd1, fd2);
-+                      /* in most cases parent directories will already exist
-+                       * because their information should have been previously
-+                       * transferred, but that may not be the case with -R */
-+                      if (fd2 == -1 && relative_paths && errno == ENOENT
-+                          && create_directory_path(fnametmp, orig_umask) == 0) {
-+                              strlcpy(fnametmp, template, sizeof fnametmp);
-+                              fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
-+                      }
-+                      if (fd2 == -1) {
-+                              rsyserr(FERROR, errno, "mkstemp %s failed",
-+                                      full_fname(fnametmp));
-+                              receive_data(f_in,mapbuf,-1,NULL,file->length);
-+                              if (mapbuf)
-+                                      unmap_file(mapbuf);
-+                              if (fd1 != -1)
-+                                      close(fd1);
-+                              continue;
-+                      }
-+
-+                      cleanup_set(fnametmp, fname, file, mapbuf, fd1, fd2);
-+              }
-               if (!am_server && verbose)
-                       rprintf(FINFO, "%s\n", fname);
---- orig/rsync.c       2004-07-02 18:06:32
-+++ rsync.c    2004-07-03 20:19:54
-@@ -34,6 +34,7 @@ extern int force_delete;
- extern int recurse;
- extern int make_backups;
- extern char *backup_dir;
-+extern int inplace;
- /*
-@@ -239,6 +240,13 @@ void finish_transfer(char *fname, char *
-       if (make_backups && !make_backup(fname))
-               return;
-+      if (inplace) {
-+              if (verbose > 2)
-+                      rprintf(FINFO, "finishing %s\n", fname);
-+              set_perms(fname, file, NULL, 0);
-+              return;
-+      }
-+
-       /* move tmp file over real file */
-       if (verbose > 2)
-               rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
---- orig/rsync.h       2004-07-07 08:27:00
-+++ rsync.h    2004-07-16 19:36:20
-@@ -458,11 +458,13 @@ struct file_list {
-       struct file_struct **files;
- };
-+#define SUMFLG_SAME_OFFSET    (1<<0)
-+
- struct sum_buf {
-       OFF_T offset;           /**< offset in file of this chunk */
-       unsigned int len;       /**< length of chunk of file */
--      int i;                  /**< index of this chunk */
-       uint32 sum1;            /**< simple checksum */
-+      short flags;            /**< flag bits */
-       char sum2[SUM_LENGTH];  /**< checksum  */
- };
---- orig/rsync.yo      2004-07-16 19:35:29
-+++ rsync.yo   2004-07-03 20:19:55
-@@ -289,6 +289,7 @@ verb(
-      --backup-dir            make backups into this directory
-      --suffix=SUFFIX         backup suffix (default ~ w/o --backup-dir)
-  -u, --update                update only (don't overwrite newer files)
-+     --inplace               update the destination file inplace
-  -K, --keep-dirlinks         treat symlinked dir on receiver as dir
-  -l, --links                 copy symlinks as symlinks
-  -L, --copy-links            copy the referent of all symlinks
-@@ -484,6 +485,17 @@ dit(bf(-K, --keep-dirlinks)) On the rece
- pointing to a directory, it will be treated as matching a directory
- from the sender.
-+dit(bf(--inplace)) This causes rsync not to create a new copy of the file
-+and then move it into place.  Instead rsync will overwrite the existing
-+file, meaning that the rsync algorithm can't extract the full ammount of
-+network reduction it might otherwise.
-+
-+This option is useful for transfer of large files with block based changes
-+and also on systems that are disk bound not network bound.
-+
-+WARNING: If the transfer is interrupted, you will have an inconsistent file
-+and the transfer should be run again.
-+
- dit(bf(-l, --links)) When symlinks are encountered, recreate the
- symlink on the destination.
---- orig/sender.c      2004-07-15 02:21:11
-+++ sender.c   2004-07-16 19:40:59
-@@ -85,7 +85,7 @@ static struct sum_struct *receive_sums(i
-               read_buf(f, s->sums[i].sum2, s->s2length);
-               s->sums[i].offset = offset;
--              s->sums[i].i = i;
-+              s->sums[i].flags = 0;
-               if (i == (int) s->count-1 && s->remainder != 0) {
-                       s->sums[i].len = s->remainder;