Include 2008 in the copyright years.
[rsync/rsync.git] / exclude.c
index 1a0be70..027ea7a 100644 (file)
--- a/exclude.c
+++ b/exclude.c
@@ -4,7 +4,7 @@
  * Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
  * Copyright (C) 1996 Paul Mackerras
  * Copyright (C) 2002 Martin Pool
- * Copyright (C) 2003-2007 Wayne Davison
+ * Copyright (C) 2003-2008 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
@@ -26,8 +26,6 @@ extern int verbose;
 extern int am_server;
 extern int am_sender;
 extern int eol_nulls;
-extern int list_only;
-extern int recurse;
 extern int io_error;
 extern int local_server;
 extern int prune_empty_dirs;
@@ -144,9 +142,8 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
                }
        }
 
-       if (!(ret = new(struct filter_struct)))
+       if (!(ret = new0(struct filter_struct)))
                out_of_memory("add_rule");
-       memset(ret, 0, sizeof ret[0]);
 
        if (!(mflags & (MATCHFLG_ABS_PATH | MATCHFLG_MERGE_FILE))
         && ((xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH) && *pat == '/')
@@ -298,7 +295,7 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
                        strlcpy(to, merge_file, *len_ptr + 1);
                        merge_file = to;
                }
-               if (!sanitize_path(fn, merge_file, r, dirbuf_depth, NULL)) {
+               if (!sanitize_path(fn, merge_file, r, dirbuf_depth)) {
                        rprintf(FERROR, "merge-file name overflows: %s\n",
                                merge_file);
                        return NULL;
@@ -306,7 +303,7 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
                fn_len = strlen(fn);
        } else {
                strlcpy(fn, merge_file, len_ptr ? *len_ptr + 1 : MAXPATHLEN);
-               fn_len = clean_fname(fn, 1);
+               fn_len = clean_fname(fn, CFN_COLLAPSE_DOT_DOT_DIRS);
        }
 
        /* If the name isn't in buf yet, it's wasn't absolute. */
@@ -317,7 +314,7 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
                }
                memcpy(buf, dirbuf + prefix_skip, dirbuf_len - prefix_skip);
                memcpy(buf + dirbuf_len - prefix_skip, fn, fn_len + 1);
-               fn_len = clean_fname(buf, 1);
+               fn_len = clean_fname(buf, CFN_COLLAPSE_DOT_DOT_DIRS);
        }
 
        if (len_ptr)
@@ -339,7 +336,7 @@ void set_filter_dir(const char *dir, unsigned int dirlen)
                len = 0;
        memcpy(dirbuf + len, dir, dirlen);
        dirbuf[dirlen + len] = '\0';
-       dirbuf_len = clean_fname(dirbuf, 1);
+       dirbuf_len = clean_fname(dirbuf, CFN_COLLAPSE_DOT_DOT_DIRS);
        if (dirbuf_len > 1 && dirbuf[dirbuf_len-1] == '.'
            && dirbuf[dirbuf_len-2] == '/')
                dirbuf_len -= 2;
@@ -375,7 +372,7 @@ static BOOL setup_merge_file(struct filter_struct *ex,
        else
                pathjoin(buf, MAXPATHLEN, dirbuf, x);
 
-       len = clean_fname(buf, 1);
+       len = clean_fname(buf, CFN_COLLAPSE_DOT_DOT_DIRS);
        if (len != 1 && len < MAXPATHLEN-1) {
                buf[len++] = '/';
                buf[len] = '\0';
@@ -494,37 +491,40 @@ void pop_local_filters(void *mem)
 
 void change_local_filter_dir(const char *dname, int dlen, int dir_depth)
 {
-       static int min_depth = MAXPATHLEN, cur_depth = -1;
+       static int cur_depth = -1;
        static void *filt_array[MAXPATHLEN/2+1];
 
        if (!dname) {
-               while (cur_depth >= min_depth)
-                       pop_local_filters(filt_array[cur_depth--]);
-               min_depth = MAXPATHLEN;
-               cur_depth = -1;
+               for ( ; cur_depth >= 0; cur_depth--) {
+                       if (filt_array[cur_depth]) {
+                               pop_local_filters(filt_array[cur_depth]);
+                               filt_array[cur_depth] = NULL;
+                       }
+               }
                return;
        }
 
        assert(dir_depth < MAXPATHLEN/2+1);
 
-       while (cur_depth >= dir_depth && cur_depth >= min_depth)
-               pop_local_filters(filt_array[cur_depth--]);
-       cur_depth = dir_depth;
-       if (cur_depth < min_depth)
-               min_depth = cur_depth;
+       for ( ; cur_depth >= dir_depth; cur_depth--) {
+               if (filt_array[cur_depth]) {
+                       pop_local_filters(filt_array[cur_depth]);
+                       filt_array[cur_depth] = NULL;
+               }
+       }
 
+       cur_depth = dir_depth;
        filt_array[cur_depth] = push_local_filters(dname, dlen);
 }
 
-static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
+static int rule_matches(char *fname, struct filter_struct *ex, int name_is_dir)
 {
        int slash_handling, str_cnt = 0, anchored_match = 0;
        int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
        char *p, *pattern = ex->pattern;
        const char *strings[16]; /* more than enough */
+       char *name = fname + (*fname == '/');
 
-       if (*name == '/')
-               name++;
        if (!*name)
                return 0;
 
@@ -534,13 +534,13 @@ static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
                 * just match the name portion of the path. */
                if ((p = strrchr(name,'/')) != NULL)
                        name = p+1;
-       } else if (ex->match_flags & MATCHFLG_ABS_PATH && *name != '/'
+       } else if (ex->match_flags & MATCHFLG_ABS_PATH && *fname != '/'
            && curr_dir_len > module_dirlen + 1) {
                /* If we're matching against an absolute-path pattern,
                 * we need to prepend our full path info. */
                strings[str_cnt++] = curr_dir + module_dirlen + 1;
                strings[str_cnt++] = "/";
-       } else if (ex->match_flags & MATCHFLG_WILD2_PREFIX && *name != '/') {
+       } else if (ex->match_flags & MATCHFLG_WILD2_PREFIX && *fname != '/') {
                /* Allow "**"+"/" to match at the start of the string. */
                strings[str_cnt++] = "/";
        }
@@ -898,7 +898,7 @@ static char default_cvsignore[] =
        " *.a *.olb *.o *.obj *.so *.exe"
        " *.Z *.elc *.ln core"
        /* The rest we added to suit ourself. */
-       " .svn/ .bzr/";
+       " .svn/ .git/ .bzr/";
 
 static void get_cvs_excludes(uint32 mflags)
 {
@@ -1011,7 +1011,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
        if (*fname != '-' || fname[1] || am_server) {
                if (server_filter_list.head) {
                        strlcpy(line, fname, sizeof line);
-                       clean_fname(line, 1);
+                       clean_fname(line, CFN_COLLAPSE_DOT_DOT_DIRS);
                        if (check_filter(&server_filter_list, line, 0) < 0)
                                fp = NULL;
                        else
@@ -1212,11 +1212,6 @@ void send_filter_list(int f_out)
                parse_rule(&filter_list, "-C", 0, 0);
        }
 
-       /* This is a complete hack - blame Rusty.  FIXME!
-        * Remove this hack when older rsyncs (below 2.6.4) are gone. */
-       if (list_only == 1 && !recurse)
-               parse_rule(&filter_list, "/*/*", MATCHFLG_NO_PREFIXES, 0);
-
        send_rules(f_out, &filter_list);
 
        if (f_out >= 0)