From 59c95e4243749273fe91f8197a39f89e4d905cb8 Mon Sep 17 00:00:00 2001 From: David Dykstra Date: Thu, 29 Aug 2002 14:44:55 +0000 Subject: [PATCH] Add --link-dest option from J.W. Schultz. --- NEWS | 4 ++++ generator.c | 22 ++++++++++++++++++++++ options.c | 19 +++++++++++++++++-- rsync.yo | 6 ++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 34e424ff..fe1e75f1 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,10 @@ rsync changes since last release * If the file name given to --include-from or --exclude-from is "-", rsync will read from standard input. (J.W. Schultz) + * New option --link-dest which is like --compare-dest except that + unchanged files are hard-linked in to the destination directory. + (J.W. Schultz) + BUG FIXES: * Fix "forward name lookup failed" errors on AIX 4.3.3. (John diff --git a/generator.c b/generator.c index dd3eef66..f3849a07 100644 --- a/generator.c +++ b/generator.c @@ -41,6 +41,7 @@ extern int remote_version; extern int always_checksum; extern int modify_window; extern char *compare_dest; +extern int link_dest; /* choose whether to skip a particular file */ @@ -50,6 +51,15 @@ static int skip_file(char *fname, if (st->st_size != file->length) { return 0; } + if (link_dest) { + if((st->st_mode & ~_S_IFMT) != (file->mode & ~_S_IFMT)) { + return 0; + } + if (st->st_uid != file->uid || st->st_gid != file->gid) { + return 0; + } + } + /* if always checksum is set then we use the checksum instead of the file time to determine whether to sync */ @@ -356,6 +366,18 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out) statret = -1; if (statret == -1) errno = saveerrno; +#if HAVE_LINK + else if (link_dest && !dry_run) { + if (do_link(fnamecmpbuf, fname) != 0) { + if (verbose > 0) + rprintf(FINFO,"link %s => %s : %s\n", + fnamecmpbuf, + fname, + strerror(errno)); + } + fnamecmp = fnamecmpbuf; + } +#endif else fnamecmp = fnamecmpbuf; } diff --git a/options.c b/options.c index 7ed88232..06b442c8 100644 --- a/options.c +++ b/options.c @@ -115,6 +115,7 @@ char *password_file = NULL; char *rsync_path = RSYNC_PATH; char *backup_dir = NULL; int rsync_port = RSYNC_PORT; +int link_dest = 0; int verbose = 0; int quiet = 0; @@ -289,7 +290,7 @@ enum {OPT_VERSION = 1000, OPT_SUFFIX, OPT_SENDER, OPT_SERVER, OPT_EXCLUDE, OPT_EXCLUDE_FROM, OPT_DELETE, OPT_DELETE_EXCLUDED, OPT_NUMERIC_IDS, OPT_RSYNC_PATH, OPT_FORCE, OPT_TIMEOUT, OPT_DAEMON, OPT_CONFIG, OPT_PORT, OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL, OPT_PROGRESS, - OPT_COPY_UNSAFE_LINKS, OPT_SAFE_LINKS, OPT_COMPARE_DEST, + OPT_COPY_UNSAFE_LINKS, OPT_SAFE_LINKS, OPT_COMPARE_DEST, OPT_LINK_DEST, OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS, OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR, OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO, @@ -348,6 +349,7 @@ static struct poptOption long_options[] = { {"timeout", 0, POPT_ARG_INT, &io_timeout , 0, 0, 0 }, {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir , 0, 0, 0 }, {"compare-dest", 0, POPT_ARG_STRING, &compare_dest , 0, 0, 0 }, + {"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 }, /* TODO: Should this take an optional int giving the compression level? */ {"compress", 'z', POPT_ARG_NONE, &do_compression , 0, 0, 0 }, {"daemon", 0, POPT_ARG_NONE, &am_daemon , 0, 0, 0 }, @@ -591,6 +593,19 @@ int parse_arguments(int *argc, const char ***argv, int frommain) /* popt stores the filename in batch_prefix for us */ read_batch = 1; break; + case OPT_LINK_DEST: +#if HAVE_LINK + compare_dest = poptGetOptArg(pc); + link_dest = 1; + break; +#else + snprintf(err_buf,sizeof(err_buf), + "hard links are not supported on this %s\n", + am_server ? "server" : "client"); + rprintf(FERROR,"ERROR: hard links not supported on this platform\n"); + return 0; +#endif + default: /* FIXME: If --daemon is specified, then errors for later @@ -827,7 +842,7 @@ void server_options(char **args,int *argc) * and it may be an older version that doesn't know this * option, so don't send it if client is the sender. */ - args[ac++] = "--compare-dest"; + args[ac++] = link_dest ? "--link-dest" : "--compare-dest"; args[ac++] = compare_dest; } diff --git a/rsync.yo b/rsync.yo index 93b06f92..21d69624 100644 --- a/rsync.yo +++ b/rsync.yo @@ -324,6 +324,7 @@ verb( --modify-window=NUM Timestamp window (seconds) for file match (default=0) -T --temp-dir=DIR create temporary files in directory DIR --compare-dest=DIR also compare destination files relative to DIR + --link-dest=DIR create hardlinks to DIR for unchanged files -P equivalent to --partial --progress -z, --compress compress file data --exclude=PATTERN exclude files matching PATTERN @@ -686,6 +687,11 @@ files that haven't changed). This option increases the usefulness of temporary destination until they have a chance to be completed. If DIR is a relative path, it is relative to the destination directory. +dit(bf(--link-dest=DIR)) This option behaves like bf(--compare-dest) but +also will create hard links from em(DIR) to the destination directory for +unchanged files. Files with changed ownership or permissions will not be +linked. + dit(bf(-z, --compress)) With this option, rsync compresses any data from the files that it sends to the destination machine. This option is useful on slow links. The compression method used is the -- 2.34.1