Implement a --partial-dir=DIR option.
authorWayne Davison <wayned@samba.org>
Fri, 23 Jul 2004 19:40:29 +0000 (19:40 +0000)
committerWayne Davison <wayned@samba.org>
Fri, 23 Jul 2004 19:40:29 +0000 (19:40 +0000)
partial-dir.diff [new file with mode: 0644]

diff --git a/partial-dir.diff b/partial-dir.diff
new file mode 100644 (file)
index 0000000..7fee89e
--- /dev/null
@@ -0,0 +1,220 @@
+--- orig/cleanup.c     2004-07-20 21:36:07
++++ cleanup.c  2004-07-23 19:19:47
+@@ -24,6 +24,7 @@
+ extern int io_error;
+ extern int keep_partial;
+ extern int log_got_error;
++extern char *partial_dir;
+ /**
+  * Close all open sockets and files, allowing a (somewhat) graceful
+@@ -113,6 +114,8 @@ void _exit_cleanup(int code, const char 
+       if (cleanup_got_literal && cleanup_fname && keep_partial) {
+               char *fname = cleanup_fname;
++              if (partial_dir)
++                      do_mkdir(partial_dir, 0700);
+               cleanup_fname = NULL;
+               if (cleanup_fd_r != -1)
+                       close(cleanup_fd_r);
+--- orig/generator.c   2004-07-23 17:16:12
++++ generator.c        2004-07-23 19:19:47
+@@ -42,6 +42,7 @@ extern int size_only;
+ extern int io_timeout;
+ extern int protocol_version;
+ extern int always_checksum;
++extern char *partial_dir;
+ extern char *compare_dest;
+ extern int link_dest;
+ extern int whole_file;
+@@ -413,6 +414,21 @@ static void recv_generator(char *fname, 
+       fnamecmp = fname;
++      if (partial_dir) {
++              STRUCT_STAT st2;
++              char *fn = strrchr(fname, '/');
++              if (fn)
++                      fn++;
++              else
++                      fn = fname;
++              pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, partial_dir, fn);
++              if (link_stat(fnamecmpbuf, &st2, 0) == 0 && S_ISREG(st2.st_mode)) {
++                      statret = 0;
++                      st = st2;
++                      fnamecmp = fnamecmpbuf;
++              }
++      }
++
+       if (statret == -1 && compare_dest != NULL) {
+               /* try the file at compare_dest instead */
+               int saveerrno = errno;
+--- orig/options.c     2004-07-23 17:16:13
++++ options.c  2004-07-23 19:19:48
+@@ -118,6 +118,7 @@ unsigned int backup_dir_remainder;
+ char *backup_suffix = NULL;
+ char *tmpdir = NULL;
++char *partial_dir = NULL;
+ char *compare_dest = NULL;
+ char *config_file = NULL;
+ char *shell_cmd = NULL;
+@@ -268,6 +269,7 @@ void usage(enum logcode F)
+   rprintf(F,"     --ignore-errors         delete even if there are I/O errors\n");
+   rprintf(F,"     --max-delete=NUM        don't delete more than NUM files\n");
+   rprintf(F,"     --partial               keep partially transferred files\n");
++  rprintf(F,"     --partial-dir=DIR       put a partially transferred file into DIR\n");
+   rprintf(F,"     --force                 force deletion of directories even if not empty\n");
+   rprintf(F,"     --numeric-ids           don't map uid/gid values by user/group name\n");
+   rprintf(F,"     --timeout=TIME          set I/O timeout in seconds\n");
+@@ -383,6 +385,7 @@ static struct poptOption long_options[] 
+   {"stats",            0,  POPT_ARG_NONE,   &do_stats, 0, 0, 0 },
+   {"progress",         0,  POPT_ARG_NONE,   &do_progress, 0, 0, 0 },
+   {"partial",          0,  POPT_ARG_NONE,   &keep_partial, 0, 0, 0 },
++  {"partial-dir",      0,  POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
+   {"ignore-errors",    0,  POPT_ARG_NONE,   &ignore_errors, 0, 0, 0 },
+   {"blocking-io",      0,  POPT_ARG_VAL,    &blocking_io, 1, 0, 0 },
+   {"no-blocking-io",   0,  POPT_ARG_VAL,    &blocking_io, 0, 0, 0 },
+@@ -770,6 +773,11 @@ int parse_arguments(int *argc, const cha
+       if (inplace) {
+ #if HAVE_FTRUNCATE
++              if (partial_dir) {
++                      snprintf(err_buf, sizeof err_buf,
++                               "--inplace cannot be used with --partial-dir\n");
++                      return 0;
++              }
+               keep_partial = 0;
+ #else
+               snprintf(err_buf, sizeof err_buf,
+@@ -777,7 +785,8 @@ int parse_arguments(int *argc, const cha
+                        am_server ? "server" : "client");
+               return 0;
+ #endif
+-      }
++      } else if (partial_dir)
++              keep_partial = 1;
+       if (files_from) {
+               char *colon;
+@@ -969,7 +978,10 @@ void server_options(char **args,int *arg
+               args[ac++] = arg;
+       }
+-      if (keep_partial)
++      if (partial_dir) {
++              args[ac++] = "--partial-dir";
++              args[ac++] = partial_dir;
++      } else if (keep_partial)
+               args[ac++] = "--partial";
+       if (force_delete)
+--- orig/receiver.c    2004-07-23 17:16:13
++++ receiver.c 2004-07-23 19:19:48
+@@ -38,6 +38,7 @@ extern int preserve_perms;
+ extern int cvs_exclude;
+ extern int io_error;
+ extern char *tmpdir;
++extern char *partial_dir;
+ extern char *compare_dest;
+ extern int make_backups;
+ extern int do_progress;
+@@ -339,7 +340,7 @@ int recv_files(int f_in, struct file_lis
+       char template[MAXPATHLEN];
+       char fnametmp[MAXPATHLEN];
+       char *fnamecmp;
+-      char fnamecmpbuf[MAXPATHLEN];
++      char fnamecmpbuf[MAXPATHLEN], partialbuf[MAXPATHLEN];
+       struct file_struct *file;
+       struct stats initial_stats;
+       int save_make_backups = make_backups;
+@@ -406,8 +407,6 @@ int recv_files(int f_in, struct file_lis
+               if (verbose > 2)
+                       rprintf(FINFO,"recv_files(%s)\n",fname);
+-              fnamecmp = fname;
+-
+               if (read_batch) {
+                       while (i > next_gen_i) {
+                               next_gen_i = read_int(batch_gen_fd);
+@@ -434,9 +433,25 @@ int recv_files(int f_in, struct file_lis
+                       continue;
+               }
++              if (partial_dir) {
++                      char *fn = strrchr(fname, '/');
++                      if (fn)
++                              fn++;
++                      else
++                              fn = fname;
++                      pathjoin(partialbuf, sizeof partialbuf, partial_dir, fn);
++                      fnamecmp = partialbuf;
++              } else
++                      fnamecmp = fname;
++
+               /* open the file */
+               fd1 = do_open(fnamecmp, O_RDONLY, 0);
++              if (fd1 == -1 && partial_dir) {
++                      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,
+@@ -524,7 +539,8 @@ int recv_files(int f_in, struct file_lis
+                               continue;
+                       }
+-                      cleanup_set(fnametmp, fname, file, fd1, fd2);
++                      cleanup_set(fnametmp, partial_dir ? partialbuf : fname,
++                                  file, fd1, fd2);
+               }
+               if (!am_server && verbose)
+@@ -549,6 +565,12 @@ int recv_files(int f_in, struct file_lis
+               else
+                       do_unlink(fnametmp);
++              if (fnamecmp == partialbuf) {
++                      do_unlink(partialbuf);
++                      if (*partialbuf != '/')
++                              do_rmdir(partial_dir);
++              }
++
+               cleanup_disable();
+               if (!recv_ok) {
+--- orig/rsync.yo      2004-07-23 17:16:13
++++ rsync.yo   2004-07-23 19:36:41
+@@ -317,6 +317,7 @@ verb(
+      --ignore-errors         delete even if there are I/O errors
+      --max-delete=NUM        don't delete more than NUM files
+      --partial               keep partially transferred files
++     --partial-dir=DIR       put a partially transferred file into DIR
+      --force                 force deletion of dirs even if not empty
+      --numeric-ids           don't map uid/gid values by user/group name
+      --timeout=TIME          set I/O timeout in seconds
+@@ -865,6 +866,21 @@ it is more desirable to keep partially t
+ --partial option tells rsync to keep the partial file which should
+ make a subsequent transfer of the rest of the file much faster.
++dit(bf(--partial-dir=DIR)) Turns on --partial mode, but tells rsync to
++put a partially transferred file into DIR instead of writing out the
++file to the destination dir.  Rsync will also use a file found in this
++dir as data to speed up a subsequent transfer.
++
++Rsync will create the dir if it is missing, so feel free to use a
++relative path (such as quote(--partial-dir=.rsync-partial)) if you
++want the file put into a directory relative to the current directory
++in the tree (rsync will also try to remove the DIR if a partial file
++was found and the DIR was specified as a relative path).
++
++If you want to delete files on the destination, be sure to use
++--delete-after instead of --delete or the partial file may be deleted
++before it can be used.
++
+ dit(bf(--progress)) This option tells rsync to print information
+ showing the progress of the transfer. This gives a bored user
+ something to watch.