Add --link-dest option from J.W. Schultz.
authorDavid Dykstra <dwd@samba.org>
Thu, 29 Aug 2002 14:44:55 +0000 (14:44 +0000)
committerDavid Dykstra <dwd@samba.org>
Thu, 29 Aug 2002 14:44:55 +0000 (14:44 +0000)
NEWS
generator.c
options.c
rsync.yo

diff --git a/NEWS b/NEWS
index 34e424f..fe1e75f 100644 (file)
--- 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)
 
     * 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
   BUG FIXES:
   
     * Fix "forward name lookup failed" errors on AIX 4.3.3.  (John
index dd3eef6..f3849a0 100644 (file)
@@ -41,6 +41,7 @@ extern int remote_version;
 extern int always_checksum;
 extern int modify_window;
 extern char *compare_dest;
 extern int always_checksum;
 extern int modify_window;
 extern char *compare_dest;
+extern int link_dest;
 
 
 /* choose whether to skip a particular file */
 
 
 /* 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 (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 */
        
        /* 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;
                        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;
        }
                else
                        fnamecmp = fnamecmpbuf;
        }
index 7ed8823..06b442c 100644 (file)
--- 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;
 char *rsync_path = RSYNC_PATH;
 char *backup_dir = NULL;
 int rsync_port = RSYNC_PORT;
+int link_dest = 0;
 
 int verbose = 0;
 int quiet = 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_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,
       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 },
   {"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 },
   /* 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;
                        /* 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
 
                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.
                 */
                 *   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;
        }
 
                args[ac++] = compare_dest;
        }
 
index 93b06f9..21d6962 100644 (file)
--- 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
      --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
  -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.
 
 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
 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