7e273ea88ab538671402bb67e85aa9a6a5f2be0d
[rsync/rsync-patches.git] / inplace.diff
1 Patch 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.