1 /* -*- c-file-style: "linux" -*-
3 * Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
4 * Copyright (C) 1996 by Paul Mackerras
5 * Copyright (C) 2002 by Martin Pool
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 /* a lot of this stuff was originally derived from GNU tar, although
23 it has now changed so much that it is hard to tell :) */
25 /* include/exclude cluestick added by Martin Pool <mbp@samba.org> */
35 extern int sanitize_paths
;
36 extern int protocol_version
;
39 extern char curr_dir
[];
40 extern unsigned int curr_dir_len
;
41 extern unsigned int module_dirlen
;
43 struct filter_list_struct filter_list
= { 0, 0, "" };
44 struct filter_list_struct server_filter_list
= { 0, 0, "server " };
46 /* Need room enough for ":MODS " prefix plus some room to grow. */
47 #define MAX_RULE_PREFIX (16)
49 /* The dirbuf is set by push_local_filters() to the current subdirectory
50 * relative to curr_dir that is being processed. The path always has a
51 * trailing slash appended, and the variable dirbuf_len contains the length
52 * of this path prefix. The path is always absolute. */
53 static char dirbuf
[MAXPATHLEN
+1];
54 static unsigned int dirbuf_len
= 0;
55 static int dirbuf_depth
;
57 /* This is True when we're scanning parent dirs for per-dir merge-files. */
58 static BOOL parent_dirscan
= False
;
60 /* This array contains a list of all the currently active per-dir merge
61 * files. This makes it easier to save the appropriate values when we
62 * "push" down into each subdirectory. */
63 static struct filter_struct
**mergelist_parents
;
64 static int mergelist_cnt
= 0;
65 static int mergelist_size
= 0;
67 /* Each filter_list_struct describes a singly-linked list by keeping track
68 * of both the head and tail pointers. The list is slightly unusual in that
69 * a parent-dir's content can be appended to the end of the local list in a
70 * special way: the last item in the local list has its "next" pointer set
71 * to point to the inherited list, but the local list's tail pointer points
72 * at the end of the local list. Thus, if the local list is empty, the head
73 * will be pointing at the inherited content but the tail will be NULL. To
74 * help you visualize this, here are the possible list arrangements:
76 * Completely Empty Local Content Only
77 * ================================== ====================================
78 * head -> NULL head -> Local1 -> Local2 -> NULL
79 * tail -> NULL tail -------------^
81 * Inherited Content Only Both Local and Inherited Content
82 * ================================== ====================================
83 * head -> Parent1 -> Parent2 -> NULL head -> L1 -> L2 -> P1 -> P2 -> NULL
84 * tail -> NULL tail ---------^
86 * This means that anyone wanting to traverse the whole list to use it just
87 * needs to start at the head and use the "next" pointers until it goes
88 * NULL. To add new local content, we insert the item after the tail item
89 * and update the tail (obviously, if "tail" was NULL, we insert it at the
90 * head). To clear the local list, WE MUST NOT FREE THE INHERITED CONTENT
91 * because it is shared between the current list and our parent list(s).
92 * The easiest way to handle this is to simply truncate the list after the
93 * tail item and then free the local list from the head. When inheriting
94 * the list for a new local dir, we just save off the filter_list_struct
95 * values (so we can pop back to them later) and set the tail to NULL.
98 static void free_filter(struct filter_struct
*ex
)
100 if (ex
->match_flags
& MATCHFLG_PERDIR_MERGE
) {
101 free(ex
->u
.mergelist
->debug_type
);
102 free(ex
->u
.mergelist
);
109 /* Build a filter structure given a filter pattern. The value in "pat"
110 * is not null-terminated. */
111 static void filter_rule(struct filter_list_struct
*listp
, const char *pat
,
112 unsigned int pat_len
, unsigned int mflags
, int xflags
)
114 struct filter_struct
*ret
;
119 rprintf(FINFO
, "[%s] filter_rule(%.*s, %s%s)\n",
120 who_am_i(), (int)pat_len
, pat
,
121 mflags
& MATCHFLG_PERDIR_MERGE
? "per-dir-merge"
122 : mflags
& MATCHFLG_INCLUDE
? "include" : "exclude",
126 ret
= new(struct filter_struct
);
128 out_of_memory("filter_rule");
129 memset(ret
, 0, sizeof ret
[0]);
131 if (xflags
& XFLG_ANCHORED2ABS
&& *pat
== '/'
132 && !(mflags
& (MATCHFLG_ABS_PATH
| MATCHFLG_MERGE_FILE
))) {
133 mflags
|= MATCHFLG_ABS_PATH
;
134 ex_len
= dirbuf_len
- module_dirlen
- 1;
137 ret
->pattern
= new_array(char, ex_len
+ pat_len
+ 1);
139 out_of_memory("filter_rule");
141 memcpy(ret
->pattern
, dirbuf
+ module_dirlen
, ex_len
);
142 strlcpy(ret
->pattern
+ ex_len
, pat
, pat_len
+ 1);
145 if (strpbrk(ret
->pattern
, "*[?")) {
146 mflags
|= MATCHFLG_WILD
;
147 if ((cp
= strstr(ret
->pattern
, "**")) != NULL
) {
148 mflags
|= MATCHFLG_WILD2
;
149 /* If the pattern starts with **, note that. */
150 if (cp
== ret
->pattern
)
151 mflags
|= MATCHFLG_WILD2_PREFIX
;
155 if (pat_len
> 1 && ret
->pattern
[pat_len
-1] == '/') {
156 ret
->pattern
[pat_len
-1] = 0;
157 mflags
|= MATCHFLG_DIRECTORY
;
160 if (mflags
& MATCHFLG_PERDIR_MERGE
) {
161 struct filter_list_struct
*lp
;
165 if ((cp
= strrchr(ret
->pattern
, '/')) != NULL
)
170 /* If the local merge file was already mentioned, don't
172 for (i
= 0; i
< mergelist_cnt
; i
++) {
173 struct filter_struct
*ex
= mergelist_parents
[i
];
174 const char *s
= strrchr(ex
->pattern
, '/');
180 if (len
== pat_len
- (cp
- ret
->pattern
)
181 && memcmp(s
, cp
, len
) == 0) {
187 if (!(lp
= new_array(struct filter_list_struct
, 1)))
188 out_of_memory("filter_rule");
189 lp
->head
= lp
->tail
= NULL
;
190 if (asprintf(&lp
->debug_type
, " (per-dir %s)", cp
) < 0)
191 out_of_memory("filter_rule");
192 ret
->u
.mergelist
= lp
;
194 if (mergelist_cnt
== mergelist_size
) {
196 mergelist_parents
= realloc_array(mergelist_parents
,
197 struct filter_struct
*,
199 if (!mergelist_parents
)
200 out_of_memory("filter_rule");
202 mergelist_parents
[mergelist_cnt
++] = ret
;
204 for (cp
= ret
->pattern
; (cp
= strchr(cp
, '/')) != NULL
; cp
++)
208 ret
->match_flags
= mflags
;
211 ret
->next
= listp
->head
;
212 listp
->head
= listp
->tail
= ret
;
214 ret
->next
= listp
->tail
->next
;
215 listp
->tail
->next
= ret
;
220 static void clear_filter_list(struct filter_list_struct
*listp
)
223 struct filter_struct
*ent
, *next
;
224 /* Truncate any inherited items from the local list. */
225 listp
->tail
->next
= NULL
;
226 /* Now free everything that is left. */
227 for (ent
= listp
->head
; ent
; ent
= next
) {
233 listp
->head
= listp
->tail
= NULL
;
236 /* This returns an expanded (absolute) filename for the merge-file name if
237 * the name has any slashes in it OR if the parent_dirscan var is True;
238 * otherwise it returns the original merge_file name. If the len_ptr value
239 * is non-NULL the merge_file name is limited by the referenced length
240 * value and will be updated with the length of the resulting name. We
241 * always return a name that is null terminated, even if the merge_file
243 static char *parse_merge_name(const char *merge_file
, unsigned int *len_ptr
,
244 unsigned int prefix_skip
)
246 static char buf
[MAXPATHLEN
];
247 char *fn
, tmpbuf
[MAXPATHLEN
];
250 if (!parent_dirscan
&& *merge_file
!= '/') {
251 /* Return the name unchanged it doesn't have any slashes. */
253 const char *p
= merge_file
+ *len_ptr
;
254 while (--p
> merge_file
&& *p
!= '/') {}
255 if (p
== merge_file
) {
256 strlcpy(buf
, merge_file
, *len_ptr
+ 1);
259 } else if (strchr(merge_file
, '/') == NULL
)
260 return (char *)merge_file
;
263 fn
= *merge_file
== '/' ? buf
: tmpbuf
;
264 if (sanitize_paths
) {
265 const char *r
= prefix_skip
? "/" : NULL
;
266 /* null-terminate the name if it isn't already */
267 if (len_ptr
&& merge_file
[*len_ptr
]) {
268 char *to
= fn
== buf
? tmpbuf
: buf
;
269 strlcpy(to
, merge_file
, *len_ptr
+ 1);
272 if (!sanitize_path(fn
, merge_file
, r
, dirbuf_depth
)) {
273 rprintf(FERROR
, "merge-file name overflows: %s\n",
278 strlcpy(fn
, merge_file
, len_ptr
? *len_ptr
+ 1 : MAXPATHLEN
);
286 if (dirbuf_len
+ fn_len
>= MAXPATHLEN
) {
287 rprintf(FERROR
, "merge-file name overflows: %s\n", fn
);
290 memcpy(buf
, dirbuf
+ prefix_skip
, dirbuf_len
- prefix_skip
);
291 memcpy(buf
+ dirbuf_len
- prefix_skip
, fn
, fn_len
+ 1);
292 fn_len
= clean_fname(buf
, 1);
300 /* Sets the dirbuf and dirbuf_len values. */
301 void set_filter_dir(const char *dir
, unsigned int dirlen
)
305 memcpy(dirbuf
, curr_dir
, curr_dir_len
);
306 dirbuf
[curr_dir_len
] = '/';
307 len
= curr_dir_len
+ 1;
308 if (len
+ dirlen
>= MAXPATHLEN
)
312 memcpy(dirbuf
+ len
, dir
, dirlen
);
313 dirbuf
[dirlen
+ len
] = '\0';
314 dirbuf_len
= clean_fname(dirbuf
, 1);
315 if (dirbuf_len
> 1 && dirbuf
[dirbuf_len
-1] == '.'
316 && dirbuf
[dirbuf_len
-2] == '/')
319 dirbuf
[dirbuf_len
++] = '/';
320 dirbuf
[dirbuf_len
] = '\0';
322 dirbuf_depth
= count_dir_elements(dirbuf
+ module_dirlen
);
325 /* This routine takes a per-dir merge-file entry and finishes its setup.
326 * If the name has a path portion then we check to see if it refers to a
327 * parent directory of the first transfer dir. If it does, we scan all the
328 * dirs from that point through the parent dir of the transfer dir looking
329 * for the per-dir merge-file in each one. */
330 static BOOL
setup_merge_file(struct filter_struct
*ex
,
331 struct filter_list_struct
*lp
, int flags
)
333 char buf
[MAXPATHLEN
];
334 char *x
, *y
, *pat
= ex
->pattern
;
337 if (!(x
= parse_merge_name(pat
, NULL
, 0)) || *x
!= '/')
342 ex
->pattern
= strdup(y
+1);
346 strlcpy(buf
, x
, MAXPATHLEN
);
348 pathjoin(buf
, MAXPATHLEN
, dirbuf
, x
);
350 len
= clean_fname(buf
, 1);
351 if (len
!= 1 && len
< MAXPATHLEN
-1) {
355 /* This ensures that the specified dir is a parent of the transfer. */
356 for (x
= buf
, y
= dirbuf
; *x
&& *x
== *y
; x
++, y
++) {}
358 y
+= strlen(y
); /* nope -- skip the scan */
360 parent_dirscan
= True
;
362 char save
[MAXPATHLEN
];
363 strlcpy(save
, y
, MAXPATHLEN
);
365 dirbuf_len
= y
- dirbuf
;
366 strlcpy(x
, ex
->pattern
, MAXPATHLEN
- (x
- buf
));
367 add_filter_file(lp
, buf
, flags
| XFLG_ANCHORED2ABS
);
368 if (ex
->match_flags
& MATCHFLG_NO_INHERIT
)
371 strlcpy(y
, save
, MAXPATHLEN
);
372 while ((*x
++ = *y
++) != '/') {}
374 parent_dirscan
= False
;
379 /* Each time rsync changes to a new directory it call this function to
380 * handle all the per-dir merge-files. The "dir" value is the current path
381 * relative to curr_dir (which might not be null-terminated). We copy it
382 * into dirbuf so that we can easily append a file name on the end. */
383 void *push_local_filters(const char *dir
, unsigned int dirlen
)
385 struct filter_list_struct
*ap
, *push
;
388 set_filter_dir(dir
, dirlen
);
393 push
= new_array(struct filter_list_struct
, mergelist_cnt
);
395 out_of_memory("push_local_filters");
397 for (i
= 0, ap
= push
; i
< mergelist_cnt
; i
++) {
398 memcpy(ap
++, mergelist_parents
[i
]->u
.mergelist
,
399 sizeof (struct filter_list_struct
));
402 /* Note: add_filter_file() might increase mergelist_cnt, so keep
403 * this loop separate from the above loop. */
404 for (i
= 0; i
< mergelist_cnt
; i
++) {
405 struct filter_struct
*ex
= mergelist_parents
[i
];
406 struct filter_list_struct
*lp
= ex
->u
.mergelist
;
410 rprintf(FINFO
, "[%s] pushing filter list%s\n",
411 who_am_i(), lp
->debug_type
);
414 lp
->tail
= NULL
; /* Switch any local rules to inherited. */
415 if (ex
->match_flags
& MATCHFLG_NO_INHERIT
)
417 if (ex
->match_flags
& MATCHFLG_WORD_SPLIT
)
418 flags
|= XFLG_WORD_SPLIT
;
419 if (ex
->match_flags
& MATCHFLG_NO_PREFIXES
)
420 flags
|= XFLG_NO_PREFIXES
;
421 if (ex
->match_flags
& MATCHFLG_INCLUDE
)
422 flags
|= XFLG_DEF_INCLUDE
;
423 else if (ex
->match_flags
& MATCHFLG_NO_PREFIXES
)
424 flags
|= XFLG_DEF_EXCLUDE
;
426 if (ex
->match_flags
& MATCHFLG_FINISH_SETUP
) {
427 ex
->match_flags
&= ~MATCHFLG_FINISH_SETUP
;
428 if (setup_merge_file(ex
, lp
, flags
))
429 set_filter_dir(dir
, dirlen
);
432 if (strlcpy(dirbuf
+ dirbuf_len
, ex
->pattern
,
433 MAXPATHLEN
- dirbuf_len
) < MAXPATHLEN
- dirbuf_len
)
434 add_filter_file(lp
, dirbuf
, flags
| XFLG_ANCHORED2ABS
);
436 io_error
|= IOERR_GENERAL
;
438 "cannot add local filter rules in long-named directory: %s\n",
441 dirbuf
[dirbuf_len
] = '\0';
447 void pop_local_filters(void *mem
)
449 struct filter_list_struct
*ap
, *pop
= (struct filter_list_struct
*)mem
;
452 for (i
= mergelist_cnt
; i
-- > 0; ) {
453 struct filter_struct
*ex
= mergelist_parents
[i
];
454 struct filter_list_struct
*lp
= ex
->u
.mergelist
;
457 rprintf(FINFO
, "[%s] popping filter list%s\n",
458 who_am_i(), lp
->debug_type
);
461 clear_filter_list(lp
);
467 for (i
= 0, ap
= pop
; i
< mergelist_cnt
; i
++) {
468 memcpy(mergelist_parents
[i
]->u
.mergelist
, ap
++,
469 sizeof (struct filter_list_struct
));
475 static int rule_matches(char *name
, struct filter_struct
*ex
, int name_is_dir
)
477 char *p
, full_name
[MAXPATHLEN
];
479 char *pattern
= ex
->pattern
;
484 /* If the pattern does not have any slashes AND it does not have
485 * a "**" (which could match a slash), then we just match the
486 * name portion of the path. */
487 if (!ex
->u
.slash_cnt
&& !(ex
->match_flags
& MATCHFLG_WILD2
)) {
488 if ((p
= strrchr(name
,'/')) != NULL
)
491 else if (ex
->match_flags
& MATCHFLG_ABS_PATH
&& *name
!= '/'
492 && curr_dir_len
> module_dirlen
+ 1) {
493 pathjoin(full_name
, sizeof full_name
,
494 curr_dir
+ module_dirlen
+ 1, name
);
498 if (ex
->match_flags
& MATCHFLG_DIRECTORY
&& !name_is_dir
)
501 if (*pattern
== '/') {
508 if (ex
->match_flags
& MATCHFLG_WILD
) {
509 /* A non-anchored match with an infix slash and no "**"
510 * needs to match the last slash_cnt+1 name elements. */
511 if (!match_start
&& ex
->u
.slash_cnt
512 && !(ex
->match_flags
& MATCHFLG_WILD2
)) {
513 int cnt
= ex
->u
.slash_cnt
+ 1;
514 for (p
= name
+ strlen(name
) - 1; p
>= name
; p
--) {
515 if (*p
== '/' && !--cnt
)
520 if (wildmatch(pattern
, name
))
522 if (ex
->match_flags
& MATCHFLG_WILD2_PREFIX
) {
523 /* If the **-prefixed pattern has a '/' as the next
524 * character, then try to match the rest of the
525 * pattern at the root. */
526 if (pattern
[2] == '/' && wildmatch(pattern
+3, name
))
529 else if (!match_start
&& ex
->match_flags
& MATCHFLG_WILD2
) {
530 /* A non-anchored match with an infix or trailing "**"
531 * (but not a prefixed "**") needs to try matching
532 * after every slash. */
533 while ((name
= strchr(name
, '/')) != NULL
) {
535 if (wildmatch(pattern
, name
))
539 } else if (match_start
) {
540 if (strcmp(name
,pattern
) == 0)
543 int l1
= strlen(name
);
544 int l2
= strlen(pattern
);
546 strcmp(name
+(l1
-l2
),pattern
) == 0 &&
547 (l1
==l2
|| name
[l1
-(l2
+1)] == '/')) {
556 static void report_filter_result(char const *name
,
557 struct filter_struct
const *ent
,
558 int name_is_dir
, const char *type
)
560 /* If a trailing slash is present to match only directories,
561 * then it is stripped out by filter_rule. So as a special
562 * case we add it back in here. */
565 rprintf(FINFO
, "[%s] %scluding %s %s because of pattern %s%s%s\n",
567 ent
->match_flags
& MATCHFLG_INCLUDE
? "in" : "ex",
568 name_is_dir
? "directory" : "file", name
, ent
->pattern
,
569 ent
->match_flags
& MATCHFLG_DIRECTORY
? "/" : "", type
);
575 * Return -1 if file "name" is defined to be excluded by the specified
576 * exclude list, 1 if it is included, and 0 if it was not matched.
578 int check_filter(struct filter_list_struct
*listp
, char *name
, int name_is_dir
)
580 struct filter_struct
*ent
;
582 for (ent
= listp
->head
; ent
; ent
= ent
->next
) {
583 if (ent
->match_flags
& MATCHFLG_PERDIR_MERGE
) {
584 int rc
= check_filter(ent
->u
.mergelist
, name
,
590 if (rule_matches(name
, ent
, name_is_dir
)) {
591 report_filter_result(name
, ent
, name_is_dir
,
593 return ent
->match_flags
& MATCHFLG_INCLUDE
? 1 : -1;
601 /* Get the next include/exclude arg from the string. The token will not
602 * be '\0' terminated, so use the returned length to limit the string.
603 * Also, be sure to add this length to the returned pointer before passing
604 * it back to ask for the next token. This routine parses the "!" (list-
605 * clearing) token and (if xflags does NOT contain XFLG_NO_PREFIXES) the
606 * +/- prefixes for overriding the include/exclude mode. The *flag_ptr
607 * value will also be set to the MATCHFLG_* bits for the current token.
609 static const char *get_filter_tok(const char *p
, int xflags
,
610 unsigned int *len_ptr
, unsigned int *flag_ptr
)
612 const unsigned char *s
= (const unsigned char *)p
;
613 unsigned int len
, mflags
= 0;
614 int empty_pat_is_OK
= 0;
616 if (xflags
& XFLG_WORD_SPLIT
) {
617 /* Skip over any initial whitespace. */
620 /* Update to point to real start of rule. */
626 /* Figure out what kind of a filter rule "s" is pointing at. */
627 if (!(xflags
& (XFLG_DEF_INCLUDE
| XFLG_DEF_EXCLUDE
))) {
631 mflags
|= MATCHFLG_PERDIR_MERGE
632 | MATCHFLG_FINISH_SETUP
;
635 mflags
|= MATCHFLG_MERGE_FILE
;
639 mflags
|= MATCHFLG_INCLUDE
;
645 mflags
|= MATCHFLG_CLEAR_LIST
;
649 rprintf(FERROR
, "Unknown filter rule: %s\n", p
);
650 exit_cleanup(RERR_SYNTAX
);
652 while (mods
&& *++s
&& *s
!= ' ' && *s
!= '_') {
653 if (strchr(mods
, *s
) == NULL
) {
654 if (xflags
& XFLG_WORD_SPLIT
&& isspace(*s
)) {
659 "unknown modifier '%c' in filter rule: %s\n",
661 exit_cleanup(RERR_SYNTAX
);
665 mflags
|= MATCHFLG_NO_PREFIXES
;
668 mflags
|= MATCHFLG_NO_PREFIXES
672 mflags
|= MATCHFLG_ABS_PATH
;
676 mflags
|= MATCHFLG_NO_PREFIXES
677 | MATCHFLG_WORD_SPLIT
678 | MATCHFLG_NO_INHERIT
;
681 mflags
|= MATCHFLG_EXCLUDE_SELF
;
684 mflags
|= MATCHFLG_NO_INHERIT
;
687 mflags
|= MATCHFLG_WORD_SPLIT
;
693 } else if (!(xflags
& XFLG_NO_PREFIXES
)
694 && (*s
== '-' || *s
== '+') && s
[1] == ' ') {
696 mflags
|= MATCHFLG_INCLUDE
;
699 if (xflags
& XFLG_DEF_INCLUDE
)
700 mflags
|= MATCHFLG_INCLUDE
;
702 mflags
|= MATCHFLG_CLEAR_LIST
; /* Tentative! */
705 if (xflags
& XFLG_DIRECTORY
)
706 mflags
|= MATCHFLG_DIRECTORY
;
708 if (xflags
& XFLG_WORD_SPLIT
) {
709 const unsigned char *cp
= s
;
710 /* Token ends at whitespace or the end of the string. */
711 while (!isspace(*cp
) && *cp
!= '\0')
715 len
= strlen((char*)s
);
717 if (mflags
& MATCHFLG_CLEAR_LIST
) {
718 if (!(xflags
& (XFLG_DEF_INCLUDE
| XFLG_DEF_EXCLUDE
)) && len
) {
720 "'!' rule has trailing characters: %s\n", p
);
721 exit_cleanup(RERR_SYNTAX
);
724 mflags
&= ~MATCHFLG_CLEAR_LIST
;
725 } else if (!len
&& !empty_pat_is_OK
) {
726 rprintf(FERROR
, "unexpected end of filter rule: %s\n", p
);
727 exit_cleanup(RERR_SYNTAX
);
732 return (const char *)s
;
736 void add_filter(struct filter_list_struct
*listp
, const char *pattern
,
739 unsigned int pat_len
, mflags
;
746 /* Remember that the returned string is NOT '\0' terminated! */
747 cp
= get_filter_tok(pattern
, xflags
, &pat_len
, &mflags
);
750 if (pat_len
>= MAXPATHLEN
) {
751 rprintf(FERROR
, "discarding over-long filter: %s\n",
755 pattern
= cp
+ pat_len
;
757 if (mflags
& MATCHFLG_CLEAR_LIST
) {
760 "[%s] clearing filter list%s\n",
761 who_am_i(), listp
->debug_type
);
763 clear_filter_list(listp
);
772 if (mflags
& MATCHFLG_MERGE_FILE
) {
773 unsigned int len
= pat_len
;
774 if (mflags
& MATCHFLG_EXCLUDE_SELF
) {
775 const char *name
= strrchr(cp
, '/');
780 filter_rule(listp
, name
, len
, 0, 0);
781 mflags
&= ~MATCHFLG_EXCLUDE_SELF
;
784 if (mflags
& MATCHFLG_PERDIR_MERGE
) {
785 if (parent_dirscan
) {
786 if (!(p
= parse_merge_name(cp
, &len
, module_dirlen
)))
788 filter_rule(listp
, p
, len
, mflags
, 0);
792 int flgs
= XFLG_FATAL_ERRORS
;
793 if (!(p
= parse_merge_name(cp
, &len
, 0)))
795 if (mflags
& MATCHFLG_INCLUDE
)
796 flgs
|= XFLG_DEF_INCLUDE
;
797 else if (mflags
& MATCHFLG_NO_PREFIXES
)
798 flgs
|= XFLG_DEF_EXCLUDE
;
799 add_filter_file(listp
, p
, flgs
);
804 filter_rule(listp
, cp
, pat_len
, mflags
, xflags
);
809 void add_filter_file(struct filter_list_struct
*listp
, const char *fname
,
813 char line
[MAXPATHLEN
+MAX_RULE_PREFIX
+1]; /* +1 for trailing slash. */
814 char *eob
= line
+ sizeof line
- 1;
815 int word_split
= xflags
& XFLG_WORD_SPLIT
;
817 if (!fname
|| !*fname
)
820 if (*fname
!= '-' || fname
[1] || am_server
) {
821 if (server_filter_list
.head
) {
822 strlcpy(line
, fname
, sizeof line
);
823 clean_fname(line
, 1);
824 if (check_filter(&server_filter_list
, line
, 0) < 0)
827 fp
= fopen(line
, "rb");
829 fp
= fopen(fname
, "rb");
834 rprintf(FINFO
, "[%s] add_filter_file(%s,%d)%s\n",
835 who_am_i(), safe_fname(fname
), xflags
,
836 fp
? "" : " [not found]");
840 if (xflags
& XFLG_FATAL_ERRORS
) {
841 rsyserr(FERROR
, errno
,
842 "failed to open %sclude file %s",
843 xflags
& XFLG_DEF_INCLUDE
? "in" : "ex",
845 exit_cleanup(RERR_FILEIO
);
849 dirbuf
[dirbuf_len
] = '\0';
853 int ch
, overflow
= 0;
855 if ((ch
= getc(fp
)) == EOF
) {
856 if (ferror(fp
) && errno
== EINTR
)
860 if (word_split
&& isspace(ch
))
862 if (eol_nulls
? !ch
: (ch
== '\n' || ch
== '\r'))
870 rprintf(FERROR
, "discarding over-long filter: %s...\n", line
);
874 /* Skip an empty token and (when line parsing) comments. */
875 if (*line
&& (word_split
|| (*line
!= ';' && *line
!= '#')))
876 add_filter(listp
, line
, xflags
);
883 char *get_rule_prefix(int match_flags
, const char *pat
, unsigned int *plen_ptr
)
885 static char buf
[MAX_RULE_PREFIX
+1];
888 if (match_flags
& MATCHFLG_PERDIR_MERGE
) {
890 if (match_flags
& MATCHFLG_WORD_SPLIT
)
892 if (match_flags
& MATCHFLG_NO_INHERIT
)
894 if (match_flags
& MATCHFLG_EXCLUDE_SELF
)
896 if (match_flags
& MATCHFLG_NO_PREFIXES
) {
897 if (match_flags
& MATCHFLG_INCLUDE
)
903 } else if (match_flags
& MATCHFLG_INCLUDE
) {
906 } else if (protocol_version
>= 29
907 || ((*pat
== '-' || *pat
== '+') && pat
[1] == ' ')) {
913 *plen_ptr
= op
- buf
;
914 if (op
- buf
> MAX_RULE_PREFIX
)
915 overflow("get_rule_prefix");
919 void send_filter_list(int f
)
921 struct filter_struct
*ent
;
923 /* This is a complete hack - blame Rusty. FIXME!
924 * Remove this hack when older rsyncs (below 2.6.4) are gone. */
925 if (list_only
== 1 && !recurse
)
926 add_filter(&filter_list
, "/*/*", XFLG_DEF_EXCLUDE
);
928 for (ent
= filter_list
.head
; ent
; ent
= ent
->next
) {
929 unsigned int len
, plen
, dlen
;
932 len
= strlen(ent
->pattern
);
933 if (len
== 0 || len
>= MAXPATHLEN
)
935 p
= get_rule_prefix(ent
->match_flags
, ent
->pattern
, &plen
);
936 if (protocol_version
< 29 && *p
== ':') {
937 if (strcmp(p
, ":sn- ") == 0
938 && strcmp(ent
->pattern
, ".cvsignore") == 0)
941 "remote rsync is too old to understand per-directory merge files.\n");
942 exit_cleanup(RERR_SYNTAX
);
944 dlen
= ent
->match_flags
& MATCHFLG_DIRECTORY
? 1 : 0;
945 write_int(f
, plen
+ len
+ dlen
);
947 write_buf(f
, p
, plen
);
948 write_buf(f
, ent
->pattern
, len
);
957 void recv_filter_list(int f
)
959 char line
[MAXPATHLEN
+MAX_RULE_PREFIX
+1]; /* +1 for trailing slash. */
960 unsigned int xflags
= protocol_version
>= 29 ? 0 : XFLG_DEF_EXCLUDE
;
963 while ((l
= read_int(f
)) != 0) {
964 if (l
>= sizeof line
)
965 overflow("recv_filter_list");
966 read_sbuf(f
, line
, l
);
967 add_filter(&filter_list
, line
, xflags
);
972 static char default_cvsignore
[] =
973 /* These default ignored items come from the CVS manual. */
974 "RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS"
975 " .make.state .nse_depinfo *~ #* .#* ,* _$* *$"
976 " *.old *.bak *.BAK *.orig *.rej .del-*"
977 " *.a *.olb *.o *.obj *.so *.exe"
978 " *.Z *.elc *.ln core"
979 /* The rest we added to suit ourself. */
982 void add_cvs_excludes(void)
984 static unsigned int cvs_flags
= XFLG_WORD_SPLIT
| XFLG_NO_PREFIXES
986 char fname
[MAXPATHLEN
];
987 char *p
= module_id
>= 0 && lp_use_chroot(module_id
)
988 ? "/" : getenv("HOME");
990 add_filter(&filter_list
, ":C", 0);
991 add_filter(&filter_list
, default_cvsignore
, cvs_flags
);
993 if (p
&& pathjoin(fname
, MAXPATHLEN
, p
, ".cvsignore") < MAXPATHLEN
) {
994 add_filter_file(&filter_list
, fname
, cvs_flags
);
997 add_filter(&filter_list
, getenv("CVSIGNORE"), cvs_flags
);