From df8c196d2db53f0eb6734d56e31aee030f2ea175 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Fri, 23 Jul 2004 19:40:29 +0000 Subject: [PATCH] Implement a --partial-dir=DIR option. --- partial-dir.diff | 220 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 partial-dir.diff diff --git a/partial-dir.diff b/partial-dir.diff new file mode 100644 index 0000000..7fee89e --- /dev/null +++ b/partial-dir.diff @@ -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. -- 2.34.1