+++ /dev/null
-Delay the renaming of all the temp files until the end of the transfer.
-
---- orig/options.c 2005-01-25 03:26:51
-+++ options.c 2005-01-25 09:21:08
-@@ -101,6 +101,7 @@ int modify_window = 0;
- int blocking_io = -1;
- int checksum_seed = 0;
- int inplace = 0;
-+int delay_renames = 0;
- long block_size = 0; /* "long" because popt can't set an int32. */
-
-
-@@ -288,6 +289,7 @@ void usage(enum logcode F)
- rprintf(F," --max-size=SIZE don't transfer any file larger than SIZE\n");
- rprintf(F," --partial keep partially transferred files\n");
- rprintf(F," --partial-dir=DIR put a partially transferred file into DIR\n");
-+ rprintf(F," --delay-renames rename all transferred files into place at end\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");
- rprintf(F," -I, --ignore-times turn off mod time & file size quick check\n");
-@@ -407,6 +409,7 @@ static struct poptOption long_options[]
- {"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 },
-+ {"delay-renames", 0, POPT_ARG_NONE, &delay_renames, 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 },
-@@ -995,11 +998,15 @@ int parse_arguments(int *argc, const cha
- bwlimit_writemax = 512;
- }
-
-+ if (delay_renames && !partial_dir)
-+ partial_dir = ".~tmp~";
-+
- if (inplace) {
- #if HAVE_FTRUNCATE
- if (partial_dir) {
- snprintf(err_buf, sizeof err_buf,
-- "--inplace cannot be used with --partial-dir\n");
-+ "--inplace cannot be used with --%s\n",
-+ delay_renames ? "delay-renames" : "partial-dir");
- return 0;
- }
- keep_partial = 0;
-@@ -1236,6 +1243,8 @@ void server_options(char **args,int *arg
- if (partial_dir && am_sender) {
- args[ac++] = "--partial-dir";
- args[ac++] = partial_dir;
-+ if (delay_renames)
-+ args[ac++] = "--delay-renames";
- } else if (keep_partial)
- args[ac++] = "--partial";
-
---- orig/receiver.c 2005-01-24 01:43:10
-+++ receiver.c 2005-01-10 10:16:54
-@@ -48,6 +48,7 @@ extern int orig_umask;
- extern int keep_partial;
- extern int checksum_seed;
- extern int inplace;
-+extern int delay_renames;
-
- extern struct filter_list_struct server_filter_list;
-
-@@ -272,6 +273,7 @@ int recv_files(int f_in, struct file_lis
- char fnametmp[MAXPATHLEN];
- char *fnamecmp, *partialptr;
- char fnamecmpbuf[MAXPATHLEN];
-+ uchar *delayed_bits = NULL;
- struct file_struct *file;
- struct stats initial_stats;
- int save_make_backups = make_backups;
-@@ -285,6 +287,13 @@ int recv_files(int f_in, struct file_lis
- flist->hlink_pool = NULL;
- }
-
-+ if (delay_renames) {
-+ int sz = (flist->count + 7) / 8;
-+ if (!(delayed_bits = new_array(char, sz)))
-+ out_of_memory("recv_files");
-+ memset(delayed_bits, 0, sz);
-+ }
-+
- while (1) {
- cleanup_disable();
-
-@@ -499,7 +508,7 @@ int recv_files(int f_in, struct file_lis
- exit_cleanup(RERR_FILEIO);
- }
-
-- if (recv_ok || inplace) {
-+ if ((recv_ok && !delay_renames) || inplace) {
- finish_transfer(fname, fnametmp, file, recv_ok, 1);
- if (partialptr != fname && fnamecmp == partialptr) {
- do_unlink(partialptr);
-@@ -509,6 +518,8 @@ int recv_files(int f_in, struct file_lis
- && handle_partial_dir(partialptr, PDIR_CREATE)) {
- finish_transfer(partialptr, fnametmp, file, recv_ok,
- !partial_dir);
-+ if (delay_renames && recv_ok)
-+ delayed_bits[i/8] |= 1 << (i % 8);
- } else {
- partialptr = NULL;
- do_unlink(fnametmp);
-@@ -548,6 +559,33 @@ int recv_files(int f_in, struct file_lis
- }
- make_backups = save_make_backups;
-
-+ if (delay_renames) {
-+ for (i = 0; i < flist->count; i++) {
-+ struct file_struct *file = flist->files[i];
-+ if (!file->basename
-+ || !(delayed_bits[i/8] & (1 << (i % 8))))
-+ continue;
-+ fname = local_name ? local_name : f_name(file);
-+ partialptr = partial_dir_fname(fname);
-+ if (partialptr) {
-+ if (make_backups && !make_backup(fname))
-+ continue;
-+ if (verbose > 2) {
-+ rprintf(FINFO, "renaming %s to %s\n",
-+ partialptr, fname);
-+ }
-+ if (do_rename(partialptr, fname) < 0) {
-+ rsyserr(FERROR, errno,
-+ "rename failed for %s (from %s)",
-+ fname, partialptr);
-+ } else {
-+ handle_partial_dir(partialptr,
-+ PDIR_DELETE);
-+ }
-+ }
-+ }
-+ }
-+
- if (delete_after && recurse && !local_name && flist->count > 0)
- delete_files(flist);
-
---- orig/rsync.yo 2005-01-25 03:26:51
-+++ rsync.yo 2005-01-25 09:30:44
-@@ -353,6 +353,7 @@ verb(
- --max-size=SIZE don't transfer any file larger than SIZE
- --partial keep partially transferred files
- --partial-dir=DIR put a partially transferred file into DIR
-+ --delay-renames rename transferred files into place at end
- --numeric-ids don't map uid/gid values by user/group name
- --timeout=TIME set I/O timeout in seconds
- -I, --ignore-times turn off mod time & file size quick check
-@@ -549,9 +550,9 @@ or appended data, and also on systems th
- bound.
-
- The option implies --partial (since an interrupted transfer does not delete
--the file), but conflicts with --partial-dir. Prior to rsync 2.6.4
----inplace was also incompatible with --compare-dest, --copy-dest, and
----link-dest.
-+the file), but conflicts with --partial-dir and --delay-renames.
-+Prior to rsync 2.6.4 --inplace was also incompatible with --compare-dest,
-+--copy-dest, and --link-dest.
-
- WARNING: The file's data will be in an inconsistent state during the
- transfer (and possibly afterward if the transfer gets interrupted), so you
-@@ -1028,13 +1029,26 @@ is a security risk. E.g. AVOID "/tmp".
-
- You can also set the partial-dir value the RSYNC_PARTIAL_DIR environment
- variable. Setting this in the environment does not force --partial to be
--enabled, but rather it effects where partial files go when --partial (or
---P) is used. For instance, instead of specifying --partial-dir=.rsync-tmp
-+enabled, but rather it effects where partial files go when --partial is
-+specified. For instance, instead of using --partial-dir=.rsync-tmp
- along with --progress, you could set RSYNC_PARTIAL_DIR=.rsync-tmp in your
- environment and then just use the -P option to turn on the use of the
--.rsync-tmp dir for partial transfers. The only time the --partial option
--does not look for this environment value is when --inplace was also
--specified (since --inplace conflicts with --partial-dir).
-+.rsync-tmp dir for partial transfers. The only times the --partial option
-+does not look for this environment value is (1) when --inplace was also
-+specified (since --inplace conflicts with --partial-dir), and (2) when
-+--delay-renames was also specified (see below).
-+
-+dit(bf(--delay-renames)) This option puts the temporary file from each
-+updated file into the file's partial-dir (see above) until the end of the
-+transfer, at which time all the files are renamed into place in rapid
-+succession. This attempts to make the updating of the files a little more
-+atomic. If you don't specify the --partial-dir option, this option will
-+cause it to default to ".~tmp~" (RSYNC_PARTIAL_DIR is not consulted for
-+this value). Conflicts with --inplace.
-+
-+See also the "atomic-rsync" perl script in the "support" subdir for an
-+update algorithm that is even more atomic (it uses --link-dest and a
-+parallel hierarchy of files).
-
- dit(bf(--progress)) This option tells rsync to print information
- showing the progress of the transfer. This gives a bored user