1 Delay the renaming of all the temp files until the end of the transfer.
3 --- orig/options.c 2005-01-23 01:45:43
4 +++ options.c 2005-01-23 07:27:59
5 @@ -99,6 +99,7 @@ int modify_window = 0;
9 +int delay_renames = 0;
10 long block_size = 0; /* "long" because popt can't set an int32. */
13 @@ -273,6 +274,7 @@ void usage(enum logcode F)
14 rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n");
15 rprintf(F," --existing only update files that already exist\n");
16 rprintf(F," --ignore-existing ignore files that already exist on receiving side\n");
17 + rprintf(F," --delay-renames renames transferred files into place at end\n");
18 rprintf(F," --delete delete files that don't exist on the sending side\n");
19 rprintf(F," --delete-after receiver deletes after transferring, not before\n");
20 rprintf(F," --delete-excluded also delete excluded files on the receiving side\n");
21 @@ -394,6 +396,7 @@ static struct poptOption long_options[]
22 {"progress", 0, POPT_ARG_NONE, &do_progress, 0, 0, 0 },
23 {"partial", 0, POPT_ARG_NONE, &keep_partial, 0, 0, 0 },
24 {"partial-dir", 0, POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
25 + {"delay-renames", 0, POPT_ARG_NONE, &delay_renames, 0, 0, 0 },
26 {"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors, 0, 0, 0 },
27 {"blocking-io", 0, POPT_ARG_VAL, &blocking_io, 1, 0, 0 },
28 {"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 },
29 @@ -948,11 +951,15 @@ int parse_arguments(int *argc, const cha
30 bwlimit_writemax = 512;
33 + if (delay_renames && !partial_dir)
34 + partial_dir = ".~tmp~";
39 + if (partial_dir || delay_renames) {
40 snprintf(err_buf, sizeof err_buf,
41 - "--inplace cannot be used with --partial-dir\n");
42 + "--inplace cannot be used with --%s\n",
43 + delay_renames ? "delay-renames" : "partial-dir");
47 @@ -1187,6 +1194,8 @@ void server_options(char **args,int *arg
48 if (partial_dir && am_sender) {
49 args[ac++] = "--partial-dir";
50 args[ac++] = partial_dir;
52 + args[ac++] = "--delay-renames";
53 } else if (keep_partial)
54 args[ac++] = "--partial";
56 --- orig/receiver.c 2005-01-23 07:27:24
57 +++ receiver.c 2005-01-10 10:16:54
58 @@ -53,6 +53,7 @@ extern int orig_umask;
59 extern int keep_partial;
60 extern int checksum_seed;
62 +extern int delay_renames;
64 extern struct exclude_list_struct server_exclude_list;
66 @@ -324,6 +325,7 @@ int recv_files(int f_in, struct file_lis
67 char fnametmp[MAXPATHLEN];
68 char *fnamecmp, *partialptr;
69 char fnamecmpbuf[MAXPATHLEN];
70 + uchar *delayed_bits = NULL;
71 struct file_struct *file;
72 struct stats initial_stats;
73 int save_make_backups = make_backups;
74 @@ -337,6 +339,12 @@ int recv_files(int f_in, struct file_lis
75 flist->hlink_pool = NULL;
78 + if (delay_renames) {
79 + if (!(delayed_bits = new_array(char, (flist->count + 7) / 8)))
80 + out_of_memory("recv_files");
81 + memset(delayed_bits, 0, (flist->count + 7) / 8);
87 @@ -551,7 +559,7 @@ int recv_files(int f_in, struct file_lis
88 exit_cleanup(RERR_FILEIO);
91 - if (recv_ok || inplace) {
92 + if ((recv_ok && !delay_renames) || inplace) {
93 finish_transfer(fname, fnametmp, file, recv_ok, 1);
94 if (partialptr != fname && fnamecmp == partialptr) {
95 do_unlink(partialptr);
96 @@ -561,6 +569,8 @@ int recv_files(int f_in, struct file_lis
97 && handle_partial_dir(partialptr, PDIR_CREATE)) {
98 finish_transfer(partialptr, fnametmp, file, recv_ok,
100 + if (delay_renames && recv_ok)
101 + delayed_bits[i/8] |= 1 << (i % 8);
105 @@ -600,6 +610,33 @@ int recv_files(int f_in, struct file_lis
107 make_backups = save_make_backups;
109 + if (delay_renames) {
110 + for (i = 0; i < flist->count; i++) {
111 + struct file_struct *file = flist->files[i];
112 + if (!file->basename
113 + || !(delayed_bits[i/8] & (1 << (i % 8))))
115 + fname = local_name ? local_name : f_name(file);
116 + partialptr = partial_dir_fname(fname);
118 + if (make_backups && !make_backup(fname))
121 + rprintf(FINFO, "renaming %s to %s\n",
122 + partialptr, fname);
124 + if (do_rename(partialptr, fname) < 0) {
125 + rsyserr(FERROR, errno,
126 + "rename failed for %s (from %s)",
127 + fname, partialptr);
129 + handle_partial_dir(partialptr,
136 if (delete_after && recurse && !local_name && flist->count > 0)
139 --- orig/rsync.yo 2005-01-22 22:48:52
140 +++ rsync.yo 2005-01-23 07:28:13
141 @@ -340,6 +340,7 @@ verb(
142 --rsync-path=PATH specify path to rsync on the remote machine
143 --existing only update files that already exist
144 --ignore-existing ignore files that already exist on receiver
145 + --delay-renames renames transferred files into place at end
146 --delete delete files that don't exist on sender
147 --delete-after receiver deletes after transfer, not before
148 --delete-excluded also delete excluded files on receiver
149 @@ -546,9 +547,9 @@ or appended data, and also on systems th
152 The option implies --partial (since an interrupted transfer does not delete
153 -the file), but conflicts with --partial-dir. Prior to rsync 2.6.4
154 ---inplace was also incompatible with --compare-dest, --copy-dest, and
156 +the file), but conflicts with --partial-dir and --delay-renames.
157 +Prior to rsync 2.6.4 --inplace was also incompatible with --compare-dest,
158 +--copy-dest, and --link-dest.
160 WARNING: The file's data will be in an inconsistent state during the
161 transfer (and possibly afterward if the transfer gets interrupted), so you
162 @@ -978,6 +979,17 @@ environment and then just use the -P opt
163 does not look for this environment value is when --inplace was also
164 specified (since --inplace conflicts with --partial-dir).
166 +dit(bf(--delay-renames)) This option puts the temporary file from each
167 +updated file into the file's partial-dir (see above) until the end of the
168 +transfer, at which time all the files are renamed into place in rapid
169 +succession. This attempts to make the updating of the files a little more
170 +atomic. If you don't specify the --partial-dir option, this option will
171 +cause it to default to ".~tmp~" (RSYNC_PARTIAL_DIR is not consulted for
172 +this value). Conflicts with --inplace.
174 +See also the "atomic-rsync" perl script in the "support" subdir for an
175 +update algorithm that is even more atomic (it uses --link-dest).
177 dit(bf(--progress)) This option tells rsync to print information
178 showing the progress of the transfer. This gives a bored user