The improved --xattrs option is landing on the trunk.
[rsync/rsync.git] / options.c
index 0478749..c1423b6 100644 (file)
--- a/options.c
+++ b/options.c
@@ -3,12 +3,11 @@
  *
  * Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
  * Copyright (C) 2000, 2001, 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Wayne Davison
+ * Copyright (C) 2002-2007 Wayne Davison
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -47,6 +46,8 @@ int copy_dirlinks = 0;
 int copy_links = 0;
 int preserve_links = 0;
 int preserve_hard_links = 0;
+int preserve_acls = 0;
+int preserve_xattrs = 0;
 int preserve_perms = 0;
 int preserve_executability = 0;
 int preserve_devices = 0;
@@ -90,6 +91,7 @@ char *filesfrom_host = NULL;
 int eol_nulls = 0;
 int human_readable = 0;
 int recurse = 0;
+int allow_inc_recurse = 1;
 int xfer_dirs = -1;
 int am_daemon = 0;
 int daemon_over_rsh = 0;
@@ -199,6 +201,8 @@ static void print_rsync_version(enum logcode f)
        char const *got_socketpair = "no ";
        char const *have_inplace = "no ";
        char const *hardlinks = "no ";
+       char const *acls = "no ";
+       char const *xattrs = "no ";
        char const *links = "no ";
        char const *ipv6 = "no ";
        STRUCT_STAT *dumstat;
@@ -215,6 +219,12 @@ static void print_rsync_version(enum logcode f)
        hardlinks = "";
 #endif
 
+#ifdef SUPPORT_ACLS
+       acls = "";
+#endif
+#ifdef SUPPORT_XATTRS
+       xattrs = "";
+#endif
 #ifdef SUPPORT_LINKS
        links = "";
 #endif
@@ -233,8 +243,8 @@ static void print_rsync_version(enum logcode f)
                (int)(sizeof (int64) * 8));
        rprintf(f, "    %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
                got_socketpair, hardlinks, links, ipv6, have_inplace);
-       rprintf(f, "    %sappend\n",
-               have_inplace);
+       rprintf(f, "    %sappend, %sACLs, %sxattrs\n",
+               have_inplace, acls, xattrs);
 
 #ifdef MAINTAINER_MODE
        rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
@@ -280,7 +290,7 @@ void usage(enum logcode F)
   rprintf(F," -q, --quiet                 suppress non-error messages\n");
   rprintf(F,"     --no-motd               suppress daemon-mode MOTD (see manpage caveat)\n");
   rprintf(F," -c, --checksum              skip based on checksum, not mod-time & size\n");
-  rprintf(F," -a, --archive               archive mode; same as -rlptgoD (no -H)\n");
+  rprintf(F," -a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)\n");
   rprintf(F,"     --no-OPTION             turn off an implied OPTION (e.g. --no-D)\n");
   rprintf(F," -r, --recursive             recurse into directories\n");
   rprintf(F," -R, --relative              use relative path names\n");
@@ -302,6 +312,12 @@ void usage(enum logcode F)
   rprintf(F," -p, --perms                 preserve permissions\n");
   rprintf(F," -E, --executability         preserve the file's executability\n");
   rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
+#ifdef SUPPORT_ACLS
+  rprintf(F," -A, --acls                  preserve ACLs (implies --perms)\n");
+#endif
+#ifdef SUPPORT_XATTRS
+  rprintf(F," -X, --xattrs                preserve extended attributes (implies --perms)\n");
+#endif
   rprintf(F," -o, --owner                 preserve owner (super-user only)\n");
   rprintf(F," -g, --group                 preserve group\n");
   rprintf(F,"     --devices               preserve device files (super-user only)\n");
@@ -414,6 +430,10 @@ static struct poptOption long_options[] = {
   {"archive",         'a', POPT_ARG_NONE,   0, 'a', 0, 0 },
   {"recursive",       'r', POPT_ARG_VAL,    &recurse, 2, 0, 0 },
   {"no-recursive",     0,  POPT_ARG_VAL,    &recurse, 0, 0, 0 },
+  {"ir",               0,  POPT_ARG_VAL,    &allow_inc_recurse, 1, 0, 0 },
+  {"inc-recursive",    0,  POPT_ARG_VAL,    &allow_inc_recurse, 1, 0, 0 },
+  {"no-ir",            0,  POPT_ARG_VAL,    &allow_inc_recurse, 0, 0, 0 },
+  {"no-inc-recursive", 0,  POPT_ARG_VAL,    &allow_inc_recurse, 0, 0, 0 },
   {"no-r",             0,  POPT_ARG_VAL,    &recurse, 0, 0, 0 },
   {"dirs",            'd', POPT_ARG_VAL,    &xfer_dirs, 2, 0, 0 },
   {"no-dirs",          0,  POPT_ARG_VAL,    &xfer_dirs, 0, 0, 0 },
@@ -422,6 +442,12 @@ static struct poptOption long_options[] = {
   {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
   {"no-p",             0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
   {"executability",   'E', POPT_ARG_NONE,   &preserve_executability, 0, 0, 0 },
+  {"acls",            'A', POPT_ARG_NONE,   0, 'A', 0, 0 },
+  {"no-acls",          0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
+  {"no-A",             0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
+  {"xattrs",          'X', POPT_ARG_NONE,   0, 'X', 0, 0 },
+  {"no-xattrs",        0,  POPT_ARG_VAL,    &preserve_xattrs, 0, 0, 0 },
+  {"no-X",             0,  POPT_ARG_VAL,    &preserve_xattrs, 0, 0, 0 },
   {"times",           't', POPT_ARG_VAL,    &preserve_times, 1, 0, 0 },
   {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
   {"no-t",             0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
@@ -1093,6 +1119,35 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                        usage(FINFO);
                        exit_cleanup(0);
 
+               case 'A':
+#ifdef SUPPORT_ACLS
+                       preserve_acls = 1;
+                       preserve_perms = 1;
+                       break;
+#else
+                       /* FIXME: this should probably be ignored with a
+                        * warning and then countermeasures taken to
+                        * restrict group and other access in the presence
+                        * of any more restrictive ACLs, but this is safe
+                        * for now */
+                       snprintf(err_buf,sizeof(err_buf),
+                                 "ACLs are not supported on this %s\n",
+                                am_server ? "server" : "client");
+                       return 0;
+#endif
+
+               case 'X':
+#ifdef SUPPORT_XATTRS
+                       preserve_xattrs = 1;
+                       preserve_perms = 1;
+                       break;
+#else
+                       snprintf(err_buf,sizeof(err_buf),
+                                "extended attributes are not supported on this %s\n",
+                                am_server ? "server" : "client");
+                       return 0;
+#endif
+
                default:
                        /* A large opt value means that set_refuse_options()
                         * turned this option off. */
@@ -1288,10 +1343,10 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                snprintf(err_buf, sizeof err_buf,
                        "--suffix cannot be a null string without --backup-dir\n");
                return 0;
-       } else if (make_backups && delete_mode && !delete_excluded) {
-               snprintf(backup_dir_buf, sizeof backup_dir_buf,
+       } else if (make_backups && delete_mode && !delete_excluded && !am_server) {
+               snprintf(backup_dir_buf, sizeof backup_dir_buf,
                        "P *%s", backup_suffix);
-               parse_rule(&filter_list, backup_dir_buf, 0, 0);
+               parse_rule(&filter_list, backup_dir_buf, 0, 0);
        }
        if (make_backups && !backup_dir)
                omit_dir_times = 1;
@@ -1404,10 +1459,6 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                                clean_fname(partial_dir, 1);
                        if (!*partial_dir || strcmp(partial_dir, ".") == 0)
                                partial_dir = NULL;
-                       else if (*partial_dir != '/' && !am_server) {
-                               parse_rule(&filter_list, partial_dir,
-                                   MATCHFLG_NO_PREFIXES|MATCHFLG_DIRECTORY, 0);
-                       }
                        if (!partial_dir && refused_partial) {
                                create_refuse_error(refused_partial);
                                return 0;
@@ -1556,6 +1607,14 @@ void server_options(char **args,int *argc)
                argstr[x++] = 'p';
        else if (preserve_executability && am_sender)
                argstr[x++] = 'E';
+#ifdef SUPPORT_ACLS
+       if (preserve_acls)
+               argstr[x++] = 'A';
+#endif
+#ifdef SUPPORT_XATTRS
+       if (preserve_xattrs)
+               argstr[x++] = 'X';
+#endif
        if (recurse)
                argstr[x++] = 'r';
        if (always_checksum)