Merged in the g2r-basis-filename.diff changes so that the receiver
[rsync/rsync-patches.git] / inplace.diff
1 Patch from Mark Curtis to implement the --inplace option.
2
3 --- match.c     21 May 2004 08:27:04 -0000      1.62
4 +++ match.c     18 Jun 2004 17:27:29 -0000
5 @@ -23,6 +23,7 @@ extern int verbose;
6  extern int am_server;
7  extern int do_progress;
8  extern int checksum_seed;
9 +extern int inplace;
10  
11  typedef unsigned short tag;
12  
13 @@ -200,6 +201,10 @@ static void hash_search(int f,struct sum
14                         if (l != s->sums[i].len)
15                                 continue;
16  
17 +                       /* if inplace, make sure the offset is greater than where we are */
18 +                       if (inplace && offset > s->sums[i].offset)
19 +                               continue;
20 +
21                         if (verbose > 3)
22                                 rprintf(FINFO,"potential match at %.0f target=%.0f %.0f sum=%08x\n",
23                                         (double)offset,(double)j,(double)i,sum);
24 --- options.c   7 Jun 2004 22:05:22 -0000       1.156
25 +++ options.c   18 Jun 2004 17:27:29 -0000
26 @@ -94,6 +94,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 @@ -234,6 +235,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," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
40    rprintf(F," -l, --links                 copy symlinks as symlinks\n");
41    rprintf(F," -L, --copy-links            copy the referent of all symlinks\n");
42 @@ -341,6 +343,7 @@ static struct poptOption long_options[] 
43    {"sparse",          'S', POPT_ARG_NONE,   &sparse_files, 0, 0, 0 },
44    {"cvs-exclude",     'C', POPT_ARG_NONE,   &cvs_exclude, 0, 0, 0 },
45    {"update",          'u', POPT_ARG_NONE,   &update_only, 0, 0, 0 },
46 +  {"inplace",          0,  POPT_ARG_NONE,   &inplace, 0, 0, 0 },
47    {"keep-dirlinks",   'K', POPT_ARG_NONE,   &keep_dirlinks, 0, 0, 0 },
48    {"links",           'l', POPT_ARG_NONE,   &preserve_links, 0, 0, 0 },
49    {"copy-links",      'L', POPT_ARG_NONE,   &copy_links, 0, 0, 0 },
50 @@ -739,6 +742,9 @@ int parse_arguments(int *argc, const cha
51                         bwlimit_writemax = 512;
52         }
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 @@ -963,6 +969,9 @@ void server_options(char **args,int *arg
61         if (opt_ignore_existing && am_sender)
62                 args[ac++] = "--ignore-existing";
63  
64 +       if (inplace)
65 +               args[ac++] = "--inplace";
66 +
67         if (tmpdir) {
68                 args[ac++] = "--temp-dir";
69                 args[ac++] = tmpdir;
70 --- receiver.c  14 Jun 2004 15:09:36 -0000      1.82
71 +++ receiver.c  18 Jun 2004 17:27:30 -0000
72 @@ -48,6 +48,7 @@ extern int ignore_errors;
73  extern int orig_umask;
74  extern int keep_partial;
75  extern int checksum_seed;
76 +extern int inplace;
77  
78  static void delete_one(char *fn, int is_dir)
79  {
80 @@ -257,16 +258,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 -                       rsyserr(FERROR, errno, "write failed on %s",
86 -                               full_fname(fname));
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",
91 +                                       full_fname(fname));
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 @@ -418,37 +431,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 +                               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);
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 -                       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);
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 +                               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);
187 +                               continue;
188 +                       }
189                 }
190  
191                 cleanup_set(fnametmp, fname, file, mapbuf, fd1, fd2);
192 --- rsync.c     11 Jun 2004 07:40:45 -0000      1.141
193 +++ rsync.c     18 Jun 2004 17:27:30 -0000
194 @@ -34,6 +34,7 @@ extern int force_delete;
195  extern int recurse;
196  extern int make_backups;
197  extern char *backup_dir;
198 +extern int inplace;
199  
200  
201  /*
202 @@ -239,6 +240,11 @@ void finish_transfer(char *fname, char *
203         if (make_backups && !make_backup(fname))
204                 return;
205  
206 +       if (inplace) {
207 +               set_perms(fname,file,NULL,0);
208 +               return;
209 +       }
210 +
211         /* move tmp file over real file */
212         ret = robust_rename(fnametmp, fname, file->mode & INITACCESSPERMS);
213         if (ret < 0) {
214 --- rsync.yo    5 Jun 2004 16:16:30 -0000       1.171
215 +++ rsync.yo    18 Jun 2004 17:27:30 -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   -K, --keep-dirlinks         treat symlinked dir on receiver as dir
222   -l, --links                 copy symlinks as symlinks
223   -L, --copy-links            copy the referent of all symlinks
224 @@ -484,6 +485,17 @@ dit(bf(-K, --keep-dirlinks)) On the rece
225  pointing to a directory, it will be treated as matching a directory
226  from the sender.
227  
228 +dit(bf(--inplace)) This causes rsync not to create a new copy of the file
229 +and then move it into place.  Instead rsync will overwrite the existing
230 +file, meaning that the rsync algorithm can't extract the full ammount of
231 +network reduction it might otherwise.
232 +
233 +This option is useful for transfer of large files with block based changes
234 +and also on systems that are disk bound not network bound.
235 +
236 +WARNING: If the transfer is interrupted, you will have an inconsistent file
237 +and the transfer should be run again.
238 +
239  dit(bf(-l, --links)) When symlinks are encountered, recreate the
240  symlink on the destination.
241