1 Patch from Mark Curtis to implement the --inplace option.
3 --- match.c 13 May 2004 06:46:20 -0000 1.61
4 +++ match.c 15 May 2004 20:23:18 -0000
8 extern int do_progress;
11 typedef unsigned short tag;
13 @@ -197,6 +198,10 @@ static void hash_search(int f,struct sum
14 /* also make sure the two blocks are the same length */
15 l = MIN((OFF_T)s->blength, len-offset);
16 if (l != s->sums[i].len)
19 + /* if inplace, make sure the offset is greater than where we are */
20 + if (inplace && offset > s->sums[i].offset)
24 --- options.c 6 May 2004 21:08:01 -0000 1.148
25 +++ options.c 15 May 2004 20:23:19 -0000
26 @@ -91,6 +91,7 @@ int ignore_errors = 0;
27 int modify_window = 0;
29 int checksum_seed = 0;
31 unsigned int block_size = 0;
34 @@ -231,6 +232,7 @@ void usage(enum logcode F)
35 rprintf(F," --backup-dir make backups into this directory\n");
36 rprintf(F," --suffix=SUFFIX backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
37 rprintf(F," -u, --update update only (don't overwrite newer files)\n");
38 + rprintf(F," --inplace update the destination file inplace *SEE MAN PAGE*\n");
39 rprintf(F," -l, --links copy symlinks as symlinks\n");
40 rprintf(F," -L, --copy-links copy the referent of all symlinks\n");
41 rprintf(F," --copy-unsafe-links copy the referent of \"unsafe\" symlinks\n");
42 @@ -321,6 +323,7 @@ static struct poptOption long_options[]
43 {"delete", 0, POPT_ARG_NONE, &delete_mode, 0, 0, 0 },
44 {"existing", 0, POPT_ARG_NONE, &only_existing, 0, 0, 0 },
45 {"ignore-existing", 0, POPT_ARG_NONE, &opt_ignore_existing, 0, 0, 0 },
46 + {"inplace", 0, POPT_ARG_NONE, &inplace, 0, 0, 0 },
47 {"delete-after", 0, POPT_ARG_NONE, 0, OPT_DELETE_AFTER, 0, 0 },
48 {"delete-excluded", 0, POPT_ARG_NONE, 0, OPT_DELETE_EXCLUDED, 0, 0 },
49 {"force", 0, POPT_ARG_NONE, &force_delete, 0, 0, 0 },
50 @@ -723,6 +726,9 @@ int parse_arguments(int *argc, const cha
51 if (do_progress && !verbose)
54 + if (inplace && keep_partial)
59 if (*argc != 2 && !(am_server && am_sender && *argc == 1)) {
60 @@ -938,6 +944,9 @@ void server_options(char **args,int *arg
62 if (opt_ignore_existing && am_sender)
63 args[ac++] = "--ignore-existing";
66 + args[ac++] = "--inplace";
69 args[ac++] = "--temp-dir";
70 --- receiver.c 15 May 2004 19:31:10 -0000 1.78
71 +++ receiver.c 15 May 2004 20:23:19 -0000
72 @@ -46,6 +46,7 @@ extern int module_id;
73 extern int ignore_errors;
74 extern int orig_umask;
75 extern int keep_partial;
78 static void delete_one(char *fn, int is_dir)
80 @@ -251,16 +252,28 @@ static int receive_data(int f_in,struct
84 - if (fd != -1 && write_file(fd,map,len) != (int) len) {
85 - rsyserr(FERROR, errno, "write failed on %s",
87 - exit_cleanup(RERR_FILEIO);
88 + if (!inplace || offset != offset2) {
89 + if (fd != -1 && write_file(fd,map,len) != (int) len) {
90 + rsyserr(FERROR, errno, "write failed on %s",
92 + exit_cleanup(RERR_FILEIO);
95 + flush_write_file(fd);
96 + if (do_lseek(fd,(OFF_T)len,SEEK_CUR) != offset+len) {
97 + rprintf(FERROR, "lseek failed on %s: %s, %lli, %lli, %i\n",
98 + full_fname(fname), strerror(errno), do_lseek(fd,0,SEEK_CUR), (offset+len), i);
99 + exit_cleanup(RERR_FILEIO);
105 flush_write_file(fd);
108 + ftruncate(fd, offset);
111 end_progress(total_size);
113 @@ -412,37 +425,50 @@ int recv_files(int f_in,struct file_list
117 - if (!get_tmpname(fnametmp,fname)) {
118 - if (mapbuf) unmap_file(mapbuf);
119 - if (fd1 != -1) close(fd1);
122 + /* We now check to see if we are writing file "inplace" */
124 + fd2 = do_open(fnamecmp, O_WRONLY|O_CREAT, 0);
126 + rsyserr(FERROR, errno, "open %s failed",
127 + full_fname(fnametmp));
128 + receive_data(f_in,mapbuf,-1,NULL,file->length);
129 + if (mapbuf) unmap_file(mapbuf);
130 + if (fd1 != -1) close(fd1);
134 + if (!get_tmpname(fnametmp,fname)) {
135 + if (mapbuf) unmap_file(mapbuf);
136 + if (fd1 != -1) close(fd1);
140 - strlcpy(template, fnametmp, sizeof template);
141 + strlcpy(template, fnametmp, sizeof template);
143 - /* we initially set the perms without the
144 - * setuid/setgid bits to ensure that there is no race
145 - * condition. They are then correctly updated after
146 - * the lchown. Thanks to snabb@epipe.fi for pointing
147 - * this out. We also set it initially without group
148 - * access because of a similar race condition. */
149 - fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
151 - /* in most cases parent directories will already exist
152 - * because their information should have been previously
153 - * transferred, but that may not be the case with -R */
154 - if (fd2 == -1 && relative_paths && errno == ENOENT &&
155 - create_directory_path(fnametmp, orig_umask) == 0) {
156 - strlcpy(fnametmp, template, sizeof fnametmp);
157 + /* we initially set the perms without the
158 + * setuid/setgid bits to ensure that there is no race
159 + * condition. They are then correctly updated after
160 + * the lchown. Thanks to snabb@epipe.fi for pointing
161 + * this out. We also set it initially without group
162 + * access because of a similar race condition. */
163 fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
166 - rsyserr(FERROR, errno, "mkstemp %s failed",
167 - full_fname(fnametmp));
168 - receive_data(f_in,mapbuf,-1,NULL,file->length);
169 - if (mapbuf) unmap_file(mapbuf);
170 - if (fd1 != -1) close(fd1);
173 + /* in most cases parent directories will already exist
174 + * because their information should have been previously
175 + * transferred, but that may not be the case with -R */
176 + if (fd2 == -1 && relative_paths && errno == ENOENT
177 + && create_directory_path(fnametmp, orig_umask) == 0) {
178 + strlcpy(fnametmp, template, sizeof fnametmp);
179 + fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
182 + rsyserr(FERROR, errno, "mkstemp %s failed",
183 + full_fname(fnametmp));
184 + receive_data(f_in,mapbuf,-1,NULL,file->length);
185 + if (mapbuf) unmap_file(mapbuf);
186 + if (fd1 != -1) close(fd1);
191 cleanup_set(fnametmp, fname, file, mapbuf, fd1, fd2);
192 --- rsync.c 15 May 2004 19:31:10 -0000 1.139
193 +++ rsync.c 15 May 2004 20:23:19 -0000
194 @@ -31,6 +31,7 @@ extern int am_generator;
195 extern int preserve_uid;
196 extern int preserve_gid;
197 extern int make_backups;
202 @@ -235,6 +236,11 @@ void finish_transfer(char *fname, char *
204 if (make_backups && !make_backup(fname))
208 + set_perms(fname,file,NULL,0);
212 /* move tmp file over real file */
213 ret = robust_rename(fnametmp, fname, file->mode & INITACCESSPERMS);
214 --- rsync.yo 7 May 2004 00:18:37 -0000 1.169
215 +++ rsync.yo 15 May 2004 20:23:20 -0000
216 @@ -289,6 +289,7 @@ verb(
217 --backup-dir make backups into this directory
218 --suffix=SUFFIX backup suffix (default ~ w/o --backup-dir)
219 -u, --update update only (don't overwrite newer files)
220 + --inplace update the destination file inplace
221 -l, --links copy symlinks as symlinks
222 -L, --copy-links copy the referent of all symlinks
223 --copy-unsafe-links copy the referent of "unsafe" symlinks
224 @@ -477,6 +478,17 @@ is on the objects. In other words, if t
225 symlink where the destination has a file, the transfer would occur
226 regardless of the timestamps. This might change in the future (feel
227 free to comment on this on the mailing list if you have an opinion).
229 +dit(bf(--inplace)) This causes rsync not to create a new copy of the file
230 +and then move it into place. Instead rsync will overwrite the existing
231 +file, meaning that the rsync algorithm can't extract the full ammount of
232 +network reduction it might otherwise.
234 +This option is useful for transfer of large files with block based changes
235 +and also on systems that are disk bound not network bound.
237 +WARNING: If the transfer is interrupted, you will have an inconsistent file
238 +and the transfer should be run again.
240 dit(bf(-l, --links)) When symlinks are encountered, recreate the
241 symlink on the destination.