This routine takes a per-dir merge-file entry and finishes its setup. * If the name has a path portion then we check to see if it refers to a * parent directory of the first transfer dir. If it does, we scan all the * dirs from that point through the parent dir of the transfer dir looking * for the per-dir merge-file in each one. */
| 684 | * dirs from that point through the parent dir of the transfer dir looking |
| 685 | * for the per-dir merge-file in each one. */ |
| 686 | static BOOL setup_merge_file(int mergelist_num, filter_rule *ex, |
| 687 | filter_rule_list *lp) |
| 688 | { |
| 689 | char buf[MAXPATHLEN]; |
| 690 | char *x, *y, *pat = ex->pattern; |
| 691 | unsigned int len; |
| 692 | |
| 693 | if (!(x = parse_merge_name(pat, NULL, 0)) || *x != '/') |
| 694 | return 0; |
| 695 | |
| 696 | if (DEBUG_GTE(FILTER, 2)) { |
| 697 | rprintf(FINFO, "[%s] performing parent_dirscan for mergelist #%d%s\n", |
| 698 | who_am_i(), mergelist_num, lp->debug_type); |
| 699 | } |
| 700 | y = strrchr(x, '/'); |
| 701 | *y = '\0'; |
| 702 | ex->pattern = strdup(y+1); |
| 703 | if (!*x) |
| 704 | x = "/"; |
| 705 | if (*x == '/') |
| 706 | strlcpy(buf, x, MAXPATHLEN); |
| 707 | else |
| 708 | pathjoin(buf, MAXPATHLEN, dirbuf, x); |
| 709 | |
| 710 | len = clean_fname(buf, CFN_COLLAPSE_DOT_DOT_DIRS); |
| 711 | if (len != 1 && len < MAXPATHLEN-1) { |
| 712 | buf[len++] = '/'; |
| 713 | buf[len] = '\0'; |
| 714 | } |
| 715 | /* This ensures that the specified dir is a parent of the transfer. */ |
| 716 | for (x = buf, y = dirbuf; *x && *x == *y; x++, y++) {} |
| 717 | if (*x) |
| 718 | y += strlen(y); /* nope -- skip the scan */ |
| 719 | |
| 720 | parent_dirscan = True; |
| 721 | while (*y) { |
| 722 | char save[MAXPATHLEN]; |
| 723 | /* copylen is strlen(y) which is < MAXPATHLEN. +1 for \0 */ |
| 724 | size_t copylen = strlcpy(save, y, MAXPATHLEN) + 1; |
| 725 | *y = '\0'; |
| 726 | dirbuf_len = y - dirbuf; |
| 727 | strlcpy(x, ex->pattern, MAXPATHLEN - (x - buf)); |
| 728 | parse_filter_file(lp, buf, ex, XFLG_ANCHORED2ABS); |
| 729 | if (ex->rflags & FILTRULE_NO_INHERIT) { |
| 730 | /* Free the undesired rules to clean up any per-dir |
| 731 | * mergelists they defined. Otherwise pop_local_filters |
| 732 | * may crash trying to restore nonexistent state for |
| 733 | * those mergelists. */ |
| 734 | free_filters(lp->head); |
| 735 | lp->head = NULL; |
| 736 | } |
| 737 | lp->tail = NULL; |
| 738 | strlcpy(y, save, copylen); |
| 739 | while ((*x++ = *y++) != '/') {} |
| 740 | } |
| 741 | parent_dirscan = False; |
| 742 | if (DEBUG_GTE(FILTER, 2)) { |
| 743 | rprintf(FINFO, "[%s] completed parent_dirscan for mergelist #%d%s\n", |
no test coverage detected