⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exclude.c

📁 Rsync 3.0.5 source code
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Each time rsync changes to a new directory it call this function to * handle all the per-dir merge-files.  The "dir" value is the current path * relative to curr_dir (which might not be null-terminated).  We copy it * into dirbuf so that we can easily append a file name on the end. */void *push_local_filters(const char *dir, unsigned int dirlen){	struct filter_list_struct *ap, *push;	int i;	set_filter_dir(dir, dirlen);	if (!mergelist_cnt)		return NULL;	push = new_array(struct filter_list_struct, mergelist_cnt);	if (!push)		out_of_memory("push_local_filters");	for (i = 0, ap = push; i < mergelist_cnt; i++) {		memcpy(ap++, mergelist_parents[i]->u.mergelist,		       sizeof (struct filter_list_struct));	}	/* Note: parse_filter_file() might increase mergelist_cnt, so keep	 * this loop separate from the above loop. */	for (i = 0; i < mergelist_cnt; i++) {		struct filter_struct *ex = mergelist_parents[i];		struct filter_list_struct *lp = ex->u.mergelist;		if (verbose > 2) {			rprintf(FINFO, "[%s] pushing filter list%s\n",				who_am_i(), lp->debug_type);		}		lp->tail = NULL; /* Switch any local rules to inherited. */		if (ex->match_flags & MATCHFLG_NO_INHERIT)			lp->head = NULL;		if (ex->match_flags & MATCHFLG_FINISH_SETUP) {			ex->match_flags &= ~MATCHFLG_FINISH_SETUP;			if (setup_merge_file(ex, lp))				set_filter_dir(dir, dirlen);		}		if (strlcpy(dirbuf + dirbuf_len, ex->pattern,		    MAXPATHLEN - dirbuf_len) < MAXPATHLEN - dirbuf_len) {			parse_filter_file(lp, dirbuf, ex->match_flags,					  XFLG_ANCHORED2ABS);		} else {			io_error |= IOERR_GENERAL;			rprintf(FERROR,			    "cannot add local filter rules in long-named directory: %s\n",			    full_fname(dirbuf));		}		dirbuf[dirbuf_len] = '\0';	}	return (void*)push;}void pop_local_filters(void *mem){	struct filter_list_struct *ap, *pop = (struct filter_list_struct*)mem;	int i;	for (i = mergelist_cnt; i-- > 0; ) {		struct filter_struct *ex = mergelist_parents[i];		struct filter_list_struct *lp = ex->u.mergelist;		if (verbose > 2) {			rprintf(FINFO, "[%s] popping filter list%s\n",				who_am_i(), lp->debug_type);		}		clear_filter_list(lp);	}	if (!pop)		return;	for (i = 0, ap = pop; i < mergelist_cnt; i++) {		memcpy(mergelist_parents[i]->u.mergelist, ap++,		       sizeof (struct filter_list_struct));	}	free(pop);}void change_local_filter_dir(const char *dname, int dlen, int dir_depth){	static int cur_depth = -1;	static void *filt_array[MAXPATHLEN/2+1];	if (!dname) {		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);	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(const 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 */	const char *name = fname + (*fname == '/');	if (!*name)		return 0;	if (!ex->u.slash_cnt && !(ex->match_flags & MATCHFLG_WILD2)) {		/* If the pattern does not have any slashes AND it does		 * not have a "**" (which could match a slash), then we		 * just match the name portion of the path. */		if ((p = strrchr(name,'/')) != NULL)			name = p+1;	} 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 && *fname != '/') {		/* Allow "**"+"/" to match at the start of the string. */		strings[str_cnt++] = "/";	}	strings[str_cnt++] = name;	if (name_is_dir) {		/* Allow a trailing "/"+"***" to match the directory. */		if (ex->match_flags & MATCHFLG_WILD3_SUFFIX)			strings[str_cnt++] = "/";	} else if (ex->match_flags & MATCHFLG_DIRECTORY)		return !ret_match;	strings[str_cnt] = NULL;	if (*pattern == '/') {		anchored_match = 1;		pattern++;	}	if (!anchored_match && ex->u.slash_cnt	    && !(ex->match_flags & MATCHFLG_WILD2)) {		/* A non-anchored match with an infix slash and no "**"		 * needs to match the last slash_cnt+1 name elements. */		slash_handling = ex->u.slash_cnt + 1;	} else if (!anchored_match && !(ex->match_flags & MATCHFLG_WILD2_PREFIX)				   && ex->match_flags & MATCHFLG_WILD2) {		/* A non-anchored match with an infix or trailing "**" (but not		 * a prefixed "**") needs to try matching after every slash. */		slash_handling = -1;	} else {		/* The pattern matches only at the start of the path or name. */		slash_handling = 0;	}	if (ex->match_flags & MATCHFLG_WILD) {		if (wildmatch_array(pattern, strings, slash_handling))			return ret_match;	} else if (str_cnt > 1) {		if (litmatch_array(pattern, strings, slash_handling))			return ret_match;	} else if (anchored_match) {		if (strcmp(name, pattern) == 0)			return ret_match;	} else {		int l1 = strlen(name);		int l2 = strlen(pattern);		if (l2 <= l1 &&		    strcmp(name+(l1-l2),pattern) == 0 &&		    (l1==l2 || name[l1-(l2+1)] == '/')) {			return ret_match;		}	}	return !ret_match;}static void report_filter_result(enum logcode code, char const *name,                                 struct filter_struct const *ent,                                 int name_is_dir, const char *type){	/* If a trailing slash is present to match only directories,	 * then it is stripped out by add_rule().  So as a special	 * case we add it back in here. */	if (verbose >= 2) {		static char *actions[2][2]		    = { {"show", "hid"}, {"risk", "protect"} };		const char *w = who_am_i();		rprintf(code, "[%s] %sing %s %s because of pattern %s%s%s\n",		    w, actions[*w!='s'][!(ent->match_flags&MATCHFLG_INCLUDE)],		    name_is_dir ? "directory" : "file", name, ent->pattern,		    ent->match_flags & MATCHFLG_DIRECTORY ? "/" : "", type);	}}/* * Return -1 if file "name" is defined to be excluded by the specified * exclude list, 1 if it is included, and 0 if it was not matched. */int check_filter(struct filter_list_struct *listp, enum logcode code,		 const char *name, int name_is_dir){	struct filter_struct *ent;	for (ent = listp->head; ent; ent = ent->next) {		if (ignore_perishable && ent->match_flags & MATCHFLG_PERISHABLE)			continue;		if (ent->match_flags & MATCHFLG_PERDIR_MERGE) {			int rc = check_filter(ent->u.mergelist, code, name,					      name_is_dir);			if (rc)				return rc;			continue;		}		if (ent->match_flags & MATCHFLG_CVS_IGNORE) {			int rc = check_filter(&cvs_filter_list, code, name,					      name_is_dir);			if (rc)				return rc;			continue;		}		if (rule_matches(name, ent, name_is_dir)) {			report_filter_result(code, name, ent, name_is_dir,					     listp->debug_type);			return ent->match_flags & MATCHFLG_INCLUDE ? 1 : -1;		}	}	return 0;}#define RULE_STRCMP(s,r) rule_strcmp((s), (r), sizeof (r) - 1)static const uchar *rule_strcmp(const uchar *str, const char *rule, int rule_len){	if (strncmp((char*)str, rule, rule_len) != 0)		return NULL;	if (isspace(str[rule_len]) || str[rule_len] == '_' || !str[rule_len])		return str + rule_len - 1;	if (str[rule_len] == ',')		return str + rule_len;	return NULL;}/* Get the next include/exclude arg from the string.  The token will not * be '\0' terminated, so use the returned length to limit the string. * Also, be sure to add this length to the returned pointer before passing * it back to ask for the next token.  This routine parses the "!" (list- * clearing) token and (depending on the mflags) the various prefixes. * The *mflags_ptr value will be set on exit to the new MATCHFLG_* bits * for the current token. */static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags,				  unsigned int *len_ptr, uint32 *mflags_ptr){	const uchar *s = (const uchar *)p;	uint32 new_mflags;	unsigned int len;	if (mflags & MATCHFLG_WORD_SPLIT) {		/* Skip over any initial whitespace. */		while (isspace(*s))			s++;		/* Update to point to real start of rule. */		p = (const char *)s;	}	if (!*s)		return NULL;	new_mflags = mflags & MATCHFLGS_FROM_CONTAINER;	/* Figure out what kind of a filter rule "s" is pointing at.  Note	 * that if MATCHFLG_NO_PREFIXES is set, the rule is either an include	 * or an exclude based on the inheritance of the MATCHFLG_INCLUDE	 * flag (above).  XFLG_OLD_PREFIXES indicates a compatibility mode	 * for old include/exclude patterns where just "+ " and "- " are	 * allowed as optional prefixes.  */	if (mflags & MATCHFLG_NO_PREFIXES) {		if (*s == '!' && mflags & MATCHFLG_CVS_IGNORE)			new_mflags |= MATCHFLG_CLEAR_LIST; /* Tentative! */	} else if (xflags & XFLG_OLD_PREFIXES) {		if (*s == '-' && s[1] == ' ') {			new_mflags &= ~MATCHFLG_INCLUDE;			s += 2;		} else if (*s == '+' && s[1] == ' ') {			new_mflags |= MATCHFLG_INCLUDE;			s += 2;		} else if (*s == '!')			new_mflags |= MATCHFLG_CLEAR_LIST; /* Tentative! */	} else {		char ch = 0, *mods = "";		switch (*s) {		case 'c':			if ((s = RULE_STRCMP(s, "clear")) != NULL)				ch = '!';			break;		case 'd':			if ((s = RULE_STRCMP(s, "dir-merge")) != NULL)				ch = ':';			break;		case 'e':			if ((s = RULE_STRCMP(s, "exclude")) != NULL)				ch = '-';			break;		case 'h':			if ((s = RULE_STRCMP(s, "hide")) != NULL)				ch = 'H';			break;		case 'i':			if ((s = RULE_STRCMP(s, "include")) != NULL)				ch = '+';			break;		case 'm':			if ((s = RULE_STRCMP(s, "merge")) != NULL)				ch = '.';			break;		case 'p':			if ((s = RULE_STRCMP(s, "protect")) != NULL)				ch = 'P';			break;		case 'r':			if ((s = RULE_STRCMP(s, "risk")) != NULL)				ch = 'R';			break;		case 's':			if ((s = RULE_STRCMP(s, "show")) != NULL)				ch = 'S';			break;		default:			ch = *s;			if (s[1] == ',')				s++;			break;		}		switch (ch) {		case ':':			new_mflags |= MATCHFLG_PERDIR_MERGE				    | MATCHFLG_FINISH_SETUP;			/* FALL THROUGH */		case '.':			new_mflags |= MATCHFLG_MERGE_FILE;			mods = MODIFIERS_INCL_EXCL MODIFIERS_MERGE_FILE;			break;		case '+':			new_mflags |= MATCHFLG_INCLUDE;			/* FALL THROUGH */		case '-':			mods = MODIFIERS_INCL_EXCL;			break;		case 'S':			new_mflags |= MATCHFLG_INCLUDE;			/* FALL THROUGH */		case 'H':			new_mflags |= MATCHFLG_SENDER_SIDE;			mods = MODIFIERS_HIDE_PROTECT;			break;		case 'R':			new_mflags |= MATCHFLG_INCLUDE;			/* FALL THROUGH */		case 'P':			new_mflags |= MATCHFLG_RECEIVER_SIDE;			mods = MODIFIERS_HIDE_PROTECT;			break;		case '!':			new_mflags |= MATCHFLG_CLEAR_LIST;			mods = NULL;			break;		default:			rprintf(FERROR, "Unknown filter rule: `%s'\n", p);			exit_cleanup(RERR_SYNTAX);		}		while (mods && *++s && *s != ' ' && *s != '_') {			if (strchr(mods, *s) == NULL) {				if (mflags & MATCHFLG_WORD_SPLIT && isspace(*s)) {					s--;					break;				}			    invalid:				rprintf(FERROR,					"invalid modifier sequence at '%c' in filter rule: %s\n",					*s, p);				exit_cleanup(RERR_SYNTAX);			}			switch (*s) {			case '-':				if (new_mflags & MATCHFLG_NO_PREFIXES)				    goto invalid;				new_mflags |= MATCHFLG_NO_PREFIXES;				break;			case '+':				if (new_mflags & MATCHFLG_NO_PREFIXES)				    goto invalid;				new_mflags |= MATCHFLG_NO_PREFIXES					    | MATCHFLG_INCLUDE;				break;			case '/':				new_mflags |= MATCHFLG_ABS_PATH;				break;			case '!':				new_mflags |= MATCHFLG_NEGATE;				break;			case 'C':				if (new_mflags & MATCHFLG_NO_PREFIXES)				    goto invalid;				new_mflags |= MATCHFLG_NO_PREFIXES					    | MATCHFLG_WORD_SPLIT					    | MATCHFLG_NO_INHERIT					    | MATCHFLG_CVS_IGNORE;				break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -