1/* 2 * The filter include/exclude routines. 3 * 4 * Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org> 5 * Copyright (C) 1996 Paul Mackerras 6 * Copyright (C) 2002 Martin Pool 7 * Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write to the Free Software Foundation, Inc., 21 * 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. 22 */ 23 24#include "rsync.h" 25 26extern int verbose; 27extern int am_server; 28extern int am_sender; 29extern int eol_nulls; 30extern int list_only; 31extern int recurse; 32extern int io_error; 33extern int local_server; 34extern int prune_empty_dirs; 35extern int delete_mode; 36extern int delete_excluded; 37extern int cvs_exclude; 38extern int sanitize_paths; 39extern int protocol_version; 40extern int module_id; 41 42extern char curr_dir[]; 43extern unsigned int curr_dir_len; 44extern unsigned int module_dirlen; 45 46struct filter_list_struct filter_list = { 0, 0, "" }; 47struct filter_list_struct cvs_filter_list = { 0, 0, " [global CVS]" }; 48struct filter_list_struct server_filter_list = { 0, 0, " [daemon]" }; 49 50/* Need room enough for ":MODS " prefix plus some room to grow. */ 51#define MAX_RULE_PREFIX (16) 52 53#define MODIFIERS_MERGE_FILE "-+Cenw" 54#define MODIFIERS_INCL_EXCL "/!Crs" 55#define MODIFIERS_HIDE_PROTECT "/!" 56 57/* The dirbuf is set by push_local_filters() to the current subdirectory 58 * relative to curr_dir that is being processed. The path always has a 59 * trailing slash appended, and the variable dirbuf_len contains the length 60 * of this path prefix. The path is always absolute. */ 61static char dirbuf[MAXPATHLEN+1]; 62static unsigned int dirbuf_len = 0; 63static int dirbuf_depth; 64 65/* This is True when we're scanning parent dirs for per-dir merge-files. */ 66static BOOL parent_dirscan = False; 67 68/* This array contains a list of all the currently active per-dir merge 69 * files. This makes it easier to save the appropriate values when we 70 * "push" down into each subdirectory. */ 71static struct filter_struct **mergelist_parents; 72static int mergelist_cnt = 0; 73static int mergelist_size = 0; 74 75/* Each filter_list_struct describes a singly-linked list by keeping track 76 * of both the head and tail pointers. The list is slightly unusual in that 77 * a parent-dir's content can be appended to the end of the local list in a 78 * special way: the last item in the local list has its "next" pointer set 79 * to point to the inherited list, but the local list's tail pointer points 80 * at the end of the local list. Thus, if the local list is empty, the head 81 * will be pointing at the inherited content but the tail will be NULL. To 82 * help you visualize this, here are the possible list arrangements: 83 * 84 * Completely Empty Local Content Only 85 * ================================== ==================================== 86 * head -> NULL head -> Local1 -> Local2 -> NULL 87 * tail -> NULL tail -------------^ 88 * 89 * Inherited Content Only Both Local and Inherited Content 90 * ================================== ==================================== 91 * head -> Parent1 -> Parent2 -> NULL head -> L1 -> L2 -> P1 -> P2 -> NULL 92 * tail -> NULL tail ---------^ 93 * 94 * This means that anyone wanting to traverse the whole list to use it just 95 * needs to start at the head and use the "next" pointers until it goes 96 * NULL. To add new local content, we insert the item after the tail item 97 * and update the tail (obviously, if "tail" was NULL, we insert it at the 98 * head). To clear the local list, WE MUST NOT FREE THE INHERITED CONTENT 99 * because it is shared between the current list and our parent list(s). 100 * The easiest way to handle this is to simply truncate the list after the 101 * tail item and then free the local list from the head. When inheriting 102 * the list for a new local dir, we just save off the filter_list_struct 103 * values (so we can pop back to them later) and set the tail to NULL. 104 */ 105 106static void free_filter(struct filter_struct *ex) 107{ 108 if (ex->match_flags & MATCHFLG_PERDIR_MERGE) { 109 free(ex->u.mergelist->debug_type); 110 free(ex->u.mergelist); 111 mergelist_cnt--; 112 } 113 free(ex->pattern); 114 free(ex); 115} 116 117/* Build a filter structure given a filter pattern. The value in "pat" 118 * is not null-terminated. */ 119static void add_rule(struct filter_list_struct *listp, const char *pat, 120 unsigned int pat_len, uint32 mflags, int xflags) 121{ 122 struct filter_struct *ret; 123 const char *cp; 124 unsigned int ex_len; 125 126 if (verbose > 2) { 127 rprintf(FINFO, "[%s] add_rule(%s%.*s%s)%s\n", 128 who_am_i(), get_rule_prefix(mflags, pat, 0, NULL), 129 (int)pat_len, pat, 130 (mflags & MATCHFLG_DIRECTORY) ? "/" : "", 131 listp->debug_type); 132 } 133 134 /* These flags also indicate that we're reading a list that 135 * needs to be filtered now, not post-filtered later. */ 136 if (xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH)) { 137 uint32 mf = mflags & (MATCHFLG_RECEIVER_SIDE|MATCHFLG_SENDER_SIDE); 138 if (am_sender) { 139 if (mf == MATCHFLG_RECEIVER_SIDE) 140 return; 141 } else { 142 if (mf == MATCHFLG_SENDER_SIDE) 143 return; 144 } 145 } 146 147 if (!(ret = new(struct filter_struct))) 148 out_of_memory("add_rule"); 149 memset(ret, 0, sizeof ret[0]); 150 151 if (!(mflags & (MATCHFLG_ABS_PATH | MATCHFLG_MERGE_FILE)) 152 && ((xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH) && *pat == '/') 153 || (xflags & XFLG_ABS_IF_SLASH && strchr(pat, '/') != NULL))) { 154 mflags |= MATCHFLG_ABS_PATH; 155 if (*pat == '/') 156 ex_len = dirbuf_len - module_dirlen - 1; 157 else 158 ex_len = 0; 159 } else 160 ex_len = 0; 161 if (!(ret->pattern = new_array(char, ex_len + pat_len + 1))) 162 out_of_memory("add_rule"); 163 if (ex_len) 164 memcpy(ret->pattern, dirbuf + module_dirlen, ex_len); 165 strlcpy(ret->pattern + ex_len, pat, pat_len + 1); 166 pat_len += ex_len; 167 168 if (strpbrk(ret->pattern, "*[?")) { 169 mflags |= MATCHFLG_WILD; 170 if ((cp = strstr(ret->pattern, "**")) != NULL) { 171 mflags |= MATCHFLG_WILD2; 172 /* If the pattern starts with **, note that. */ 173 if (cp == ret->pattern) 174 mflags |= MATCHFLG_WILD2_PREFIX; 175 /* If the pattern ends with ***, note that. */ 176 if (pat_len >= 3 177 && ret->pattern[pat_len-3] == '*' 178 && ret->pattern[pat_len-2] == '*' 179 && ret->pattern[pat_len-1] == '*') 180 mflags |= MATCHFLG_WILD3_SUFFIX; 181 } 182 } 183 184 if (pat_len > 1 && ret->pattern[pat_len-1] == '/') { 185 ret->pattern[pat_len-1] = 0; 186 mflags |= MATCHFLG_DIRECTORY; 187 } 188 189 if (mflags & MATCHFLG_PERDIR_MERGE) { 190 struct filter_list_struct *lp; 191 unsigned int len; 192 int i; 193 194 if ((cp = strrchr(ret->pattern, '/')) != NULL) 195 cp++; 196 else 197 cp = ret->pattern; 198 199 /* If the local merge file was already mentioned, don't 200 * add it again. */ 201 for (i = 0; i < mergelist_cnt; i++) { 202 struct filter_struct *ex = mergelist_parents[i]; 203 const char *s = strrchr(ex->pattern, '/'); 204 if (s) 205 s++; 206 else 207 s = ex->pattern; 208 len = strlen(s); 209 if (len == pat_len - (cp - ret->pattern) 210 && memcmp(s, cp, len) == 0) { 211 free_filter(ret); 212 return; 213 } 214 } 215 216 if (!(lp = new_array(struct filter_list_struct, 1))) 217 out_of_memory("add_rule"); 218 lp->head = lp->tail = NULL; 219 if (asprintf(&lp->debug_type, " [per-dir %s]", cp) < 0) 220 out_of_memory("add_rule"); 221 ret->u.mergelist = lp; 222 223 if (mergelist_cnt == mergelist_size) { 224 mergelist_size += 5; 225 mergelist_parents = realloc_array(mergelist_parents, 226 struct filter_struct *, 227 mergelist_size); 228 if (!mergelist_parents) 229 out_of_memory("add_rule"); 230 } 231 mergelist_parents[mergelist_cnt++] = ret; 232 } else { 233 for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++) 234 ret->u.slash_cnt++; 235 } 236 237 ret->match_flags = mflags; 238 239 if (!listp->tail) { 240 ret->next = listp->head; 241 listp->head = listp->tail = ret; 242 } else { 243 ret->next = listp->tail->next; 244 listp->tail->next = ret; 245 listp->tail = ret; 246 } 247} 248 249static void clear_filter_list(struct filter_list_struct *listp) 250{ 251 if (listp->tail) { 252 struct filter_struct *ent, *next; 253 /* Truncate any inherited items from the local list. */ 254 listp->tail->next = NULL; 255 /* Now free everything that is left. */ 256 for (ent = listp->head; ent; ent = next) { 257 next = ent->next; 258 free_filter(ent); 259 } 260 } 261 262 listp->head = listp->tail = NULL; 263} 264 265/* This returns an expanded (absolute) filename for the merge-file name if 266 * the name has any slashes in it OR if the parent_dirscan var is True; 267 * otherwise it returns the original merge_file name. If the len_ptr value 268 * is non-NULL the merge_file name is limited by the referenced length 269 * value and will be updated with the length of the resulting name. We 270 * always return a name that is null terminated, even if the merge_file 271 * name was not. */ 272static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr, 273 unsigned int prefix_skip) 274{ 275 static char buf[MAXPATHLEN]; 276 char *fn, tmpbuf[MAXPATHLEN]; 277 unsigned int fn_len; 278 279 if (!parent_dirscan && *merge_file != '/') { 280 /* Return the name unchanged it doesn't have any slashes. */ 281 if (len_ptr) { 282 const char *p = merge_file + *len_ptr; 283 while (--p > merge_file && *p != '/') {} 284 if (p == merge_file) { 285 strlcpy(buf, merge_file, *len_ptr + 1); 286 return buf; 287 } 288 } else if (strchr(merge_file, '/') == NULL) 289 return (char *)merge_file; 290 } 291 292 fn = *merge_file == '/' ? buf : tmpbuf; 293 if (sanitize_paths) { 294 const char *r = prefix_skip ? "/" : NULL; 295 /* null-terminate the name if it isn't already */ 296 if (len_ptr && merge_file[*len_ptr]) { 297 char *to = fn == buf ? tmpbuf : buf; 298 strlcpy(to, merge_file, *len_ptr + 1); 299 merge_file = to; 300 } 301 if (!sanitize_path(fn, merge_file, r, dirbuf_depth, NULL)) { 302 rprintf(FERROR, "merge-file name overflows: %s\n", 303 merge_file); 304 return NULL; 305 } 306 fn_len = strlen(fn); 307 } else { 308 strlcpy(fn, merge_file, len_ptr ? *len_ptr + 1 : MAXPATHLEN); 309 fn_len = clean_fname(fn, 1); 310 } 311 312 /* If the name isn't in buf yet, it's wasn't absolute. */ 313 if (fn != buf) { 314 if (dirbuf_len + fn_len >= MAXPATHLEN) { 315 rprintf(FERROR, "merge-file name overflows: %s\n", fn); 316 return NULL; 317 } 318 memcpy(buf, dirbuf + prefix_skip, dirbuf_len - prefix_skip); 319 memcpy(buf + dirbuf_len - prefix_skip, fn, fn_len + 1); 320 fn_len = clean_fname(buf, 1); 321 } 322 323 if (len_ptr) 324 *len_ptr = fn_len; 325 return buf; 326} 327 328/* Sets the dirbuf and dirbuf_len values. */ 329void set_filter_dir(const char *dir, unsigned int dirlen) 330{ 331 unsigned int len; 332 if (*dir != '/') { 333 memcpy(dirbuf, curr_dir, curr_dir_len); 334 dirbuf[curr_dir_len] = '/'; 335 len = curr_dir_len + 1; 336 if (len + dirlen >= MAXPATHLEN) 337 dirlen = 0; 338 } else 339 len = 0; 340 memcpy(dirbuf + len, dir, dirlen); 341 dirbuf[dirlen + len] = '\0'; 342 dirbuf_len = clean_fname(dirbuf, 1); 343 if (dirbuf_len > 1 && dirbuf[dirbuf_len-1] == '.' 344 && dirbuf[dirbuf_len-2] == '/') 345 dirbuf_len -= 2; 346 if (dirbuf_len != 1) 347 dirbuf[dirbuf_len++] = '/'; 348 dirbuf[dirbuf_len] = '\0'; 349 if (sanitize_paths) 350 dirbuf_depth = count_dir_elements(dirbuf + module_dirlen); 351} 352 353/* This routine takes a per-dir merge-file entry and finishes its setup. 354 * If the name has a path portion then we check to see if it refers to a 355 * parent directory of the first transfer dir. If it does, we scan all the 356 * dirs from that point through the parent dir of the transfer dir looking 357 * for the per-dir merge-file in each one. */ 358static BOOL setup_merge_file(struct filter_struct *ex, 359 struct filter_list_struct *lp) 360{ 361 char buf[MAXPATHLEN]; 362 char *x, *y, *pat = ex->pattern; 363 unsigned int len; 364 365 if (!(x = parse_merge_name(pat, NULL, 0)) || *x != '/') 366 return 0; 367 368 y = strrchr(x, '/'); 369 *y = '\0'; 370 ex->pattern = strdup(y+1); 371 if (!*x) 372 x = "/"; 373 if (*x == '/') 374 strlcpy(buf, x, MAXPATHLEN); 375 else 376 pathjoin(buf, MAXPATHLEN, dirbuf, x); 377 378 len = clean_fname(buf, 1); 379 if (len != 1 && len < MAXPATHLEN-1) { 380 buf[len++] = '/'; 381 buf[len] = '\0'; 382 } 383 /* This ensures that the specified dir is a parent of the transfer. */ 384 for (x = buf, y = dirbuf; *x && *x == *y; x++, y++) {} 385 if (*x) 386 y += strlen(y); /* nope -- skip the scan */ 387 388 parent_dirscan = True; 389 while (*y) { 390 char save[MAXPATHLEN]; 391 strlcpy(save, y, MAXPATHLEN); 392 *y = '\0'; 393 dirbuf_len = y - dirbuf; 394 strlcpy(x, ex->pattern, MAXPATHLEN - (x - buf)); 395 parse_filter_file(lp, buf, ex->match_flags, XFLG_ANCHORED2ABS); 396 if (ex->match_flags & MATCHFLG_NO_INHERIT) 397 lp->head = NULL; 398 lp->tail = NULL; 399 strlcpy(y, save, MAXPATHLEN); 400 while ((*x++ = *y++) != '/') {} 401 } 402 parent_dirscan = False; 403 free(pat); 404 return 1; 405} 406 407/* Each time rsync changes to a new directory it call this function to 408 * handle all the per-dir merge-files. The "dir" value is the current path 409 * relative to curr_dir (which might not be null-terminated). We copy it 410 * into dirbuf so that we can easily append a file name on the end. */ 411void *push_local_filters(const char *dir, unsigned int dirlen) 412{ 413 struct filter_list_struct *ap, *push; 414 int i; 415 416 set_filter_dir(dir, dirlen); 417 418 if (!mergelist_cnt) 419 return NULL; 420 421 push = new_array(struct filter_list_struct, mergelist_cnt); 422 if (!push) 423 out_of_memory("push_local_filters"); 424 425 for (i = 0, ap = push; i < mergelist_cnt; i++) { 426 memcpy(ap++, mergelist_parents[i]->u.mergelist, 427 sizeof (struct filter_list_struct)); 428 } 429 430 /* Note: parse_filter_file() might increase mergelist_cnt, so keep 431 * this loop separate from the above loop. */ 432 for (i = 0; i < mergelist_cnt; i++) { 433 struct filter_struct *ex = mergelist_parents[i]; 434 struct filter_list_struct *lp = ex->u.mergelist; 435 436 if (verbose > 2) { 437 rprintf(FINFO, "[%s] pushing filter list%s\n", 438 who_am_i(), lp->debug_type); 439 } 440 441 lp->tail = NULL; /* Switch any local rules to inherited. */ 442 if (ex->match_flags & MATCHFLG_NO_INHERIT) 443 lp->head = NULL; 444 445 if (ex->match_flags & MATCHFLG_FINISH_SETUP) { 446 ex->match_flags &= ~MATCHFLG_FINISH_SETUP; 447 if (setup_merge_file(ex, lp)) 448 set_filter_dir(dir, dirlen); 449 } 450 451 if (strlcpy(dirbuf + dirbuf_len, ex->pattern, 452 MAXPATHLEN - dirbuf_len) < MAXPATHLEN - dirbuf_len) { 453 parse_filter_file(lp, dirbuf, ex->match_flags, 454 XFLG_ANCHORED2ABS); 455 } else { 456 io_error |= IOERR_GENERAL; 457 rprintf(FINFO, 458 "cannot add local filter rules in long-named directory: %s\n", 459 full_fname(dirbuf)); 460 } 461 dirbuf[dirbuf_len] = '\0'; 462 } 463 464 return (void*)push; 465} 466 467void pop_local_filters(void *mem) 468{ 469 struct filter_list_struct *ap, *pop = (struct filter_list_struct*)mem; 470 int i; 471 472 for (i = mergelist_cnt; i-- > 0; ) { 473 struct filter_struct *ex = mergelist_parents[i]; 474 struct filter_list_struct *lp = ex->u.mergelist; 475 476 if (verbose > 2) { 477 rprintf(FINFO, "[%s] popping filter list%s\n", 478 who_am_i(), lp->debug_type); 479 } 480 481 clear_filter_list(lp); 482 } 483 484 if (!pop) 485 return; 486 487 for (i = 0, ap = pop; i < mergelist_cnt; i++) { 488 memcpy(mergelist_parents[i]->u.mergelist, ap++, 489 sizeof (struct filter_list_struct)); 490 } 491 492 free(pop); 493} 494 495static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir) 496{ 497 int slash_handling, str_cnt = 0, anchored_match = 0; 498 int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1; 499 char *p, *pattern = ex->pattern; 500 const char *strings[16]; /* more than enough */ 501 502 if (*name == '/') 503 name++; 504 if (!*name) 505 return 0; 506 507 if (!ex->u.slash_cnt && !(ex->match_flags & MATCHFLG_WILD2)) { 508 /* If the pattern does not have any slashes AND it does 509 * not have a "**" (which could match a slash), then we 510 * just match the name portion of the path. */ 511 if ((p = strrchr(name,'/')) != NULL) 512 name = p+1; 513 } else if (ex->match_flags & MATCHFLG_ABS_PATH && *name != '/' 514 && curr_dir_len > module_dirlen + 1) { 515 /* If we're matching against an absolute-path pattern, 516 * we need to prepend our full path info. */ 517 strings[str_cnt++] = curr_dir + module_dirlen + 1; 518 strings[str_cnt++] = "/"; 519 } else if (ex->match_flags & MATCHFLG_WILD2_PREFIX && *name != '/') { 520 /* Allow "**"+"/" to match at the start of the string. */ 521 strings[str_cnt++] = "/"; 522 } 523 strings[str_cnt++] = name; 524 if (name_is_dir) { 525 /* Allow a trailing "/"+"***" to match the directory. */ 526 if (ex->match_flags & MATCHFLG_WILD3_SUFFIX) 527 strings[str_cnt++] = "/"; 528 } else if (ex->match_flags & MATCHFLG_DIRECTORY) 529 return !ret_match; 530 strings[str_cnt] = NULL; 531 532 if (*pattern == '/') { 533 anchored_match = 1; 534 pattern++; 535 } 536 537 if (!anchored_match && ex->u.slash_cnt 538 && !(ex->match_flags & MATCHFLG_WILD2)) { 539 /* A non-anchored match with an infix slash and no "**" 540 * needs to match the last slash_cnt+1 name elements. */ 541 slash_handling = ex->u.slash_cnt + 1; 542 } else if (!anchored_match && !(ex->match_flags & MATCHFLG_WILD2_PREFIX) 543 && ex->match_flags & MATCHFLG_WILD2) { 544 /* A non-anchored match with an infix or trailing "**" (but not 545 * a prefixed "**") needs to try matching after every slash. */ 546 slash_handling = -1; 547 } else { 548 /* The pattern matches only at the start of the path or name. */ 549 slash_handling = 0; 550 } 551 552 if (ex->match_flags & MATCHFLG_WILD) { 553 if (wildmatch_array(pattern, strings, slash_handling)) 554 return ret_match; 555 } else if (str_cnt > 1) { 556 if (litmatch_array(pattern, strings, slash_handling)) 557 return ret_match; 558 } else if (anchored_match) { 559 if (strcmp(name, pattern) == 0) 560 return ret_match; 561 } else { 562 int l1 = strlen(name); 563 int l2 = strlen(pattern); 564 if (l2 <= l1 && 565 strcmp(name+(l1-l2),pattern) == 0 && 566 (l1==l2 || name[l1-(l2+1)] == '/')) { 567 return ret_match; 568 } 569 } 570 571 return !ret_match; 572} 573 574 575static void report_filter_result(char const *name, 576 struct filter_struct const *ent, 577 int name_is_dir, const char *type) 578{ 579 /* If a trailing slash is present to match only directories, 580 * then it is stripped out by add_rule(). So as a special 581 * case we add it back in here. */ 582 583 if (verbose >= 2) { 584 static char *actions[2][2] 585 = { {"show", "hid"}, {"risk", "protect"} }; 586 const char *w = who_am_i(); 587 rprintf(FINFO, "[%s] %sing %s %s because of pattern %s%s%s\n", 588 w, actions[*w!='s'][!(ent->match_flags&MATCHFLG_INCLUDE)], 589 name_is_dir ? "directory" : "file", name, ent->pattern, 590 ent->match_flags & MATCHFLG_DIRECTORY ? "/" : "", type); 591 } 592} 593 594 595/* 596 * Return -1 if file "name" is defined to be excluded by the specified 597 * exclude list, 1 if it is included, and 0 if it was not matched. 598 */ 599int check_filter(struct filter_list_struct *listp, char *name, int name_is_dir) 600{ 601 struct filter_struct *ent; 602 603 for (ent = listp->head; ent; ent = ent->next) { 604 if (ent->match_flags & MATCHFLG_PERDIR_MERGE) { 605 int rc = check_filter(ent->u.mergelist, name, 606 name_is_dir); 607 if (rc) 608 return rc; 609 continue; 610 } 611 if (ent->match_flags & MATCHFLG_CVS_IGNORE) { 612 int rc = check_filter(&cvs_filter_list, name, 613 name_is_dir); 614 if (rc) 615 return rc; 616 continue; 617 } 618 if (rule_matches(name, ent, name_is_dir)) { 619 report_filter_result(name, ent, name_is_dir, 620 listp->debug_type); 621 return ent->match_flags & MATCHFLG_INCLUDE ? 1 : -1; 622 } 623 } 624 625 return 0; 626} 627 628#define RULE_STRCMP(s,r) rule_strcmp((s), (r), sizeof (r) - 1) 629 630static const uchar *rule_strcmp(const uchar *str, const char *rule, int rule_len) 631{ 632 if (strncmp((char*)str, rule, rule_len) != 0) 633 return NULL; 634 if (isspace(str[rule_len]) || str[rule_len] == '_' || !str[rule_len]) 635 return str + rule_len - 1; 636 if (str[rule_len] == ',') 637 return str + rule_len; 638 return NULL; 639} 640 641/* Get the next include/exclude arg from the string. The token will not 642 * be '\0' terminated, so use the returned length to limit the string. 643 * Also, be sure to add this length to the returned pointer before passing 644 * it back to ask for the next token. This routine parses the "!" (list- 645 * clearing) token and (depending on the mflags) the various prefixes. 646 * The *mflags_ptr value will be set on exit to the new MATCHFLG_* bits 647 * for the current token. */ 648static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags, 649 unsigned int *len_ptr, uint32 *mflags_ptr) 650{ 651 const uchar *s = (const uchar *)p; 652 uint32 new_mflags; 653 unsigned int len; 654 655 if (mflags & MATCHFLG_WORD_SPLIT) { 656 /* Skip over any initial whitespace. */ 657 while (isspace(*s)) 658 s++; 659 /* Update to point to real start of rule. */ 660 p = (const char *)s; 661 } 662 if (!*s) 663 return NULL; 664 665 new_mflags = mflags & MATCHFLGS_FROM_CONTAINER; 666 667 /* Figure out what kind of a filter rule "s" is pointing at. Note 668 * that if MATCHFLG_NO_PREFIXES is set, the rule is either an include 669 * or an exclude based on the inheritance of the MATCHFLG_INCLUDE 670 * flag (above). XFLG_OLD_PREFIXES indicates a compatibility mode 671 * for old include/exclude patterns where just "+ " and "- " are 672 * allowed as optional prefixes. */ 673 if (mflags & MATCHFLG_NO_PREFIXES) { 674 if (*s == '!' && mflags & MATCHFLG_CVS_IGNORE) 675 new_mflags |= MATCHFLG_CLEAR_LIST; /* Tentative! */ 676 } else if (xflags & XFLG_OLD_PREFIXES) { 677 if (*s == '-' && s[1] == ' ') { 678 new_mflags &= ~MATCHFLG_INCLUDE; 679 s += 2; 680 } else if (*s == '+' && s[1] == ' ') { 681 new_mflags |= MATCHFLG_INCLUDE; 682 s += 2; 683 } else if (*s == '!') 684 new_mflags |= MATCHFLG_CLEAR_LIST; /* Tentative! */ 685 } else { 686 char ch = 0, *mods = ""; 687 switch (*s) { 688 case 'c': 689 if ((s = RULE_STRCMP(s, "clear")) != NULL) 690 ch = '!'; 691 break; 692 case 'd': 693 if ((s = RULE_STRCMP(s, "dir-merge")) != NULL) 694 ch = ':'; 695 break; 696 case 'e': 697 if ((s = RULE_STRCMP(s, "exclude")) != NULL) 698 ch = '-'; 699 break; 700 case 'h': 701 if ((s = RULE_STRCMP(s, "hide")) != NULL) 702 ch = 'H'; 703 break; 704 case 'i': 705 if ((s = RULE_STRCMP(s, "include")) != NULL) 706 ch = '+'; 707 break; 708 case 'm': 709 if ((s = RULE_STRCMP(s, "merge")) != NULL) 710 ch = '.'; 711 break; 712 case 'p': 713 if ((s = RULE_STRCMP(s, "protect")) != NULL) 714 ch = 'P'; 715 break; 716 case 'r': 717 if ((s = RULE_STRCMP(s, "risk")) != NULL) 718 ch = 'R'; 719 break; 720 case 's': 721 if ((s = RULE_STRCMP(s, "show")) != NULL) 722 ch = 'S'; 723 break; 724 default: 725 ch = *s; 726 if (s[1] == ',') 727 s++; 728 break; 729 } 730 switch (ch) { 731 case ':': 732 new_mflags |= MATCHFLG_PERDIR_MERGE 733 | MATCHFLG_FINISH_SETUP; 734 /* FALL THROUGH */ 735 case '.': 736 new_mflags |= MATCHFLG_MERGE_FILE; 737 mods = MODIFIERS_INCL_EXCL MODIFIERS_MERGE_FILE; 738 break; 739 case '+': 740 new_mflags |= MATCHFLG_INCLUDE; 741 /* FALL THROUGH */ 742 case '-': 743 mods = MODIFIERS_INCL_EXCL; 744 break; 745 case 'S': 746 new_mflags |= MATCHFLG_INCLUDE; 747 /* FALL THROUGH */ 748 case 'H': 749 new_mflags |= MATCHFLG_SENDER_SIDE; 750 mods = MODIFIERS_HIDE_PROTECT; 751 break; 752 case 'R': 753 new_mflags |= MATCHFLG_INCLUDE; 754 /* FALL THROUGH */ 755 case 'P': 756 new_mflags |= MATCHFLG_RECEIVER_SIDE; 757 mods = MODIFIERS_HIDE_PROTECT; 758 break; 759 case '!': 760 new_mflags |= MATCHFLG_CLEAR_LIST; 761 mods = NULL; 762 break; 763 default: 764 rprintf(FERROR, "Unknown filter rule: `%s'\n", p); 765 exit_cleanup(RERR_SYNTAX); 766 } 767 while (mods && *++s && *s != ' ' && *s != '_') { 768 if (strchr(mods, *s) == NULL) { 769 if (mflags & MATCHFLG_WORD_SPLIT && isspace(*s)) { 770 s--; 771 break; 772 } 773 invalid: 774 rprintf(FERROR, 775 "invalid modifier sequence at '%c' in filter rule: %s\n", 776 *s, p); 777 exit_cleanup(RERR_SYNTAX); 778 } 779 switch (*s) { 780 case '-': 781 if (new_mflags & MATCHFLG_NO_PREFIXES) 782 goto invalid; 783 new_mflags |= MATCHFLG_NO_PREFIXES; 784 break; 785 case '+': 786 if (new_mflags & MATCHFLG_NO_PREFIXES) 787 goto invalid; 788 new_mflags |= MATCHFLG_NO_PREFIXES 789 | MATCHFLG_INCLUDE; 790 break; 791 case '/': 792 new_mflags |= MATCHFLG_ABS_PATH; 793 break; 794 case '!': 795 new_mflags |= MATCHFLG_NEGATE; 796 break; 797 case 'C': 798 if (new_mflags & MATCHFLG_NO_PREFIXES) 799 goto invalid; 800 new_mflags |= MATCHFLG_NO_PREFIXES 801 | MATCHFLG_WORD_SPLIT 802 | MATCHFLG_NO_INHERIT 803 | MATCHFLG_CVS_IGNORE; 804 break; 805 case 'e': 806 new_mflags |= MATCHFLG_EXCLUDE_SELF; 807 break; 808 case 'n': 809 new_mflags |= MATCHFLG_NO_INHERIT; 810 break; 811 case 'r': 812 new_mflags |= MATCHFLG_RECEIVER_SIDE; 813 break; 814 case 's': 815 new_mflags |= MATCHFLG_SENDER_SIDE; 816 break; 817 case 'w': 818 new_mflags |= MATCHFLG_WORD_SPLIT; 819 break; 820 } 821 } 822 if (*s) 823 s++; 824 } 825 826 if (mflags & MATCHFLG_WORD_SPLIT) { 827 const uchar *cp = s; 828 /* Token ends at whitespace or the end of the string. */ 829 while (!isspace(*cp) && *cp != '\0') 830 cp++; 831 len = cp - s; 832 } else 833 len = strlen((char*)s); 834 835 if (new_mflags & MATCHFLG_CLEAR_LIST) { 836 if (!(mflags & MATCHFLG_NO_PREFIXES) 837 && !(xflags & XFLG_OLD_PREFIXES) && len) { 838 rprintf(FERROR, 839 "'!' rule has trailing characters: %s\n", p); 840 exit_cleanup(RERR_SYNTAX); 841 } 842 if (len > 1) 843 new_mflags &= ~MATCHFLG_CLEAR_LIST; 844 } else if (!len && !(new_mflags & MATCHFLG_CVS_IGNORE)) { 845 rprintf(FERROR, "unexpected end of filter rule: %s\n", p); 846 exit_cleanup(RERR_SYNTAX); 847 } 848 849 /* --delete-excluded turns an un-modified include/exclude into a 850 * sender-side rule. We also affect per-dir merge files that take 851 * no prefixes as a simple optimization. */ 852 if (delete_excluded 853 && !(new_mflags & (MATCHFLG_RECEIVER_SIDE|MATCHFLG_SENDER_SIDE)) 854 && (!(new_mflags & MATCHFLG_PERDIR_MERGE) 855 || new_mflags & MATCHFLG_NO_PREFIXES)) 856 new_mflags |= MATCHFLG_SENDER_SIDE; 857 858 *len_ptr = len; 859 *mflags_ptr = new_mflags; 860 return (const char *)s; 861} 862 863 864static char default_cvsignore[] = 865 /* These default ignored items come from the CVS manual. */ 866 "RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS" 867 " .make.state .nse_depinfo *~ #* .#* ,* _$* *$" 868 " *.old *.bak *.BAK *.orig *.rej .del-*" 869 " *.a *.olb *.o *.obj *.so *.exe" 870 " *.Z *.elc *.ln core" 871 /* The rest we added to suit ourself. */ 872 " .svn/ .bzr/"; 873 874static void get_cvs_excludes(uint32 mflags) 875{ 876 char *p, fname[MAXPATHLEN]; 877 static int initialized = 0; 878 879 if (initialized) 880 return; 881 initialized = 1; 882 883 parse_rule(&cvs_filter_list, default_cvsignore, mflags, 0); 884 885 p = module_id >= 0 && lp_use_chroot(module_id) ? "/" : getenv("HOME"); 886 if (p && pathjoin(fname, MAXPATHLEN, p, ".cvsignore") < MAXPATHLEN) 887 parse_filter_file(&cvs_filter_list, fname, mflags, 0); 888 889 parse_rule(&cvs_filter_list, getenv("CVSIGNORE"), mflags, 0); 890} 891 892 893void parse_rule(struct filter_list_struct *listp, const char *pattern, 894 uint32 mflags, int xflags) 895{ 896 unsigned int pat_len; 897 uint32 new_mflags; 898 const char *cp, *p; 899 900 if (!pattern) 901 return; 902 903 while (1) { 904 /* Remember that the returned string is NOT '\0' terminated! */ 905 cp = parse_rule_tok(pattern, mflags, xflags, 906 &pat_len, &new_mflags); 907 if (!cp) 908 break; 909 910 pattern = cp + pat_len; 911 912 if (pat_len >= MAXPATHLEN) { 913 rprintf(FERROR, "discarding over-long filter: %.*s\n", 914 (int)pat_len, cp); 915 continue; 916 } 917 918 if (new_mflags & MATCHFLG_CLEAR_LIST) { 919 if (verbose > 2) { 920 rprintf(FINFO, 921 "[%s] clearing filter list%s\n", 922 who_am_i(), listp->debug_type); 923 } 924 clear_filter_list(listp); 925 continue; 926 } 927 928 if (new_mflags & MATCHFLG_MERGE_FILE) { 929 unsigned int len; 930 if (!pat_len) { 931 cp = ".cvsignore"; 932 pat_len = 10; 933 } 934 len = pat_len; 935 if (new_mflags & MATCHFLG_EXCLUDE_SELF) { 936 const char *name = cp + len; 937 while (name > cp && name[-1] != '/') name--; 938 len -= name - cp; 939 add_rule(listp, name, len, 0, 0); 940 new_mflags &= ~MATCHFLG_EXCLUDE_SELF; 941 len = pat_len; 942 } 943 if (new_mflags & MATCHFLG_PERDIR_MERGE) { 944 if (parent_dirscan) { 945 if (!(p = parse_merge_name(cp, &len, 946 module_dirlen))) 947 continue; 948 add_rule(listp, p, len, new_mflags, 0); 949 continue; 950 } 951 } else { 952 if (!(p = parse_merge_name(cp, &len, 0))) 953 continue; 954 parse_filter_file(listp, p, new_mflags, 955 XFLG_FATAL_ERRORS); 956 continue; 957 } 958 } 959 960 add_rule(listp, cp, pat_len, new_mflags, xflags); 961 962 if (new_mflags & MATCHFLG_CVS_IGNORE 963 && !(new_mflags & MATCHFLG_MERGE_FILE)) 964 get_cvs_excludes(new_mflags); 965 } 966} 967 968 969void parse_filter_file(struct filter_list_struct *listp, const char *fname, 970 uint32 mflags, int xflags) 971{ 972 FILE *fp; 973 char line[BIGPATHBUFLEN]; 974 char *eob = line + sizeof line - 1; 975 int word_split = mflags & MATCHFLG_WORD_SPLIT; 976 977 if (!fname || !*fname) 978 return; 979 980 if (*fname != '-' || fname[1] || am_server) { 981 if (server_filter_list.head) { 982 strlcpy(line, fname, sizeof line); 983 clean_fname(line, 1); 984 if (check_filter(&server_filter_list, line, 0) < 0) 985 fp = NULL; 986 else 987 fp = fopen(line, "rb"); 988 } else 989 fp = fopen(fname, "rb"); 990 } else 991 fp = stdin; 992 993 if (verbose > 2) { 994 rprintf(FINFO, "[%s] parse_filter_file(%s,%x,%x)%s\n", 995 who_am_i(), fname, mflags, xflags, 996 fp ? "" : " [not found]"); 997 } 998 999 if (!fp) { 1000 if (xflags & XFLG_FATAL_ERRORS) { 1001 rsyserr(FERROR, errno, 1002 "failed to open %sclude file %s", 1003 mflags & MATCHFLG_INCLUDE ? "in" : "ex", 1004 fname); 1005 exit_cleanup(RERR_FILEIO); 1006 } 1007 return; 1008 } 1009 dirbuf[dirbuf_len] = '\0'; 1010 1011 while (1) { 1012 char *s = line; 1013 int ch, overflow = 0; 1014 while (1) { 1015 if ((ch = getc(fp)) == EOF) { 1016 if (ferror(fp) && errno == EINTR) { 1017 clearerr(fp); 1018 continue; 1019 } 1020 break; 1021 } 1022 if (word_split && isspace(ch)) 1023 break; 1024 if (eol_nulls? !ch : (ch == '\n' || ch == '\r')) 1025 break; 1026 if (s < eob) 1027 *s++ = ch; 1028 else 1029 overflow = 1; 1030 } 1031 if (overflow) { 1032 rprintf(FERROR, "discarding over-long filter: %s...\n", line); 1033 s = line; 1034 } 1035 *s = '\0'; 1036 /* Skip an empty token and (when line parsing) comments. */ 1037 if (*line && (word_split || (*line != ';' && *line != '#'))) 1038 parse_rule(listp, line, mflags, xflags); 1039 if (ch == EOF) 1040 break; 1041 } 1042 fclose(fp); 1043} 1044 1045/* If the "for_xfer" flag is set, the prefix is made compatible with the 1046 * current protocol_version (if possible) or a NULL is returned (if not 1047 * possible). */ 1048char *get_rule_prefix(int match_flags, const char *pat, int for_xfer, 1049 unsigned int *plen_ptr) 1050{ 1051 static char buf[MAX_RULE_PREFIX+1]; 1052 char *op = buf; 1053 int legal_len = for_xfer && protocol_version < 29 ? 1 : MAX_RULE_PREFIX-1; 1054 1055 if (match_flags & MATCHFLG_PERDIR_MERGE) { 1056 if (legal_len == 1) 1057 return NULL; 1058 *op++ = ':'; 1059 } else if (match_flags & MATCHFLG_INCLUDE) 1060 *op++ = '+'; 1061 else if (legal_len != 1 1062 || ((*pat == '-' || *pat == '+') && pat[1] == ' ')) 1063 *op++ = '-'; 1064 else 1065 legal_len = 0; 1066 1067 if (match_flags & MATCHFLG_CVS_IGNORE) 1068 *op++ = 'C'; 1069 else { 1070 if (match_flags & MATCHFLG_NO_INHERIT) 1071 *op++ = 'n'; 1072 if (match_flags & MATCHFLG_WORD_SPLIT) 1073 *op++ = 'w'; 1074 if (match_flags & MATCHFLG_NO_PREFIXES) { 1075 if (match_flags & MATCHFLG_INCLUDE) 1076 *op++ = '+'; 1077 else 1078 *op++ = '-'; 1079 } 1080 } 1081 if (match_flags & MATCHFLG_EXCLUDE_SELF) 1082 *op++ = 'e'; 1083 if (match_flags & MATCHFLG_SENDER_SIDE 1084 && (!for_xfer || protocol_version >= 29)) 1085 *op++ = 's'; 1086 if (match_flags & MATCHFLG_RECEIVER_SIDE 1087 && (!for_xfer || protocol_version >= 29 1088 || (delete_excluded && am_sender))) 1089 *op++ = 'r'; 1090 if (op - buf > legal_len) 1091 return NULL; 1092 if (legal_len) 1093 *op++ = ' '; 1094 *op = '\0'; 1095 if (plen_ptr) 1096 *plen_ptr = op - buf; 1097 return buf; 1098} 1099 1100static void send_rules(int f_out, struct filter_list_struct *flp) 1101{ 1102 struct filter_struct *ent, *prev = NULL; 1103 1104 for (ent = flp->head; ent; ent = ent->next) { 1105 unsigned int len, plen, dlen; 1106 int elide = 0; 1107 char *p; 1108 1109 /* Note we need to check delete_excluded here in addition to 1110 * the code in parse_rule_tok() because some rules may have 1111 * been added before we found the --delete-excluded option. 1112 * We must also elide any CVS merge-file rules to avoid a 1113 * backward compatibility problem, and we elide any no-prefix 1114 * merge files as an optimization (since they can only have 1115 * include/exclude rules). */ 1116 if (ent->match_flags & MATCHFLG_SENDER_SIDE) 1117 elide = am_sender ? 1 : -1; 1118 if (ent->match_flags & MATCHFLG_RECEIVER_SIDE) 1119 elide = elide ? 0 : am_sender ? -1 : 1; 1120 else if (delete_excluded && !elide 1121 && (!(ent->match_flags & MATCHFLG_PERDIR_MERGE) 1122 || ent->match_flags & MATCHFLG_NO_PREFIXES)) 1123 elide = am_sender ? 1 : -1; 1124 if (elide < 0) { 1125 if (prev) 1126 prev->next = ent->next; 1127 else 1128 flp->head = ent->next; 1129 } else 1130 prev = ent; 1131 if (elide > 0) 1132 continue; 1133 if (ent->match_flags & MATCHFLG_CVS_IGNORE 1134 && !(ent->match_flags & MATCHFLG_MERGE_FILE)) { 1135 int f = am_sender || protocol_version < 29 ? f_out : -2; 1136 send_rules(f, &cvs_filter_list); 1137 if (f == f_out) 1138 continue; 1139 } 1140 p = get_rule_prefix(ent->match_flags, ent->pattern, 1, &plen); 1141 if (!p) { 1142 rprintf(FERROR, 1143 "filter rules are too modern for remote rsync.\n"); 1144 exit_cleanup(RERR_SYNTAX); 1145 } 1146 if (f_out < 0) 1147 continue; 1148 len = strlen(ent->pattern); 1149 dlen = ent->match_flags & MATCHFLG_DIRECTORY ? 1 : 0; 1150 if (!(plen + len + dlen)) 1151 continue; 1152 write_int(f_out, plen + len + dlen); 1153 if (plen) 1154 write_buf(f_out, p, plen); 1155 write_buf(f_out, ent->pattern, len); 1156 if (dlen) 1157 write_byte(f_out, '/'); 1158 } 1159 flp->tail = prev; 1160} 1161 1162/* This is only called by the client. */ 1163void send_filter_list(int f_out) 1164{ 1165 int receiver_wants_list = prune_empty_dirs 1166 || (delete_mode && (!delete_excluded || protocol_version >= 29)); 1167 1168 if (local_server || (am_sender && !receiver_wants_list)) 1169 f_out = -1; 1170 if (cvs_exclude && am_sender) { 1171 if (protocol_version >= 29) 1172 parse_rule(&filter_list, ":C", 0, 0); 1173 parse_rule(&filter_list, "-C", 0, 0); 1174 } 1175 1176 /* This is a complete hack - blame Rusty. FIXME! 1177 * Remove this hack when older rsyncs (below 2.6.4) are gone. */ 1178 if (list_only == 1 && !recurse) 1179 parse_rule(&filter_list, "/*/*", MATCHFLG_NO_PREFIXES, 0); 1180 1181 send_rules(f_out, &filter_list); 1182 1183 if (f_out >= 0) 1184 write_int(f_out, 0); 1185 1186 if (cvs_exclude) { 1187 if (!am_sender || protocol_version < 29) 1188 parse_rule(&filter_list, ":C", 0, 0); 1189 if (!am_sender) 1190 parse_rule(&filter_list, "-C", 0, 0); 1191 } 1192} 1193 1194/* This is only called by the server. */ 1195void recv_filter_list(int f_in) 1196{ 1197 char line[BIGPATHBUFLEN]; 1198 int xflags = protocol_version >= 29 ? 0 : XFLG_OLD_PREFIXES; 1199 int receiver_wants_list = prune_empty_dirs 1200 || (delete_mode 1201 && (!delete_excluded || protocol_version >= 29)); 1202 unsigned int len; 1203 1204 if (!local_server && (am_sender || receiver_wants_list)) { 1205 while ((len = read_int(f_in)) != 0) { 1206 if (len >= sizeof line) 1207 overflow_exit("recv_rules"); 1208 read_sbuf(f_in, line, len); 1209 parse_rule(&filter_list, line, 0, xflags); 1210 } 1211 } 1212 1213 if (cvs_exclude) { 1214 if (local_server || am_sender || protocol_version < 29) 1215 parse_rule(&filter_list, ":C", 0, 0); 1216 if (local_server || am_sender) 1217 parse_rule(&filter_list, "-C", 0, 0); 1218 } 1219 1220 if (local_server) /* filter out any rules that aren't for us. */ 1221 send_rules(-1, &filter_list); 1222} 1223