version 1.1.1.2, 2013/10/14 07:51:14
|
version 1.1.1.3, 2016/11/01 09:54:32
|
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-2013 Wayne Davison | * Copyright (C) 2003-2015 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 100 static int mergelist_size = 0;
|
Line 100 static int mergelist_size = 0;
|
|
|
static void teardown_mergelist(filter_rule *ex) |
static void teardown_mergelist(filter_rule *ex) |
{ |
{ |
|
int j; |
|
|
|
if (!ex->u.mergelist) |
|
return; |
|
|
if (DEBUG_GTE(FILTER, 2)) { |
if (DEBUG_GTE(FILTER, 2)) { |
rprintf(FINFO, "[%s] deactivating mergelist #%d%s\n", |
rprintf(FINFO, "[%s] deactivating mergelist #%d%s\n", |
who_am_i(), mergelist_cnt - 1, |
who_am_i(), mergelist_cnt - 1, |
ex->u.mergelist->debug_type); |
ex->u.mergelist->debug_type); |
} |
} |
|
|
/* We should deactivate mergelists in LIFO order. */ |
|
assert(mergelist_cnt > 0); |
|
assert(ex == mergelist_parents[mergelist_cnt - 1]); |
|
|
|
/* The parent_dirscan filters should have been freed. */ |
|
assert(ex->u.mergelist->parent_dirscan_head == NULL); |
|
|
|
free(ex->u.mergelist->debug_type); |
free(ex->u.mergelist->debug_type); |
free(ex->u.mergelist); |
free(ex->u.mergelist); |
mergelist_cnt--; | |
| for (j = 0; j < mergelist_cnt; j++) { |
| if (mergelist_parents[j] == ex) { |
| mergelist_parents[j] = NULL; |
| break; |
| } |
| } |
| while (mergelist_cnt && mergelist_parents[mergelist_cnt-1] == NULL) |
| mergelist_cnt--; |
} |
} |
|
|
static void free_filter(filter_rule *ex) |
static void free_filter(filter_rule *ex) |
{ |
{ |
|
if (ex->rflags & FILTRULE_PERDIR_MERGE) |
|
teardown_mergelist(ex); |
free(ex->pattern); |
free(ex->pattern); |
free(ex); |
free(ex); |
} |
} |
|
|
static void free_filters(filter_rule *head) | static void free_filters(filter_rule *ent) |
{ |
{ |
filter_rule *rev_head = NULL; | while (ent) { |
| filter_rule *next = ent->next; |
/* Reverse the list so we deactivate mergelists in the proper LIFO | free_filter(ent); |
* order. */ | ent = next; |
while (head) { | |
filter_rule *next = head->next; | |
head->next = rev_head; | |
rev_head = head; | |
head = next; | |
} |
} |
|
|
while (rev_head) { |
|
filter_rule *prev = rev_head->next; |
|
/* Tear down mergelists here, not in free_filter, so that we |
|
* affect only real filter lists and not temporarily allocated |
|
* filters. */ |
|
if (rev_head->rflags & FILTRULE_PERDIR_MERGE) |
|
teardown_mergelist(rev_head); |
|
free_filter(rev_head); |
|
rev_head = prev; |
|
} |
|
} |
} |
|
|
/* Build a filter structure given a filter pattern. The value in "pat" |
/* Build a filter structure given a filter pattern. The value in "pat" |
Line 252 static void add_rule(filter_rule_list *listp, const ch
|
Line 244 static void add_rule(filter_rule_list *listp, const ch
|
* add it again. */ |
* add it again. */ |
for (i = 0; i < mergelist_cnt; i++) { |
for (i = 0; i < mergelist_cnt; i++) { |
filter_rule *ex = mergelist_parents[i]; |
filter_rule *ex = mergelist_parents[i]; |
const char *s = strrchr(ex->pattern, '/'); | const char *s; |
| if (!ex) |
| continue; |
| s = strrchr(ex->pattern, '/'); |
if (s) |
if (s) |
s++; |
s++; |
else |
else |
Line 264 static void add_rule(filter_rule_list *listp, const ch
|
Line 259 static void add_rule(filter_rule_list *listp, const ch
|
} |
} |
} |
} |
|
|
if (!(lp = new_array(filter_rule_list, 1))) | if (!(lp = new_array0(filter_rule_list, 1))) |
out_of_memory("add_rule"); |
out_of_memory("add_rule"); |
lp->head = lp->tail = lp->parent_dirscan_head = NULL; |
|
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; |
Line 297 static void add_rule(filter_rule_list *listp, const ch
|
Line 291 static void add_rule(filter_rule_list *listp, const ch
|
} |
} |
} |
} |
|
|
static void clear_filter_list(filter_rule_list *listp) | /* This frees any non-inherited items, leaving just inherited items on the list. */ |
| static void pop_filter_list(filter_rule_list *listp) |
{ |
{ |
if (listp->tail) { | filter_rule *inherited; |
/* Truncate any inherited items from the local list. */ | |
listp->tail->next = NULL; | |
/* Now free everything that is left. */ | |
free_filters(listp->head); | |
} | |
|
|
listp->head = listp->tail = NULL; | if (!listp->tail) |
| return; |
| |
| inherited = listp->tail->next; |
| |
| /* Truncate any inherited items from the local list. */ |
| listp->tail->next = NULL; |
| /* Now free everything that is left. */ |
| free_filters(listp->head); |
| |
| listp->head = inherited; |
| listp->tail = NULL; |
} |
} |
|
|
/* This returns an expanded (absolute) filename for the merge-file name if |
/* This returns an expanded (absolute) filename for the merge-file name if |
Line 356 static char *parse_merge_name(const char *merge_file,
|
Line 357 static char *parse_merge_name(const char *merge_file,
|
fn_len = clean_fname(fn, CFN_COLLAPSE_DOT_DOT_DIRS); |
fn_len = clean_fname(fn, CFN_COLLAPSE_DOT_DOT_DIRS); |
} |
} |
|
|
/* If the name isn't in buf yet, it's wasn't absolute. */ | /* If the name isn't in buf yet, it wasn't absolute. */ |
if (fn != buf) { |
if (fn != buf) { |
int d_len = dirbuf_len - prefix_skip; |
int d_len = dirbuf_len - prefix_skip; |
if (d_len + fn_len >= MAXPATHLEN) { |
if (d_len + fn_len >= MAXPATHLEN) { |
Line 457 static BOOL setup_merge_file(int mergelist_num, filter
|
Line 458 static BOOL setup_merge_file(int mergelist_num, filter
|
strlcpy(y, save, MAXPATHLEN); |
strlcpy(y, save, MAXPATHLEN); |
while ((*x++ = *y++) != '/') {} |
while ((*x++ = *y++) != '/') {} |
} |
} |
/* Save current head for freeing when the mergelist becomes inactive. */ |
|
lp->parent_dirscan_head = lp->head; |
|
parent_dirscan = False; |
parent_dirscan = False; |
if (DEBUG_GTE(FILTER, 2)) { |
if (DEBUG_GTE(FILTER, 2)) { |
rprintf(FINFO, "[%s] completed parent_dirscan for mergelist #%d%s\n", |
rprintf(FINFO, "[%s] completed parent_dirscan for mergelist #%d%s\n", |
Line 501 void *push_local_filters(const char *dir, unsigned int
|
Line 500 void *push_local_filters(const char *dir, unsigned int
|
|
|
push->mergelist_cnt = mergelist_cnt; |
push->mergelist_cnt = mergelist_cnt; |
for (i = 0; i < mergelist_cnt; i++) { |
for (i = 0; i < mergelist_cnt; i++) { |
memcpy(&push->mergelists[i], mergelist_parents[i]->u.mergelist, | filter_rule *ex = mergelist_parents[i]; |
sizeof (filter_rule_list)); | if (!ex) |
| continue; |
| memcpy(&push->mergelists[i], ex->u.mergelist, sizeof (filter_rule_list)); |
} |
} |
|
|
/* Note: parse_filter_file() might increase mergelist_cnt, so keep |
/* Note: parse_filter_file() might increase mergelist_cnt, so keep |
* this loop separate from the above loop. */ |
* this loop separate from the above loop. */ |
for (i = 0; i < mergelist_cnt; i++) { |
for (i = 0; i < mergelist_cnt; i++) { |
filter_rule *ex = mergelist_parents[i]; |
filter_rule *ex = mergelist_parents[i]; |
filter_rule_list *lp = ex->u.mergelist; | filter_rule_list *lp; |
| if (!ex) |
| continue; |
| lp = ex->u.mergelist; |
|
|
if (DEBUG_GTE(FILTER, 2)) { |
if (DEBUG_GTE(FILTER, 2)) { |
rprintf(FINFO, "[%s] pushing mergelist #%d%s\n", |
rprintf(FINFO, "[%s] pushing mergelist #%d%s\n", |
Line 553 void pop_local_filters(void *mem)
|
Line 557 void pop_local_filters(void *mem)
|
|
|
for (i = mergelist_cnt; i-- > 0; ) { |
for (i = mergelist_cnt; i-- > 0; ) { |
filter_rule *ex = mergelist_parents[i]; |
filter_rule *ex = mergelist_parents[i]; |
filter_rule_list *lp = ex->u.mergelist; | filter_rule_list *lp; |
| if (!ex) |
| continue; |
| lp = ex->u.mergelist; |
|
|
if (DEBUG_GTE(FILTER, 2)) { |
if (DEBUG_GTE(FILTER, 2)) { |
rprintf(FINFO, "[%s] popping mergelist #%d%s\n", |
rprintf(FINFO, "[%s] popping mergelist #%d%s\n", |
who_am_i(), i, lp->debug_type); |
who_am_i(), i, lp->debug_type); |
} |
} |
|
|
clear_filter_list(lp); | pop_filter_list(lp); |
| if (i >= old_mergelist_cnt && lp->head) { |
if (i >= old_mergelist_cnt) { | /* This mergelist does not exist in the state to be restored, but it |
/* This mergelist does not exist in the state to be | * still has inherited rules. This can sometimes happen if a per-dir |
* restored. Free its parent_dirscan list to clean up | * merge file calls setup_merge_file() in push_local_filters() and that |
* any per-dir mergelists defined there so we don't | * leaves some inherited rules that aren't in the pushed list state. */ |
* crash trying to restore nonexistent state for them | |
* below. (Counterpart to setup_merge_file call in | |
* push_local_filters. Must be done here, not in | |
* free_filter, for LIFO order.) */ | |
if (DEBUG_GTE(FILTER, 2)) { |
if (DEBUG_GTE(FILTER, 2)) { |
rprintf(FINFO, "[%s] freeing parent_dirscan filters of mergelist #%d%s\n", |
rprintf(FINFO, "[%s] freeing parent_dirscan filters of mergelist #%d%s\n", |
who_am_i(), i, ex->u.mergelist->debug_type); |
who_am_i(), i, ex->u.mergelist->debug_type); |
} |
} |
free_filters(lp->parent_dirscan_head); | pop_filter_list(lp); |
lp->parent_dirscan_head = NULL; | |
} |
} |
} |
} |
|
|
/* If we cleaned things up properly, the only still-active mergelists | if (!pop) |
* should be those with a state to be restored. */ | return; /* No state to restore. */ |
assert(mergelist_cnt == old_mergelist_cnt); | |
|
|
if (!pop) { | for (i = 0; i < old_mergelist_cnt; i++) { |
/* No state to restore. */ | filter_rule *ex = mergelist_parents[i]; |
return; | if (!ex) |
| continue; |
| memcpy(ex->u.mergelist, &pop->mergelists[i], sizeof (filter_rule_list)); |
} |
} |
|
|
for (i = 0; i < mergelist_cnt; i++) { |
|
memcpy(mergelist_parents[i]->u.mergelist, &pop->mergelists[i], |
|
sizeof (filter_rule_list)); |
|
} |
|
|
|
free(pop); |
free(pop); |
} |
} |
|
|
Line 872 static filter_rule *parse_rule_tok(const char **rulest
|
Line 870 static filter_rule *parse_rule_tok(const char **rulest
|
switch (ch) { |
switch (ch) { |
case ':': |
case ':': |
rule->rflags |= FILTRULE_PERDIR_MERGE |
rule->rflags |= FILTRULE_PERDIR_MERGE |
| FILTRULE_FINISH_SETUP; | | FILTRULE_FINISH_SETUP; |
/* FALL THROUGH */ |
/* FALL THROUGH */ |
case '.': |
case '.': |
rule->rflags |= FILTRULE_MERGE_FILE; |
rule->rflags |= FILTRULE_MERGE_FILE; |
Line 1093 void parse_filter_str(filter_rule_list *listp, const c
|
Line 1091 void parse_filter_str(filter_rule_list *listp, const c
|
"[%s] clearing filter list%s\n", |
"[%s] clearing filter list%s\n", |
who_am_i(), listp->debug_type); |
who_am_i(), listp->debug_type); |
} |
} |
clear_filter_list(listp); | pop_filter_list(listp); |
| listp->head = NULL; |
goto free_continue; |
goto free_continue; |
} |
} |
|
|