The patches for 3.2.2.
[rsync-patches.git] / filter-attribute-mods.diff
index d7c1ebb86c930e1d00722e52e2b3014b35e5451e..5616bb68cf836fa34664a10d1fd613c5eb8692e2 100644 (file)
@@ -9,11 +9,11 @@ To use this patch, run these commands for a successful build:
     ./configure                         (optional if already run)
     make
 
-based-on: 1c82a1e1e54eb585cd37c875604193f5b977d24e
+based-on: 194cee671d5e178f20c4494f41911fa8db942935
 diff --git a/exclude.c b/exclude.c
 --- a/exclude.c
 +++ b/exclude.c
-@@ -44,10 +44,13 @@ filter_rule_list filter_list = { .debug_type = "" };
+@@ -46,10 +46,13 @@ filter_rule_list filter_list = { .debug_type = "" };
  filter_rule_list cvs_filter_list = { .debug_type = " [global CVS]" };
  filter_rule_list daemon_filter_list = { .debug_type = " [daemon]" };
  
@@ -29,7 +29,7 @@ diff --git a/exclude.c b/exclude.c
  
  #define SLASH_WILD3_SUFFIX "/***"
  
-@@ -126,8 +129,27 @@ static void teardown_mergelist(filter_rule *ex)
+@@ -128,8 +131,27 @@ static void teardown_mergelist(filter_rule *ex)
                mergelist_cnt--;
  }
  
@@ -57,7 +57,7 @@ diff --git a/exclude.c b/exclude.c
        if (ex->rflags & FILTRULE_PERDIR_MERGE)
                teardown_mergelist(ex);
        free(ex->pattern);
-@@ -729,7 +751,9 @@ static void report_filter_result(enum logcode code, char const *name,
+@@ -723,7 +745,9 @@ static void report_filter_result(enum logcode code, char const *name,
  
  /* This function is used to check if a file should be included/excluded
   * from the list of files based on its name and type etc.  The value of
@@ -68,7 +68,7 @@ diff --git a/exclude.c b/exclude.c
  int name_is_excluded(const char *fname, int name_flags, int filter_level)
  {
        if (daemon_filter_list.head && check_filter(&daemon_filter_list, FLOG, fname, name_flags) < 0) {
-@@ -738,6 +762,9 @@ int name_is_excluded(const char *fname, int name_flags, int filter_level)
+@@ -732,6 +756,9 @@ int name_is_excluded(const char *fname, int name_flags, int filter_level)
                return 1;
        }
  
@@ -78,7 +78,7 @@ diff --git a/exclude.c b/exclude.c
        if (filter_level != ALL_FILTERS)
                return 0;
  
-@@ -748,7 +775,8 @@ int name_is_excluded(const char *fname, int name_flags, int filter_level)
+@@ -742,7 +769,8 @@ int name_is_excluded(const char *fname, int name_flags, int filter_level)
  }
  
  /* Return -1 if file "name" is defined to be excluded by the specified
@@ -88,7 +88,7 @@ diff --git a/exclude.c b/exclude.c
  int check_filter(filter_rule_list *listp, enum logcode code,
                 const char *name, int name_flags)
  {
-@@ -771,10 +799,12 @@ int check_filter(filter_rule_list *listp, enum logcode code,
+@@ -765,10 +793,12 @@ int check_filter(filter_rule_list *listp, enum logcode code,
                }
                if (rule_matches(name, ent, name_flags)) {
                        report_filter_result(code, name, ent, name_flags, listp->debug_type);
@@ -101,7 +101,7 @@ diff --git a/exclude.c b/exclude.c
        return 0;
  }
  
-@@ -791,9 +821,46 @@ static const uchar *rule_strcmp(const uchar *str, const char *rule, int rule_len
+@@ -785,9 +815,45 @@ static const uchar *rule_strcmp(const uchar *str, const char *rule, int rule_len
        return NULL;
  }
  
@@ -134,8 +134,7 @@ diff --git a/exclude.c b/exclude.c
 +      if (!parse_chmod(modestr, &modes))
 +              return NULL;
 +
-+      if (!(chmod = new(struct filter_chmod_struct)))
-+              out_of_memory("make_chmod_struct");
++      chmod = new(struct filter_chmod_struct);
 +      chmod->ref_cnt = 1;
 +      chmod->modestr = modestr;
 +      chmod->modes = modes;
@@ -149,7 +148,7 @@ diff --git a/exclude.c b/exclude.c
  
  /* Gets the next include/exclude rule from *rulestr_ptr and advances
   * *rulestr_ptr to point beyond it.  Stores the pattern's start (within
-@@ -808,6 +875,7 @@ static filter_rule *parse_rule_tok(const char **rulestr_ptr,
+@@ -802,6 +868,7 @@ static filter_rule *parse_rule_tok(const char **rulestr_ptr,
                                   const char **pat_ptr, unsigned int *pat_len_ptr)
  {
        const uchar *s = (const uchar *)*rulestr_ptr;
@@ -157,7 +156,7 @@ diff --git a/exclude.c b/exclude.c
        filter_rule *rule;
        unsigned int len;
  
-@@ -827,6 +895,12 @@ static filter_rule *parse_rule_tok(const char **rulestr_ptr,
+@@ -820,6 +887,12 @@ static filter_rule *parse_rule_tok(const char **rulestr_ptr,
        /* Inherit from the template.  Don't inherit FILTRULES_SIDES; we check
         * that later. */
        rule->rflags = template->rflags & FILTRULES_FROM_CONTAINER;
@@ -170,7 +169,7 @@ diff --git a/exclude.c b/exclude.c
  
        /* Figure out what kind of a filter rule "s" is pointing at.  Note
         * that if FILTRULE_NO_PREFIXES is set, the rule is either an include
-@@ -972,11 +1046,63 @@ static filter_rule *parse_rule_tok(const char **rulestr_ptr,
+@@ -965,11 +1038,63 @@ static filter_rule *parse_rule_tok(const char **rulestr_ptr,
                                        goto invalid;
                                rule->rflags |= FILTRULE_EXCLUDE_SELF;
                                break;
@@ -234,7 +233,7 @@ diff --git a/exclude.c b/exclude.c
                        case 'p':
                                rule->rflags |= FILTRULE_PERISHABLE;
                                break;
-@@ -1301,6 +1427,23 @@ char *get_rule_prefix(filter_rule *rule, const char *pat, int for_xfer,
+@@ -1283,6 +1408,23 @@ char *get_rule_prefix(filter_rule *rule, const char *pat, int for_xfer,
                else if (am_sender)
                        return NULL;
        }
@@ -261,7 +260,7 @@ diff --git a/exclude.c b/exclude.c
 diff --git a/flist.c b/flist.c
 --- a/flist.c
 +++ b/flist.c
-@@ -82,6 +82,7 @@ extern struct chmod_mode_struct *chmod_modes;
+@@ -83,6 +83,7 @@ extern struct chmod_mode_struct *chmod_modes;
  
  extern filter_rule_list filter_list;
  extern filter_rule_list daemon_filter_list;
@@ -269,7 +268,7 @@ diff --git a/flist.c b/flist.c
  
  #ifdef ICONV_OPTION
  extern int filesfrom_convert;
-@@ -1156,7 +1157,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1178,7 +1179,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
        } else if (readlink_stat(thisname, &st, linkname) != 0) {
                int save_errno = errno;
                /* See if file is excluded before reporting an error. */
@@ -278,7 +277,7 @@ diff --git a/flist.c b/flist.c
                 && (is_excluded(thisname, 0, filter_level)
                  || is_excluded(thisname, 1, filter_level))) {
                        if (ignore_perishable && save_errno != ENOENT)
-@@ -1201,6 +1202,12 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1223,6 +1224,12 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
  
        if (filter_level == NO_FILTERS)
                goto skip_filters;
@@ -291,7 +290,7 @@ diff --git a/flist.c b/flist.c
  
        if (S_ISDIR(st.st_mode)) {
                if (!xfer_dirs) {
-@@ -1403,12 +1410,23 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
+@@ -1439,12 +1446,23 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
                                          int flags, int filter_level)
  {
        struct file_struct *file;
@@ -316,7 +315,7 @@ diff --git a/flist.c b/flist.c
                file->mode = tweak_mode(file->mode, chmod_modes);
  
        if (f >= 0) {
-@@ -2302,7 +2320,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
+@@ -2345,7 +2363,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                        struct file_struct *file;
                        file = send_file_name(f, flist, fbuf, &st,
                                              FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags,
@@ -325,7 +324,7 @@ diff --git a/flist.c b/flist.c
                        if (!file)
                                continue;
                        if (inc_recurse) {
-@@ -2316,7 +2334,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
+@@ -2359,7 +2377,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                        } else
                                send_if_directory(f, flist, file, fbuf, len, flags);
                } else
@@ -334,10 +333,64 @@ diff --git a/flist.c b/flist.c
        }
  
        if (reenable_multiplex >= 0)
+diff --git a/rsync.1.md b/rsync.1.md
+--- a/rsync.1.md
++++ b/rsync.1.md
+@@ -1247,7 +1247,9 @@ your home directory (remove the '=' for that).
+     >     --chmod=D2775,F664
+     It is also legal to specify multiple `--chmod` options, as each additional
+-    option is just appended to the list of changes to make.
++    option is just appended to the list of changes to make.  To change
++    permissions of files matching a pattern, use an include filter with the `m`
++    modifier, which takes effect before any `--chmod` options.
+     See the `--perms` and `--executability` options for how the resulting
+     permission value can be applied to the files in the transfer.
+@@ -2548,6 +2550,10 @@ your home directory (remove the '=' for that).
+     If you specify "`--chown=foo:bar`", this is exactly the same as specifying
+     "`--usermap=*:foo --groupmap=*:bar`", only easier.
++    To change ownership of files matching a pattern, use an include filter with
++    the `o` and `g` modifiers, which take effect before uid/gid mapping and
++    therefore em(can) be mixed with `--usermap` and `--groupmap`.
++
+ 0.  `--timeout=SECONDS`
+     This option allows you to set a maximum I/O timeout in seconds.  If no data
+@@ -3499,6 +3505,15 @@ The following modifiers are accepted after a "`+`" or "`-`":
+   rules that exclude things like "CVS" and "`*.o`" are marked as perishable,
+   and will not prevent a directory that was removed on the source from being
+   deleted on the destination.
++- An `m+nop()(CHMOD)` on an include rule tweaks the permissions of matching
++  source files in the same way as `--chmod`.  This happens before any tweaks
++  requested via `--chmod` options.
++- An `o+nop()(USER)` on an include rule pretends that matching source files are
++  owned by `USER` (a name or numeric uid).  This happens before any uid mapping
++  by name or `--usermap`.
++- A `g+nop()(GROUP)` on an include rule pretends that matching source files are
++  owned by `GROUP` (a name or numeric gid).  This happens before any gid
++  mapping by name or `--groupmap`.
+ - An `x` indicates that a rule affects xattr names in xattr copy/delete
+   operations (and is thus ignored when matching file/dir names).  If no
+   xattr-matching rules are specified, a default xattr filtering rule is used
+@@ -3556,6 +3571,12 @@ The following modifiers are accepted after a merge or dir-merge rule:
+   rules in the file must not specify sides (via a modifier or a rule prefix
+   such as `hide`).
++The attribute-affecting modifiers `m`, `o`, and `g` work only in client filters
++(not in daemon filters), and only the modifiers of the first matching rule are
++applied.  As an example, assuming `--super` is enabled, the rule
++"`+o+nop()(root)g+nop()(root)m+nop()(go=) *~`" would ensure that all "backup"
++files belong to root and are not accessible to anyone else.
++
+ Per-directory rules are inherited in all subdirectories of the directory where
+ the merge-file was found unless the 'n' modifier was used.  Each subdirectory's
+ rules are prefixed to the inherited per-directory rules from its parents, which
 diff --git a/rsync.h b/rsync.h
 --- a/rsync.h
 +++ b/rsync.h
-@@ -158,6 +158,9 @@
+@@ -171,6 +171,9 @@
  #define NO_FILTERS    0
  #define SERVER_FILTERS        1
  #define ALL_FILTERS   2
@@ -347,7 +400,7 @@ diff --git a/rsync.h b/rsync.h
  
  #define XFLG_FATAL_ERRORS     (1<<0)
  #define XFLG_OLD_PREFIXES     (1<<1)
-@@ -866,6 +869,8 @@ struct map_struct {
+@@ -920,6 +923,8 @@ struct map_struct {
        int status;             /* first errno from read errors         */
  };
  
@@ -356,7 +409,7 @@ diff --git a/rsync.h b/rsync.h
  #define NAME_IS_FILE          (0)    /* filter name as a file */
  #define NAME_IS_DIR           (1<<0) /* filter name as a dir */
  #define NAME_IS_XATTR         (1<<2) /* filter name as an xattr */
-@@ -891,8 +896,18 @@ struct map_struct {
+@@ -945,8 +950,18 @@ struct map_struct {
  #define FILTRULE_CLEAR_LIST   (1<<18)/* this item is the "!" token */
  #define FILTRULE_PERISHABLE   (1<<19)/* perishable if parent dir goes away */
  #define FILTRULE_XATTR                (1<<20)/* rule only applies to xattr names */
@@ -375,7 +428,7 @@ diff --git a/rsync.h b/rsync.h
  
  typedef struct filter_struct {
        struct filter_struct *next;
-@@ -902,6 +917,11 @@ typedef struct filter_struct {
+@@ -956,6 +971,11 @@ typedef struct filter_struct {
                int slash_cnt;
                struct filter_list_struct *mergelist;
        } u;
@@ -387,62 +440,10 @@ diff --git a/rsync.h b/rsync.h
  } filter_rule;
  
  typedef struct filter_list_struct {
-diff --git a/rsync.yo b/rsync.yo
---- a/rsync.yo
-+++ b/rsync.yo
-@@ -1185,6 +1185,8 @@ quote(--chmod=D2775,F664)
- It is also legal to specify multiple bf(--chmod) options, as each
- additional option is just appended to the list of changes to make.
-+To change permissions of files matching a pattern, use an include filter with
-+the bf(m) modifier, which takes effect before any bf(--chmod) options.
- See the bf(--perms) and bf(--executability) options for how the resulting
- permission value can be applied to the files in the transfer.
-@@ -2157,6 +2159,10 @@ be omitted, but if USER is empty, a leading colon must be supplied.
- If you specify "--chown=foo:bar, this is exactly the same as specifying
- "--usermap=*:foo --groupmap=*:bar", only easier.
-+To change ownership of files matching a pattern, use an include filter with
-+the bf(o) and bf(g) modifiers, which take effect before uid/gid mapping and
-+therefore em(can) be mixed with bf(--usermap) and bf(--groupmap).
-+
- dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum I/O
- timeout in seconds. If no data is transferred for the specified time
- then rsync will exit. The default is 0, which means no timeout.
-@@ -3039,6 +3045,15 @@ itemization(
-   option's default rules that exclude things like "CVS" and "*.o" are
-   marked as perishable, and will not prevent a directory that was removed
-   on the source from being deleted on the destination.
-+  it() An bf(m+nop()(CHMOD)) on an include rule tweaks the permissions of matching
-+  source files in the same way as bf(--chmod).  This happens before any
-+  tweaks requested via bf(--chmod) options.
-+  it() An bf(o+nop()(USER)) on an include rule pretends that matching source files
-+  are owned by bf(USER) (a name or numeric uid).  This happens before any uid
-+  mapping by name or bf(--usermap).
-+  it() A bf(g+nop()(GROUP)) on an include rule pretends that matching source files
-+  are owned by bf(GROUP) (a name or numeric gid).  This happens before any gid
-+  mapping by name or bf(--groupmap).
-   it() An bf(x) indicates that a rule affects xattr names in xattr copy/delete
-   operations (and is thus ignored when matching file/dir names). If no
-   xattr-matching rules are specified, a default xattr filtering rule is
-@@ -3104,6 +3119,12 @@ itemization(
-   a rule prefix such as bf(hide)).
- )
-+The attribute-affecting modifiers bf(m), bf(o), and bf(g) work only in client
-+filters (not in daemon filters), and only the modifiers of the first matching
-+rule are applied.  As an example, assuming bf(--super) is enabled, the
-+rule "+o+nop()(root)g+nop()(root)m+nop()(go=) *~" would ensure that all "backup" files belong to
-+root and are not accessible to anyone else.
-+
- Per-directory rules are inherited in all subdirectories of the directory
- where the merge-file was found unless the 'n' modifier was used.  Each
- subdirectory's rules are prefixed to the inherited per-directory rules
 diff --git a/util.c b/util.c
 --- a/util.c
 +++ b/util.c
-@@ -885,6 +885,25 @@ size_t stringjoin(char *dest, size_t destsize, ...)
+@@ -884,6 +884,25 @@ size_t stringjoin(char *dest, size_t destsize, ...)
        return ret;
  }