Diff for /embedaddon/rsync/exclude.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2016/11/01 09:54:32 version 1.1.1.4, 2021/03/17 00:32:36
Line 4 Line 4
  * Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>   * Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
  * Copyright (C) 1996 Paul Mackerras   * Copyright (C) 1996 Paul Mackerras
  * Copyright (C) 2002 Martin Pool   * Copyright (C) 2002 Martin Pool
 * Copyright (C) 2003-2015 Wayne Davison * Copyright (C) 2003-2020 Wayne Davison
  *   *
  * This program is free software; you can redistribute it and/or modify   * 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   * it under the terms of the GNU General Public License as published by
Line 21 Line 21
  */   */
   
 #include "rsync.h"  #include "rsync.h"
   #include "ifuncs.h"
   
 extern int am_server;  extern int am_server;
 extern int am_sender;  extern int am_sender;
Line 44  filter_rule_list filter_list = { .debug_type = "" }; Line 45  filter_rule_list filter_list = { .debug_type = "" };
 filter_rule_list cvs_filter_list = { .debug_type = " [global CVS]" };  filter_rule_list cvs_filter_list = { .debug_type = " [global CVS]" };
 filter_rule_list daemon_filter_list = { .debug_type = " [daemon]" };  filter_rule_list daemon_filter_list = { .debug_type = " [daemon]" };
   
/* Need room enough for ":MODS " prefix plus some room to grow. */filter_rule *last_hit_filter_rule;
#define MAX_RULE_PREFIX (16) 
   
   int saw_xattr_filter = 0;
   
   /* Need room enough for ":MODS " prefix, which can now include
    * chmod/user/group values. */
   #define MAX_RULE_PREFIX (256)
   
 #define SLASH_WILD3_SUFFIX "/***"  #define SLASH_WILD3_SUFFIX "/***"
   
 /* The dirbuf is set by push_local_filters() to the current subdirectory  /* The dirbuf is set by push_local_filters() to the current subdirectory
Line 124  static void teardown_mergelist(filter_rule *ex) Line 130  static void teardown_mergelist(filter_rule *ex)
                 mergelist_cnt--;                  mergelist_cnt--;
 }  }
   
   static struct filter_chmod_struct *ref_filter_chmod(struct filter_chmod_struct *chmod)
   {
           chmod->ref_cnt++;
           assert(chmod->ref_cnt != 0); /* Catch overflow. */
           return chmod;
   }
   
   static void unref_filter_chmod(struct filter_chmod_struct *chmod)
   {
           chmod->ref_cnt--;
           if (chmod->ref_cnt == 0) {
                   free(chmod->modestr);
                   free_chmod_mode(chmod->modes);
                   free(chmod);
           }
   }
   
 static void free_filter(filter_rule *ex)  static void free_filter(filter_rule *ex)
 {  {
           if (ex->rflags & FILTRULE_CHMOD)
                   unref_filter_chmod(ex->chmod);
         if (ex->rflags & FILTRULE_PERDIR_MERGE)          if (ex->rflags & FILTRULE_PERDIR_MERGE)
                 teardown_mergelist(ex);                  teardown_mergelist(ex);
         free(ex->pattern);          free(ex->pattern);
Line 197  static void add_rule(filter_rule_list *listp, const ch Line 222  static void add_rule(filter_rule_list *listp, const ch
         } else          } else
                 suf_len = 0;                  suf_len = 0;
   
        if (!(rule->pattern = new_array(char, pre_len + pat_len + suf_len + 1)))        rule->pattern = new_array(char, pre_len + pat_len + suf_len + 1);
                out_of_memory("add_rule"); 
         if (pre_len) {          if (pre_len) {
                 memcpy(rule->pattern, dirbuf + module_dirlen, pre_len);                  memcpy(rule->pattern, dirbuf + module_dirlen, pre_len);
                 for (cp = rule->pattern; cp < rule->pattern + pre_len; cp++) {                  for (cp = rule->pattern; cp < rule->pattern + pre_len; cp++) {
Line 259  static void add_rule(filter_rule_list *listp, const ch Line 283  static void add_rule(filter_rule_list *listp, const ch
                         }                          }
                 }                  }
   
                if (!(lp = new_array0(filter_rule_list, 1)))                lp = new_array0(filter_rule_list, 1);
                        out_of_memory("add_rule"); 
                 if (asprintf(&lp->debug_type, " [per-dir %s]", cp) < 0)                  if (asprintf(&lp->debug_type, " [per-dir %s]", cp) < 0)
                         out_of_memory("add_rule");                          out_of_memory("add_rule");
                 rule->u.mergelist = lp;                  rule->u.mergelist = lp;
   
                 if (mergelist_cnt == mergelist_size) {                  if (mergelist_cnt == mergelist_size) {
                         mergelist_size += 5;                          mergelist_size += 5;
                        mergelist_parents = realloc_array(mergelist_parents,                        mergelist_parents = realloc_array(mergelist_parents, filter_rule *, mergelist_size);
                                                filter_rule *, 
                                                mergelist_size); 
                        if (!mergelist_parents) 
                                out_of_memory("add_rule"); 
                 }                  }
                 if (DEBUG_GTE(FILTER, 2)) {                  if (DEBUG_GTE(FILTER, 2)) {
                         rprintf(FINFO, "[%s] activating mergelist #%d%s\n",                          rprintf(FINFO, "[%s] activating mergelist #%d%s\n",
Line 495  void *push_local_filters(const char *dir, unsigned int Line 514  void *push_local_filters(const char *dir, unsigned int
         push = (struct local_filter_state *)new_array(char,          push = (struct local_filter_state *)new_array(char,
                           sizeof (struct local_filter_state)                            sizeof (struct local_filter_state)
                         + (mergelist_cnt-1) * sizeof (filter_rule_list));                          + (mergelist_cnt-1) * sizeof (filter_rule_list));
         if (!push)  
                 out_of_memory("push_local_filters");  
   
         push->mergelist_cnt = mergelist_cnt;          push->mergelist_cnt = mergelist_cnt;
         for (i = 0; i < mergelist_cnt; i++) {          for (i = 0; i < mergelist_cnt; i++) {
Line 622  void change_local_filter_dir(const char *dname, int dl Line 639  void change_local_filter_dir(const char *dname, int dl
         filt_array[cur_depth] = push_local_filters(dname, dlen);          filt_array[cur_depth] = push_local_filters(dname, dlen);
 }  }
   
static int rule_matches(const char *fname, filter_rule *ex, int name_is_dir)static int rule_matches(const char *fname, filter_rule *ex, int name_flags)
 {  {
         int slash_handling, str_cnt = 0, anchored_match = 0;          int slash_handling, str_cnt = 0, anchored_match = 0;
         int ret_match = ex->rflags & FILTRULE_NEGATE ? 0 : 1;          int ret_match = ex->rflags & FILTRULE_NEGATE ? 0 : 1;
Line 633  static int rule_matches(const char *fname, filter_rule Line 650  static int rule_matches(const char *fname, filter_rule
         if (!*name)          if (!*name)
                 return 0;                  return 0;
   
           if (!(name_flags & NAME_IS_XATTR) ^ !(ex->rflags & FILTRULE_XATTR))
                   return 0;
   
         if (!ex->u.slash_cnt && !(ex->rflags & FILTRULE_WILD2)) {          if (!ex->u.slash_cnt && !(ex->rflags & FILTRULE_WILD2)) {
                 /* If the pattern does not have any slashes AND it does                  /* If the pattern does not have any slashes AND it does
                  * not have a "**" (which could match a slash), then we                   * not have a "**" (which could match a slash), then we
Line 650  static int rule_matches(const char *fname, filter_rule Line 670  static int rule_matches(const char *fname, filter_rule
                 strings[str_cnt++] = "/";                  strings[str_cnt++] = "/";
         }          }
         strings[str_cnt++] = name;          strings[str_cnt++] = name;
        if (name_is_dir) {        if (name_flags & NAME_IS_DIR) {
                 /* Allow a trailing "/"+"***" to match the directory. */                  /* Allow a trailing "/"+"***" to match the directory. */
                 if (ex->rflags & FILTRULE_WILD3_SUFFIX)                  if (ex->rflags & FILTRULE_WILD3_SUFFIX)
                         strings[str_cnt++] = "/";                          strings[str_cnt++] = "/";
Line 685  static int rule_matches(const char *fname, filter_rule Line 705  static int rule_matches(const char *fname, filter_rule
                 if (litmatch_array(pattern, strings, slash_handling))                  if (litmatch_array(pattern, strings, slash_handling))
                         return ret_match;                          return ret_match;
         } else if (anchored_match) {          } else if (anchored_match) {
                if (strcmp(name, pattern) == 0)                if (ic_strEQ(name, pattern))
                         return ret_match;                          return ret_match;
         } else {          } else {
                 int l1 = strlen(name);                  int l1 = strlen(name);
                 int l2 = strlen(pattern);                  int l2 = strlen(pattern);
                if (l2 <= l1 &&                if (l2 <= l1
                    strcmp(name+(l1-l2),pattern) == 0 &&                 && ic_strEQ(name + (l1-l2), pattern)
                    (l1==l2 || name[l1-(l2+1)] == '/')) {                 && (l1 == l2 || name[l1 - (l2+1)] == '/'))
                         return ret_match;                          return ret_match;
                 }  
         }          }
   
         return !ret_match;          return !ret_match;
Line 702  static int rule_matches(const char *fname, filter_rule Line 721  static int rule_matches(const char *fname, filter_rule
   
 static void report_filter_result(enum logcode code, char const *name,  static void report_filter_result(enum logcode code, char const *name,
                                  filter_rule const *ent,                                   filter_rule const *ent,
                                 int name_is_dir, const char *type)                                 int name_flags, const char *type)
 {  {
         /* If a trailing slash is present to match only directories,          /* If a trailing slash is present to match only directories,
          * then it is stripped out by add_rule().  So as a special           * then it is stripped out by add_rule().  So as a special
Line 712  static void report_filter_result(enum logcode code, ch Line 731  static void report_filter_result(enum logcode code, ch
                 static char *actions[2][2]                  static char *actions[2][2]
                     = { {"show", "hid"}, {"risk", "protect"} };                      = { {"show", "hid"}, {"risk", "protect"} };
                 const char *w = who_am_i();                  const char *w = who_am_i();
                   const char *t = name_flags & NAME_IS_XATTR ? "xattr"
                                 : name_flags & NAME_IS_DIR ? "directory"
                                 : "file";
                 rprintf(code, "[%s] %sing %s %s because of pattern %s%s%s\n",                  rprintf(code, "[%s] %sing %s %s because of pattern %s%s%s\n",
                     w, actions[*w!='s'][!(ent->rflags & FILTRULE_INCLUDE)],                      w, actions[*w!='s'][!(ent->rflags & FILTRULE_INCLUDE)],
                    name_is_dir ? "directory" : "file", name, ent->pattern,                    t, name, ent->pattern,
                     ent->rflags & FILTRULE_DIRECTORY ? "/" : "", type);                      ent->rflags & FILTRULE_DIRECTORY ? "/" : "", type);
         }          }
 }  }
   
   /* 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
    * filter_level is set to either SERVER_FILTERS or ALL_FILTERS.
    * "last_hit_filter_rule" will be set to the operative filter, or NULL if none. */
   
   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) {
                   if (!(name_flags & NAME_IS_XATTR))
                           errno = ENOENT;
                   return 1;
           }
   
           /* Don't leave a daemon include in last_hit_filter_rule. */
           last_hit_filter_rule = NULL;
   
           if (filter_level != ALL_FILTERS)
                   return 0;
   
           if (filter_list.head && check_filter(&filter_list, FINFO, fname, name_flags) < 0)
                   return 1;
   
           return 0;
   }
   
 /* Return -1 if file "name" is defined to be excluded by the specified  /* Return -1 if file "name" is defined to be excluded by the specified
 * exclude list, 1 if it is included, and 0 if it was not matched. */ * exclude list, 1 if it is included, and 0 if it was not matched.
  * Sets last_hit_filter_rule to the filter that was hit, or NULL if none. */
 int check_filter(filter_rule_list *listp, enum logcode code,  int check_filter(filter_rule_list *listp, enum logcode code,
                 const char *name, int name_is_dir)                 const char *name, int name_flags)
 {  {
         filter_rule *ent;          filter_rule *ent;
   
Line 730  int check_filter(filter_rule_list *listp, enum logcode Line 778  int check_filter(filter_rule_list *listp, enum logcode
                 if (ignore_perishable && ent->rflags & FILTRULE_PERISHABLE)                  if (ignore_perishable && ent->rflags & FILTRULE_PERISHABLE)
                         continue;                          continue;
                 if (ent->rflags & FILTRULE_PERDIR_MERGE) {                  if (ent->rflags & FILTRULE_PERDIR_MERGE) {
                        int rc = check_filter(ent->u.mergelist, code, name,                        int rc = check_filter(ent->u.mergelist, code, name, name_flags);
                                              name_is_dir); 
                         if (rc)                          if (rc)
                                 return rc;                                  return rc;
                         continue;                          continue;
                 }                  }
                 if (ent->rflags & FILTRULE_CVS_IGNORE) {                  if (ent->rflags & FILTRULE_CVS_IGNORE) {
                        int rc = check_filter(&cvs_filter_list, code, name,                        int rc = check_filter(&cvs_filter_list, code, name, name_flags);
                                              name_is_dir); 
                         if (rc)                          if (rc)
                                 return rc;                                  return rc;
                         continue;                          continue;
                 }                  }
                if (rule_matches(name, ent, name_is_dir)) {                if (rule_matches(name, ent, name_flags)) {
                        report_filter_result(code, name, ent, name_is_dir,                        report_filter_result(code, name, ent, name_flags, listp->debug_type);
                                             listp->debug_type);                        last_hit_filter_rule = ent;
                         return ent->rflags & FILTRULE_INCLUDE ? 1 : -1;                          return ent->rflags & FILTRULE_INCLUDE ? 1 : -1;
                 }                  }
         }          }
   
           last_hit_filter_rule = NULL;
         return 0;          return 0;
 }  }
   
Line 766  static const uchar *rule_strcmp(const uchar *str, cons Line 813  static const uchar *rule_strcmp(const uchar *str, cons
         return NULL;          return NULL;
 }  }
   
   static char *grab_paren_value(const uchar **s_ptr)
   {
           const uchar *start, *end;
           int val_sz;
           char *val;
   
           if ((*s_ptr)[1] != '(')
                   return NULL;
           start = (*s_ptr) + 2;
   
           for (end = start; *end != ')'; end++)
                   if (!*end || *end == ' ' || *end == '_')
                           return NULL;
   
           val_sz = end - start + 1;
           val = new_array(char, val_sz);
           strlcpy(val, (const char *)start, val_sz);
           *s_ptr = end; /* remember ++s in parse_rule_tok */
           return val;
   }
   
   static struct filter_chmod_struct *make_chmod_struct(char *modestr)
   {
           struct filter_chmod_struct *chmod;
           struct chmod_mode_struct *modes = NULL;
   
           if (!parse_chmod(modestr, &modes))
                   return NULL;
   
           chmod = new(struct filter_chmod_struct);
           chmod->ref_cnt = 1;
           chmod->modestr = modestr;
           chmod->modes = modes;
           return chmod;
   }
   
 #define FILTRULES_FROM_CONTAINER (FILTRULE_ABS_PATH | FILTRULE_INCLUDE \  #define FILTRULES_FROM_CONTAINER (FILTRULE_ABS_PATH | FILTRULE_INCLUDE \
                                 | FILTRULE_DIRECTORY | FILTRULE_NEGATE \                                  | FILTRULE_DIRECTORY | FILTRULE_NEGATE \
                                | FILTRULE_PERISHABLE)                                | FILTRULE_PERISHABLE | FILTRULES_ATTRS)
   
 /* Gets the next include/exclude rule from *rulestr_ptr and advances  /* Gets the next include/exclude rule from *rulestr_ptr and advances
  * *rulestr_ptr to point beyond it.  Stores the pattern's start (within   * *rulestr_ptr to point beyond it.  Stores the pattern's start (within
Line 783  static filter_rule *parse_rule_tok(const char **rulest Line 866  static filter_rule *parse_rule_tok(const char **rulest
                                    const char **pat_ptr, unsigned int *pat_len_ptr)                                     const char **pat_ptr, unsigned int *pat_len_ptr)
 {  {
         const uchar *s = (const uchar *)*rulestr_ptr;          const uchar *s = (const uchar *)*rulestr_ptr;
           char *val;
         filter_rule *rule;          filter_rule *rule;
         unsigned int len;          unsigned int len;
   
Line 796  static filter_rule *parse_rule_tok(const char **rulest Line 880  static filter_rule *parse_rule_tok(const char **rulest
         if (!*s)          if (!*s)
                 return NULL;                  return NULL;
   
        if (!(rule = new0(filter_rule)))        rule = new0(filter_rule);
                out_of_memory("parse_rule_tok"); 
   
         /* Inherit from the template.  Don't inherit FILTRULES_SIDES; we check          /* Inherit from the template.  Don't inherit FILTRULES_SIDES; we check
          * that later. */           * that later. */
         rule->rflags = template->rflags & FILTRULES_FROM_CONTAINER;          rule->rflags = template->rflags & FILTRULES_FROM_CONTAINER;
           if (template->rflags & FILTRULE_CHMOD)
                   rule->chmod = ref_filter_chmod(template->chmod);
           if (template->rflags & FILTRULE_FORCE_OWNER)
                   rule->force_uid = template->force_uid;
           if (template->rflags & FILTRULE_FORCE_GROUP)
                   rule->force_gid = template->force_gid;
   
         /* Figure out what kind of a filter rule "s" is pointing at.  Note          /* 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           * that if FILTRULE_NO_PREFIXES is set, the rule is either an include
Line 947  static filter_rule *parse_rule_tok(const char **rulest Line 1036  static filter_rule *parse_rule_tok(const char **rulest
                                         goto invalid;                                          goto invalid;
                                 rule->rflags |= FILTRULE_EXCLUDE_SELF;                                  rule->rflags |= FILTRULE_EXCLUDE_SELF;
                                 break;                                  break;
                           case 'g': {
                                   gid_t gid;
   
                                   if (!(val = grab_paren_value(&s)))
                                           goto invalid;
                                   if (group_to_gid(val, &gid, True)) {
                                           rule->rflags |= FILTRULE_FORCE_GROUP;
                                           rule->force_gid = gid;
                                   } else {
                                           rprintf(FERROR,
                                                   "unknown group '%s' in filter rule: %s\n",
                                                   val, *rulestr_ptr);
                                           exit_cleanup(RERR_SYNTAX);
                                   }
                                   free(val);
                                   break;
                           }
                           case 'm': {
                                   struct filter_chmod_struct *chmod;
   
                                   if (!(val = grab_paren_value(&s)))
                                           goto invalid;
                                   if ((chmod = make_chmod_struct(val))) {
                                           if (rule->rflags & FILTRULE_CHMOD)
                                                   unref_filter_chmod(rule->chmod);
                                           rule->rflags |= FILTRULE_CHMOD;
                                           rule->chmod = chmod;
                                   } else {
                                           rprintf(FERROR,
                                                   "unparseable chmod string '%s' in filter rule: %s\n",
                                                   val, *rulestr_ptr);
                                           exit_cleanup(RERR_SYNTAX);
                                   }
                                   break;
                           }
                         case 'n':                          case 'n':
                                 if (!(rule->rflags & FILTRULE_MERGE_FILE))                                  if (!(rule->rflags & FILTRULE_MERGE_FILE))
                                         goto invalid;                                          goto invalid;
                                 rule->rflags |= FILTRULE_NO_INHERIT;                                  rule->rflags |= FILTRULE_NO_INHERIT;
                                 break;                                  break;
                           case 'o': {
                                   uid_t uid;
   
                                   if (!(val = grab_paren_value(&s)))
                                           goto invalid;
                                   if (user_to_uid(val, &uid, True)) {
                                           rule->rflags |= FILTRULE_FORCE_OWNER;
                                           rule->force_uid = uid;
                                   } else {
                                           rprintf(FERROR,
                                                   "unknown user '%s' in filter rule: %s\n",
                                                   val, *rulestr_ptr);
                                           exit_cleanup(RERR_SYNTAX);
                                   }
                                   free(val);
                                   break;
                           }
                         case 'p':                          case 'p':
                                 rule->rflags |= FILTRULE_PERISHABLE;                                  rule->rflags |= FILTRULE_PERISHABLE;
                                 break;                                  break;
Line 970  static filter_rule *parse_rule_tok(const char **rulest Line 1111  static filter_rule *parse_rule_tok(const char **rulest
                                         goto invalid;                                          goto invalid;
                                 rule->rflags |= FILTRULE_WORD_SPLIT;                                  rule->rflags |= FILTRULE_WORD_SPLIT;
                                 break;                                  break;
                           case 'x':
                                   rule->rflags |= FILTRULE_XATTR;
                                   saw_xattr_filter = 1;
                                   break;
                         }                          }
                 }                  }
                 if (*s)                  if (*s)
Line 1022  static filter_rule *parse_rule_tok(const char **rulest Line 1167  static filter_rule *parse_rule_tok(const char **rulest
         return rule;          return rule;
 }  }
   
 static char default_cvsignore[] =  
         /* These default ignored items come from the CVS manual. */  
         "RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS"  
         " .make.state .nse_depinfo *~ #* .#* ,* _$* *$"  
         " *.old *.bak *.BAK *.orig *.rej .del-*"  
         " *.a *.olb *.o *.obj *.so *.exe"  
         " *.Z *.elc *.ln core"  
         /* The rest we added to suit ourself. */  
         " .svn/ .git/ .hg/ .bzr/";  
   
 static void get_cvs_excludes(uint32 rflags)  static void get_cvs_excludes(uint32 rflags)
 {  {
         static int initialized = 0;          static int initialized = 0;
Line 1041  static void get_cvs_excludes(uint32 rflags) Line 1176  static void get_cvs_excludes(uint32 rflags)
                 return;                  return;
         initialized = 1;          initialized = 1;
   
        parse_filter_str(&cvs_filter_list, default_cvsignore,        parse_filter_str(&cvs_filter_list, default_cvsignore(),
                          rule_template(rflags | (protocol_version >= 30 ? FILTRULE_PERISHABLE : 0)),                           rule_template(rflags | (protocol_version >= 30 ? FILTRULE_PERISHABLE : 0)),
                          0);                           0);
   
Line 1105  void parse_filter_str(filter_rule_list *listp, const c Line 1240  void parse_filter_str(filter_rule_list *listp, const c
                                 const char *name;                                  const char *name;
                                 filter_rule *excl_self;                                  filter_rule *excl_self;
   
                                if (!(excl_self = new0(filter_rule)))                                excl_self = new0(filter_rule);
                                        out_of_memory("parse_filter_str"); 
                                 /* Find the beginning of the basename and add an exclude for it. */                                  /* Find the beginning of the basename and add an exclude for it. */
                                 for (name = pat + pat_len; name > pat && name[-1] != '/'; name--) {}                                  for (name = pat + pat_len; name > pat && name[-1] != '/'; name--) {}
                                 add_rule(listp, name, (pat + pat_len) - name, excl_self, 0);                                  add_rule(listp, name, (pat + pat_len) - name, excl_self, 0);
Line 1257  char *get_rule_prefix(filter_rule *rule, const char *p Line 1391  char *get_rule_prefix(filter_rule *rule, const char *p
         }          }
         if (rule->rflags & FILTRULE_EXCLUDE_SELF)          if (rule->rflags & FILTRULE_EXCLUDE_SELF)
                 *op++ = 'e';                  *op++ = 'e';
           if (rule->rflags & FILTRULE_XATTR)
                   *op++ = 'x';
         if (rule->rflags & FILTRULE_SENDER_SIDE          if (rule->rflags & FILTRULE_SENDER_SIDE
             && (!for_xfer || protocol_version >= 29))              && (!for_xfer || protocol_version >= 29))
                 *op++ = 's';                  *op++ = 's';
Line 1270  char *get_rule_prefix(filter_rule *rule, const char *p Line 1406  char *get_rule_prefix(filter_rule *rule, const char *p
                 else if (am_sender)                  else if (am_sender)
                         return NULL;                          return NULL;
         }          }
           if (rule->rflags & FILTRULES_ATTRS) {
                   if (!for_xfer || protocol_version >= 31) {
                           if (rule->rflags & FILTRULE_CHMOD)
                                   if (!snappendf(&op, (buf + sizeof buf) - op,
                                           "m(%s)", rule->chmod->modestr))
                                           return NULL;
                           if (rule->rflags & FILTRULE_FORCE_OWNER)
                                   if (!snappendf(&op, (buf + sizeof buf) - op,
                                           "o(%u)", (unsigned)rule->force_uid))
                                           return NULL;
                           if (rule->rflags & FILTRULE_FORCE_GROUP)
                                   if (!snappendf(&op, (buf + sizeof buf) - op,
                                           "g(%u)", (unsigned)rule->force_gid))
                                           return NULL;
                   } else if (!am_sender)
                           return NULL;
           }
         if (op - buf > legal_len)          if (op - buf > legal_len)
                 return NULL;                  return NULL;
         if (legal_len)          if (legal_len)
Line 1375  void recv_filter_list(int f_in) Line 1528  void recv_filter_list(int f_in)
         char line[BIGPATHBUFLEN];          char line[BIGPATHBUFLEN];
         int xflags = protocol_version >= 29 ? 0 : XFLG_OLD_PREFIXES;          int xflags = protocol_version >= 29 ? 0 : XFLG_OLD_PREFIXES;
         int receiver_wants_list = prune_empty_dirs          int receiver_wants_list = prune_empty_dirs
            || (delete_mode            || (delete_mode && (!delete_excluded || protocol_version >= 29));
             && (!delete_excluded || protocol_version >= 29)); 
         unsigned int len;          unsigned int len;
   
         if (!local_server && (am_sender || receiver_wants_list)) {          if (!local_server && (am_sender || receiver_wants_list)) {

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>