Fixed failed hunks.
[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     21 May 2004 09:03:09 -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   6 May 2004 21:08:01 -0000       1.148
25 +++ options.c   21 May 2004 09:03:09 -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 @@ -939,6 +945,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  21 May 2004 08:27:04 -0000      1.79
71 +++ receiver.c  21 May 2004 09:03:09 -0000
72 @@ -47,6 +47,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 @@ -252,16 +253,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 @@ -413,37 +426,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     21 May 2004 08:43:03 -0000      1.140
193 +++ rsync.c     21 May 2004 09:03:09 -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    7 May 2004 00:18:37 -0000       1.169
215 +++ rsync.yo    21 May 2004 09:03:10 -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 @@ -478,6 +479,17 @@ symlink where the destination has a file
225  regardless of the timestamps.  This might change in the future (feel
226  free to comment on this on the mailing list if you have an opinion).
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