Patch from Mark Curtis.
[rsync/rsync-patches.git] / inplace.diff
CommitLineData
a2d23604
WD
1Patch from Mark Curtis to implement the --inplace option.
2
3--- match.c 3 Jan 2004 19:28:03 -0000 1.60
4+++ match.c 27 Apr 2004 23:26:09 -0000
5@@ -22,6 +22,7 @@
6 extern int verbose;
7 extern int am_server;
8 extern int do_progress;
9+extern int inplace;
10
11 typedef unsigned short tag;
12
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)
17+ continue;
18+
19+ /* if inplace, make sure the offset is greater than where we are */
20+ if (inplace && offset > s->sums[i].offset)
21 continue;
22
23 if (verbose > 3)
24--- options.c 17 Apr 2004 17:07:23 -0000 1.147
25+++ options.c 27 Apr 2004 23:26:10 -0000
26@@ -91,6 +91,7 @@ int ignore_errors = 0;
27 int modify_window = 0;
28 int blocking_io = -1;
29 int checksum_seed = 0;
30+int inplace = 0;
31 unsigned int block_size = 0;
32
33
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)
52 verbose = 1;
53
54+ if (inplace && keep_partial)
55+ keep_partial = 0;
56+
57 if (files_from) {
58 char *colon;
59 if (*argc != 2 && !(am_server && am_sender && *argc == 1)) {
60@@ -938,6 +944,9 @@ void server_options(char **args,int *arg
61
62 if (opt_ignore_existing && am_sender)
63 args[ac++] = "--ignore-existing";
64+
65+ if (inplace)
66+ args[ac++] = "--inplace";
67
68 if (tmpdir) {
69 args[ac++] = "--temp-dir";
70--- receiver.c 27 Apr 2004 19:51:33 -0000 1.76
71+++ receiver.c 27 Apr 2004 23:26:10 -0000
72@@ -45,6 +45,7 @@ extern int cleanup_got_literal;
73 extern int module_id;
74 extern int ignore_errors;
75 extern int orig_umask;
76+extern int inplace;
77
78 static void delete_one(char *fn, int is_dir)
79 {
80@@ -249,16 +250,28 @@ static int receive_data(int f_in,struct
81 sum_update(map,len);
82 }
83
84- if (fd != -1 && write_file(fd,map,len) != (int) len) {
85- rprintf(FERROR, "write failed on %s: %s\n",
86- full_fname(fname), strerror(errno));
87- exit_cleanup(RERR_FILEIO);
88+ if (!inplace || offset != offset2) {
89+ if (fd != -1 && write_file(fd,map,len) != (int) len) {
90+ rprintf(FERROR, "write failed on %s: %s\n",
91+ full_fname(fname), strerror(errno));
92+ exit_cleanup(RERR_FILEIO);
93+ }
94+ } else {
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);
100+ }
101 }
102 offset += len;
103 }
104
105 flush_write_file(fd);
106
107+ if (inplace)
108+ ftruncate(fd, offset);
109+
110 if (do_progress)
111 end_progress(total_size);
112
113@@ -410,37 +423,50 @@ int recv_files(int f_in,struct file_list
114 } else
115 mapbuf = NULL;
116
117- if (!get_tmpname(fnametmp,fname)) {
118- if (mapbuf) unmap_file(mapbuf);
119- if (fd1 != -1) close(fd1);
120- continue;
121- }
122+ /* We now check to see if we are writing file "inplace" */
123+ if (inplace) {
124+ fd2 = do_open(fnamecmp, O_WRONLY|O_CREAT, 0);
125+ if (fd2 == -1) {
126+ rprintf(FERROR, "open %s failed: %s\n",
127+ full_fname(fnametmp), strerror(errno));
128+ receive_data(f_in,mapbuf,-1,NULL,file->length);
129+ if (mapbuf) unmap_file(mapbuf);
130+ if (fd1 != -1) close(fd1);
131+ continue;
132+ }
133+ } else {
134+ if (!get_tmpname(fnametmp,fname)) {
135+ if (mapbuf) unmap_file(mapbuf);
136+ if (fd1 != -1) close(fd1);
137+ continue;
138+ }
139
140- strlcpy(template, fnametmp, sizeof template);
141+ strlcpy(template, fnametmp, sizeof template);
142
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);
150-
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);
164- }
165- if (fd2 == -1) {
166- rprintf(FERROR, "mkstemp %s failed: %s\n",
167- full_fname(fnametmp), strerror(errno));
168- receive_data(f_in,mapbuf,-1,NULL,file->length);
169- if (mapbuf) unmap_file(mapbuf);
170- if (fd1 != -1) close(fd1);
171- continue;
172+
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);
180+ }
181+ if (fd2 == -1) {
182+ rprintf(FERROR, "mkstemp %s failed: %s\n",
183+ full_fname(fnametmp), strerror(errno));
184+ receive_data(f_in,mapbuf,-1,NULL,file->length);
185+ if (mapbuf) unmap_file(mapbuf);
186+ if (fd1 != -1) close(fd1);
187+ continue;
188+ }
189 }
190
191 cleanup_set(fnametmp, fname, file, mapbuf, fd1, fd2);
192--- rsync.c 23 Mar 2004 16:16:15 -0000 1.135
193+++ rsync.c 27 Apr 2004 23:26:11 -0000
194@@ -33,6 +33,7 @@ extern int preserve_uid;
195 extern int preserve_gid;
196 extern int preserve_perms;
197 extern int make_backups;
198+extern int inplace;
199
200
201 /*
202@@ -234,6 +235,11 @@ void finish_transfer(char *fname, char *
203
204 if (make_backups && !make_backup(fname))
205 return;
206+
207+ if (inplace) {
208+ set_perms(fname,file,NULL,0);
209+ return;
210+ }
211
212 /* move tmp file over real file */
213 ret = robust_rename(fnametmp, fname, file->mode & INITACCESSPERMS);
214--- rsync.yo 27 Apr 2004 03:55:37 -0000 1.165
215+++ rsync.yo 27 Apr 2004 23:26:12 -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@@ -475,6 +476,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).
228+
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.
233+
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.
236+
237+WARNING: If the transfer is interrupted, you will have an inconsistent file
238+and the transfer should be run again.
239
240 dit(bf(-l, --links)) When symlinks are encountered, recreate the
241 symlink on the destination.