Implement --tweak, --no-tweak, --no-tweak-hlinked options.
[rsync/rsync.git] / options.c
index ac34a5c..54c94d8 100644 (file)
--- a/options.c
+++ b/options.c
@@ -30,7 +30,7 @@ extern int sanitize_paths;
 extern int daemon_over_rsh;
 extern unsigned int module_dirlen;
 extern struct filter_list_struct filter_list;
-extern struct filter_list_struct server_filter_list;
+extern struct filter_list_struct daemon_filter_list;
 
 int make_backups = 0;
 
@@ -121,6 +121,7 @@ int modify_window = 0;
 int blocking_io = -1;
 int checksum_seed = 0;
 int inplace = 0;
+int tweak_attrs = 2; /* 2 = always, 1 = if not hlinked, 0 = never */
 int delay_updates = 0;
 long block_size = 0; /* "long" because popt can't set an int32. */
 char *skip_compress = NULL;
@@ -329,6 +330,8 @@ void usage(enum logcode F)
   rprintf(F,"     --inplace               update destination files in-place (SEE MAN PAGE)\n");
   rprintf(F,"     --append                append data onto shorter files\n");
   rprintf(F,"     --append-verify         like --append, but with old data in file checksum\n");
+  rprintf(F,"     --no-tweak              recreate dest files instead of tweaking attrs\n");
+  rprintf(F,"     --no-tweak-hlinked      ... if they have multiple hard links\n");
   rprintf(F," -d, --dirs                  transfer directories without recursing\n");
   rprintf(F," -l, --links                 copy symlinks as symlinks\n");
   rprintf(F," -L, --copy-links            transform symlink into referent file/dir\n");
@@ -545,6 +548,9 @@ static struct poptOption long_options[] = {
   {"append",           0,  POPT_ARG_NONE,   0, OPT_APPEND, 0, 0 },
   {"append-verify",    0,  POPT_ARG_VAL,    &append_mode, 2, 0, 0 },
   {"no-append",        0,  POPT_ARG_VAL,    &append_mode, 0, 0, 0 },
+  {"no-tweak",         0,  POPT_ARG_VAL,    &tweak_attrs, 0, 0, 0 },
+  {"no-tweak-hlinked", 0,  POPT_ARG_VAL,    &tweak_attrs, 1, 0, 0 },
+  {"tweak",            0,  POPT_ARG_VAL,    &tweak_attrs, 2, 0, 0 },
   {"del",              0,  POPT_ARG_NONE,   &delete_during, 0, 0, 0 },
   {"delete",           0,  POPT_ARG_NONE,   &delete_mode, 0, 0, 0 },
   {"delete-before",    0,  POPT_ARG_NONE,   &delete_before, 0, 0, 0 },
@@ -1033,7 +1039,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        arg = poptGetOptArg(pc);
                        if (sanitize_paths)
                                arg = sanitize_path(NULL, arg, NULL, 0);
-                       if (server_filter_list.head) {
+                       if (daemon_filter_list.head) {
                                int rej;
                                char *dir, *cp = strdup(arg);
                                if (!cp)
@@ -1042,7 +1048,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                                        goto options_rejected;
                                dir = cp + (*cp == '/' ? module_dirlen : 0);
                                clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
-                               rej = check_filter(&server_filter_list, dir, 0) < 0;
+                               rej = check_filter(&daemon_filter_list, dir, 0) < 0;
                                free(cp);
                                if (rej)
                                        goto options_rejected;
@@ -1444,8 +1450,8 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                if (backup_dir)
                        backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
        }
-       if (server_filter_list.head && !am_sender) {
-               struct filter_list_struct *elp = &server_filter_list;
+       if (daemon_filter_list.head && !am_sender) {
+               struct filter_list_struct *elp = &daemon_filter_list;
                if (tmpdir) {
                        char *dir;
                        if (!*tmpdir)
@@ -1584,11 +1590,24 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                partial_dir = tmp_partialdir;
 
        if (inplace) {
+               char *inplace_opt = append_mode ? "append" : "inplace";
 #ifdef HAVE_FTRUNCATE
+               if (tweak_attrs == 0) {
+                       snprintf(err_buf, sizeof err_buf,
+                                       "--no-tweak controverts --%s.  Remove --%s.\n",
+                                       inplace_opt, inplace_opt);
+                       return 0;
+               }
+               if (tweak_attrs == 1) {
+                       snprintf(err_buf, sizeof err_buf,
+                                       "The combination of --no-tweak-hlinked and --%s is not implemented.\n",
+                                       inplace_opt);
+                       return 0;
+               }
                if (partial_dir) {
                        snprintf(err_buf, sizeof err_buf,
                                 "--%s cannot be used with --%s\n",
-                                append_mode ? "append" : "inplace",
+                                inplace_opt,
                                 delay_updates ? "delay-updates" : "partial-dir");
                        return 0;
                }
@@ -1602,7 +1621,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
 #else
                snprintf(err_buf, sizeof err_buf,
                         "--%s is not supported on this %s\n",
-                        append_mode ? "append" : "inplace",
+                        inplace_opt,
                         am_server ? "server" : "client");
                return 0;
 #endif
@@ -1651,13 +1670,13 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                } else {
                        if (sanitize_paths)
                                files_from = sanitize_path(NULL, files_from, NULL, 0);
-                       if (server_filter_list.head) {
+                       if (daemon_filter_list.head) {
                                char *dir;
                                if (!*files_from)
                                        goto options_rejected;
                                dir = files_from + (*files_from == '/' ? module_dirlen : 0);
                                clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
-                               if (check_filter(&server_filter_list, dir, 0) < 0)
+                               if (check_filter(&daemon_filter_list, dir, 0) < 0)
                                        goto options_rejected;
                        }
                        filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
@@ -1935,6 +1954,8 @@ void server_options(char **args, int *argc_p)
                        args[ac++] = "--super";
                if (size_only)
                        args[ac++] = "--size-only";
+               if (tweak_attrs != 2)
+                       args[ac++] = (tweak_attrs == 1) ? "--no-tweak-hlinked" : "--no-tweak";
        } else {
                if (skip_compress) {
                        if (asprintf(&arg, "--skip-compress=%s", skip_compress) < 0)