From: Wayne Davison Date: Fri, 16 Jul 2004 20:07:06 +0000 (+0000) Subject: Has been applied to CVS. X-Git-Url: https://mattmccutchen.net/rsync/rsync-patches.git/commitdiff_plain/0a8bb8f452b4032dc5d4bce1bfe2dc10db117576 Has been applied to CVS. --- diff --git a/inplace.diff b/inplace.diff deleted file mode 100644 index 7200d2b..0000000 --- a/inplace.diff +++ /dev/null @@ -1,394 +0,0 @@ -Patch from Mark Curtis to implement the --inplace option. -Improved by Wayne Davison. - -Run these commands after applying the patch: - - autoconf - autoheader - ./configure - make - -Optional: - - make rsync.1 - ---- orig/configure.in 2004-04-30 18:04:07 -+++ configure.in 2004-07-03 20:19:54 -@@ -442,7 +442,7 @@ dnl AC_FUNC_MEMCMP - AC_FUNC_UTIME_NULL - AC_FUNC_ALLOCA - AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod mkfifo \ -- fchmod fstat strchr readlink link utime utimes strftime mtrace \ -+ fchmod fstat strchr readlink link utime utimes strftime mtrace ftruncate \ - memmove lchown vsnprintf snprintf asprintf setsid glob strpbrk \ - strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid) - ---- orig/match.c 2004-07-15 02:21:10 -+++ match.c 2004-07-16 19:39:08 -@@ -23,6 +23,7 @@ extern int verbose; - extern int am_server; - extern int do_progress; - extern int checksum_seed; -+extern int inplace; - - typedef unsigned short tag; - -@@ -200,6 +201,12 @@ static void hash_search(int f,struct sum - if (l != s->sums[i].len) - continue; - -+ /* inplace: ensure chunk's offset is either >= our -+ * offset or that the data didn't move. */ -+ if (inplace && s->sums[i].offset < offset -+ && !(s->sums[i].flags & SUMFLG_SAME_OFFSET)) -+ continue; -+ - if (verbose > 3) - rprintf(FINFO,"potential match at %.0f target=%.0f %.0f sum=%08x\n", - (double)offset,(double)j,(double)i,sum); -@@ -215,15 +222,41 @@ static void hash_search(int f,struct sum - continue; - } - -+ /* If inplace is enabled, the best possible match is -+ * one with an identical offset, so we prefer that over -+ * the following want_i optimization. */ -+ if (inplace) { -+ do { -+ size_t i2 = targets[j].i; -+ if (s->sums[i2].offset != offset) -+ continue; -+ if (i2 != i) { -+ if (sum != s->sums[i2].sum1) -+ break; -+ if (memcmp(sum2, s->sums[i2].sum2, -+ s->s2length) != 0) -+ break; -+ i = i2; -+ } -+ /* This chunk was at the same offset on -+ * both the sender and the receiver. */ -+ s->sums[i].flags |= SUMFLG_SAME_OFFSET; -+ goto set_want_i; -+ } while (++j < s->count && targets[j].t == t); -+ } -+ - /* we've found a match, but now check to see - * if want_i can hint at a better match. */ - if (i != want_i && want_i < s->count -+ && (!inplace || s->sums[want_i].offset >= offset -+ || s->sums[want_i].flags & SUMFLG_SAME_OFFSET) - && sum == s->sums[want_i].sum1 - && memcmp(sum2, s->sums[want_i].sum2, s->s2length) == 0) { - /* we've found an adjacent match - the RLL coder - * will be happy */ - i = want_i; - } -+ set_want_i: - want_i = i + 1; - - matched(f,s,buf,offset,i); ---- orig/options.c 2004-07-16 19:35:29 -+++ options.c 2004-07-03 20:19:54 -@@ -94,6 +94,7 @@ int ignore_errors = 0; - int modify_window = 0; - int blocking_io = -1; - int checksum_seed = 0; -+int inplace = 0; - unsigned int block_size = 0; - - -@@ -148,6 +149,7 @@ char *bind_address; - static void print_rsync_version(enum logcode f) - { - char const *got_socketpair = "no "; -+ char const *have_inplace = "no "; - char const *hardlinks = "no "; - char const *links = "no "; - char const *ipv6 = "no "; -@@ -157,6 +159,10 @@ static void print_rsync_version(enum log - got_socketpair = ""; - #endif - -+#if HAVE_FTRUNCATE -+ have_inplace = ""; -+#endif -+ - #if SUPPORT_HARD_LINKS - hardlinks = ""; - #endif -@@ -182,8 +188,8 @@ static void print_rsync_version(enum log - /* Note that this field may not have type ino_t. It depends - * on the complicated interaction between largefile feature - * macros. */ -- rprintf(f, " %sIPv6, %d-bit system inums, %d-bit internal inums\n", -- ipv6, -+ rprintf(f, " %sinplace, %sIPv6, %d-bit system inums, %d-bit internal inums\n", -+ have_inplace, ipv6, - (int) (sizeof dumstat->st_ino * 8), - (int) (sizeof (uint64) * 8)); - #ifdef MAINTAINER_MODE -@@ -233,6 +239,7 @@ void usage(enum logcode F) - rprintf(F," --backup-dir make backups into this directory\n"); - rprintf(F," --suffix=SUFFIX backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX); - rprintf(F," -u, --update update only (don't overwrite newer files)\n"); -+ rprintf(F," --inplace update the destination file inplace (see man page)\n"); - rprintf(F," -K, --keep-dirlinks treat symlinked dir on receiver as dir\n"); - rprintf(F," -l, --links copy symlinks as symlinks\n"); - rprintf(F," -L, --copy-links copy the referent of all symlinks\n"); -@@ -340,6 +347,7 @@ static struct poptOption long_options[] - {"sparse", 'S', POPT_ARG_NONE, &sparse_files, 0, 0, 0 }, - {"cvs-exclude", 'C', POPT_ARG_NONE, &cvs_exclude, 0, 0, 0 }, - {"update", 'u', POPT_ARG_NONE, &update_only, 0, 0, 0 }, -+ {"inplace", 0, POPT_ARG_NONE, &inplace, 0, 0, 0 }, - {"keep-dirlinks", 'K', POPT_ARG_NONE, &keep_dirlinks, 0, 0, 0 }, - {"links", 'l', POPT_ARG_NONE, &preserve_links, 0, 0, 0 }, - {"copy-links", 'L', POPT_ARG_NONE, ©_links, 0, 0, 0 }, -@@ -754,6 +762,18 @@ int parse_arguments(int *argc, const cha - bwlimit_writemax = 512; - } - -+ if (inplace) { -+#if HAVE_FTRUNCATE -+ if (keep_partial) -+ keep_partial = 0; -+#else -+ snprintf(err_buf, sizeof err_buf, -+ "inplace is not supported on this %s\n", -+ am_server ? "server" : "client"); -+ return 0; -+#endif -+ } -+ - if (files_from) { - char *colon; - if (*argc != 2 && !(am_server && am_sender && *argc == 1)) { -@@ -971,6 +991,9 @@ void server_options(char **args,int *arg - if (opt_ignore_existing && am_sender) - args[ac++] = "--ignore-existing"; - -+ if (inplace) -+ args[ac++] = "--inplace"; -+ - if (tmpdir) { - args[ac++] = "--temp-dir"; - args[ac++] = tmpdir; ---- orig/receiver.c 2004-07-14 17:12:06 -+++ receiver.c 2004-07-03 20:19:54 -@@ -48,6 +48,7 @@ extern int ignore_errors; - extern int orig_umask; - extern int keep_partial; - extern int checksum_seed; -+extern int inplace; - - static void delete_one(char *fn, int is_dir) - { -@@ -255,16 +256,30 @@ static int receive_data(int f_in,struct - sum_update(map,len); - } - -- if (fd != -1 && write_file(fd, map, len) != (int)len) { -- rsyserr(FERROR, errno, "write failed on %s", -- full_fname(fname)); -- exit_cleanup(RERR_FILEIO); -+ if (!inplace || offset != offset2) { -+ if (fd != -1 && write_file(fd, map, len) != (int)len) { -+ rsyserr(FERROR, errno, "write failed on %s", -+ full_fname(fname)); -+ exit_cleanup(RERR_FILEIO); -+ } -+ } else { -+ flush_write_file(fd); -+ if (do_lseek(fd,(OFF_T)len,SEEK_CUR) != offset+len) { -+ rprintf(FERROR, "lseek failed on %s: %s, %lli, %lli, %i\n", -+ full_fname(fname), strerror(errno), do_lseek(fd,0,SEEK_CUR), (offset+len), i); -+ exit_cleanup(RERR_FILEIO); -+ } - } - offset += len; - } - - flush_write_file(fd); - -+#ifdef HAVE_FTRUNCATE -+ if (inplace) -+ ftruncate(fd, offset); -+#endif -+ - if (do_progress) - end_progress(total_size); - -@@ -414,44 +429,59 @@ int recv_files(int f_in, struct file_lis - } else - mapbuf = NULL; - -- if (!get_tmpname(fnametmp,fname)) { -- if (mapbuf) -- unmap_file(mapbuf); -- if (fd1 != -1) -- close(fd1); -- continue; -- } -+ /* We now check to see if we are writing file "inplace" */ -+ if (inplace) { -+ fd2 = do_open(fnamecmp, O_WRONLY|O_CREAT, 0); -+ if (fd2 == -1) { -+ rsyserr(FERROR, errno, "open %s failed", -+ full_fname(fnamecmp)); -+ receive_data(f_in,mapbuf,-1,NULL,file->length); -+ if (mapbuf) -+ unmap_file(mapbuf); -+ if (fd1 != -1) -+ close(fd1); -+ continue; -+ } -+ } else { -+ if (!get_tmpname(fnametmp,fname)) { -+ if (mapbuf) -+ unmap_file(mapbuf); -+ if (fd1 != -1) -+ close(fd1); -+ continue; -+ } - -- strlcpy(template, fnametmp, sizeof template); -+ strlcpy(template, fnametmp, sizeof template); - -- /* we initially set the perms without the -- * setuid/setgid bits to ensure that there is no race -- * condition. They are then correctly updated after -- * the lchown. Thanks to snabb@epipe.fi for pointing -- * this out. We also set it initially without group -- * access because of a similar race condition. */ -- fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS); -- -- /* in most cases parent directories will already exist -- * because their information should have been previously -- * transferred, but that may not be the case with -R */ -- if (fd2 == -1 && relative_paths && errno == ENOENT && -- create_directory_path(fnametmp, orig_umask) == 0) { -- strlcpy(fnametmp, template, sizeof fnametmp); -+ /* we initially set the perms without the -+ * setuid/setgid bits to ensure that there is no race -+ * condition. They are then correctly updated after -+ * the lchown. Thanks to snabb@epipe.fi for pointing -+ * this out. We also set it initially without group -+ * access because of a similar race condition. */ - fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS); -- } -- if (fd2 == -1) { -- rsyserr(FERROR, errno, "mkstemp %s failed", -- full_fname(fnametmp)); -- receive_data(f_in,mapbuf,-1,NULL,file->length); -- if (mapbuf) -- unmap_file(mapbuf); -- if (fd1 != -1) -- close(fd1); -- continue; -- } - -- cleanup_set(fnametmp, fname, file, mapbuf, fd1, fd2); -+ /* in most cases parent directories will already exist -+ * because their information should have been previously -+ * transferred, but that may not be the case with -R */ -+ if (fd2 == -1 && relative_paths && errno == ENOENT -+ && create_directory_path(fnametmp, orig_umask) == 0) { -+ strlcpy(fnametmp, template, sizeof fnametmp); -+ fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS); -+ } -+ if (fd2 == -1) { -+ rsyserr(FERROR, errno, "mkstemp %s failed", -+ full_fname(fnametmp)); -+ receive_data(f_in,mapbuf,-1,NULL,file->length); -+ if (mapbuf) -+ unmap_file(mapbuf); -+ if (fd1 != -1) -+ close(fd1); -+ continue; -+ } -+ -+ cleanup_set(fnametmp, fname, file, mapbuf, fd1, fd2); -+ } - - if (!am_server && verbose) - rprintf(FINFO, "%s\n", fname); ---- orig/rsync.c 2004-07-02 18:06:32 -+++ rsync.c 2004-07-03 20:19:54 -@@ -34,6 +34,7 @@ extern int force_delete; - extern int recurse; - extern int make_backups; - extern char *backup_dir; -+extern int inplace; - - - /* -@@ -239,6 +240,13 @@ void finish_transfer(char *fname, char * - if (make_backups && !make_backup(fname)) - return; - -+ if (inplace) { -+ if (verbose > 2) -+ rprintf(FINFO, "finishing %s\n", fname); -+ set_perms(fname, file, NULL, 0); -+ return; -+ } -+ - /* move tmp file over real file */ - if (verbose > 2) - rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname); ---- orig/rsync.h 2004-07-07 08:27:00 -+++ rsync.h 2004-07-16 19:36:20 -@@ -458,11 +458,13 @@ struct file_list { - struct file_struct **files; - }; - -+#define SUMFLG_SAME_OFFSET (1<<0) -+ - struct sum_buf { - OFF_T offset; /**< offset in file of this chunk */ - unsigned int len; /**< length of chunk of file */ -- int i; /**< index of this chunk */ - uint32 sum1; /**< simple checksum */ -+ short flags; /**< flag bits */ - char sum2[SUM_LENGTH]; /**< checksum */ - }; - ---- orig/rsync.yo 2004-07-16 19:35:29 -+++ rsync.yo 2004-07-03 20:19:55 -@@ -289,6 +289,7 @@ verb( - --backup-dir make backups into this directory - --suffix=SUFFIX backup suffix (default ~ w/o --backup-dir) - -u, --update update only (don't overwrite newer files) -+ --inplace update the destination file inplace - -K, --keep-dirlinks treat symlinked dir on receiver as dir - -l, --links copy symlinks as symlinks - -L, --copy-links copy the referent of all symlinks -@@ -484,6 +485,17 @@ dit(bf(-K, --keep-dirlinks)) On the rece - pointing to a directory, it will be treated as matching a directory - from the sender. - -+dit(bf(--inplace)) This causes rsync not to create a new copy of the file -+and then move it into place. Instead rsync will overwrite the existing -+file, meaning that the rsync algorithm can't extract the full ammount of -+network reduction it might otherwise. -+ -+This option is useful for transfer of large files with block based changes -+and also on systems that are disk bound not network bound. -+ -+WARNING: If the transfer is interrupted, you will have an inconsistent file -+and the transfer should be run again. -+ - dit(bf(-l, --links)) When symlinks are encountered, recreate the - symlink on the destination. - ---- orig/sender.c 2004-07-15 02:21:11 -+++ sender.c 2004-07-16 19:40:59 -@@ -85,7 +85,7 @@ static struct sum_struct *receive_sums(i - read_buf(f, s->sums[i].sum2, s->s2length); - - s->sums[i].offset = offset; -- s->sums[i].i = i; -+ s->sums[i].flags = 0; - - if (i == (int) s->count-1 && s->remainder != 0) { - s->sums[i].len = s->remainder;