| 1 | Patch from Mark Curtis to implement the --inplace option. |
| 2 | |
| 3 | --- match.c 13 May 2004 06:46:20 -0000 1.61 |
| 4 | +++ match.c 15 May 2004 20:23:18 -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 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; |
| 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 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; |
| 76 | +extern int inplace; |
| 77 | |
| 78 | static void delete_one(char *fn, int is_dir) |
| 79 | { |
| 80 | @@ -251,16 +252,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 | @@ -412,37 +425,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 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; |
| 198 | +extern int inplace; |
| 199 | |
| 200 | |
| 201 | /* |
| 202 | @@ -235,6 +236,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 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). |
| 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. |