xref: /aosp_15_r20/external/erofs-utils/lib/exclude.c (revision 33b1fccf6a0fada2c2875d400ed01119b7676ee5)
1*33b1fccfSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
2*33b1fccfSAndroid Build Coastguard Worker /*
3*33b1fccfSAndroid Build Coastguard Worker  * Created by Li Guifu <[email protected]>
4*33b1fccfSAndroid Build Coastguard Worker  */
5*33b1fccfSAndroid Build Coastguard Worker #include <string.h>
6*33b1fccfSAndroid Build Coastguard Worker #include <stdlib.h>
7*33b1fccfSAndroid Build Coastguard Worker #include "erofs/err.h"
8*33b1fccfSAndroid Build Coastguard Worker #include "erofs/list.h"
9*33b1fccfSAndroid Build Coastguard Worker #include "erofs/print.h"
10*33b1fccfSAndroid Build Coastguard Worker #include "erofs/exclude.h"
11*33b1fccfSAndroid Build Coastguard Worker 
12*33b1fccfSAndroid Build Coastguard Worker #define EXCLUDE_RULE_EXACT_SIZE	offsetof(struct erofs_exclude_rule, reg)
13*33b1fccfSAndroid Build Coastguard Worker #define EXCLUDE_RULE_REGEX_SIZE	sizeof(struct erofs_exclude_rule)
14*33b1fccfSAndroid Build Coastguard Worker 
15*33b1fccfSAndroid Build Coastguard Worker static LIST_HEAD(exclude_head);
16*33b1fccfSAndroid Build Coastguard Worker static LIST_HEAD(regex_exclude_head);
17*33b1fccfSAndroid Build Coastguard Worker 
dump_regerror(int errcode,const char * s,const regex_t * preg)18*33b1fccfSAndroid Build Coastguard Worker static void dump_regerror(int errcode, const char *s, const regex_t *preg)
19*33b1fccfSAndroid Build Coastguard Worker {
20*33b1fccfSAndroid Build Coastguard Worker 	char str[512];
21*33b1fccfSAndroid Build Coastguard Worker 
22*33b1fccfSAndroid Build Coastguard Worker 	regerror(errcode, preg, str, sizeof(str));
23*33b1fccfSAndroid Build Coastguard Worker 	erofs_err("invalid regex %s (%s)\n", s, str);
24*33b1fccfSAndroid Build Coastguard Worker }
25*33b1fccfSAndroid Build Coastguard Worker 
erofs_insert_exclude(const char * s,bool is_regex)26*33b1fccfSAndroid Build Coastguard Worker static struct erofs_exclude_rule *erofs_insert_exclude(const char *s,
27*33b1fccfSAndroid Build Coastguard Worker 						       bool is_regex)
28*33b1fccfSAndroid Build Coastguard Worker {
29*33b1fccfSAndroid Build Coastguard Worker 	struct erofs_exclude_rule *r;
30*33b1fccfSAndroid Build Coastguard Worker 	int ret;
31*33b1fccfSAndroid Build Coastguard Worker 	struct list_head *h;
32*33b1fccfSAndroid Build Coastguard Worker 
33*33b1fccfSAndroid Build Coastguard Worker 	r = malloc(is_regex ? EXCLUDE_RULE_REGEX_SIZE :
34*33b1fccfSAndroid Build Coastguard Worker 			      EXCLUDE_RULE_EXACT_SIZE);
35*33b1fccfSAndroid Build Coastguard Worker 	if (!r)
36*33b1fccfSAndroid Build Coastguard Worker 		return ERR_PTR(-ENOMEM);
37*33b1fccfSAndroid Build Coastguard Worker 
38*33b1fccfSAndroid Build Coastguard Worker 	r->pattern = strdup(s);
39*33b1fccfSAndroid Build Coastguard Worker 	if (!r->pattern) {
40*33b1fccfSAndroid Build Coastguard Worker 		ret = -ENOMEM;
41*33b1fccfSAndroid Build Coastguard Worker 		goto err_rule;
42*33b1fccfSAndroid Build Coastguard Worker 	}
43*33b1fccfSAndroid Build Coastguard Worker 
44*33b1fccfSAndroid Build Coastguard Worker 	if (is_regex) {
45*33b1fccfSAndroid Build Coastguard Worker 		ret = regcomp(&r->reg, s, REG_EXTENDED|REG_NOSUB);
46*33b1fccfSAndroid Build Coastguard Worker 		if (ret) {
47*33b1fccfSAndroid Build Coastguard Worker 			dump_regerror(ret, s, &r->reg);
48*33b1fccfSAndroid Build Coastguard Worker 			goto err_rule;
49*33b1fccfSAndroid Build Coastguard Worker 		}
50*33b1fccfSAndroid Build Coastguard Worker 		h = &regex_exclude_head;
51*33b1fccfSAndroid Build Coastguard Worker 	} else {
52*33b1fccfSAndroid Build Coastguard Worker 		h = &exclude_head;
53*33b1fccfSAndroid Build Coastguard Worker 	}
54*33b1fccfSAndroid Build Coastguard Worker 
55*33b1fccfSAndroid Build Coastguard Worker 	list_add_tail(&r->list, h);
56*33b1fccfSAndroid Build Coastguard Worker 	erofs_info("insert exclude %s: %s\n",
57*33b1fccfSAndroid Build Coastguard Worker 		   is_regex ? "regex" : "path", s);
58*33b1fccfSAndroid Build Coastguard Worker 	return r;
59*33b1fccfSAndroid Build Coastguard Worker 
60*33b1fccfSAndroid Build Coastguard Worker err_rule:
61*33b1fccfSAndroid Build Coastguard Worker 	if (r->pattern)
62*33b1fccfSAndroid Build Coastguard Worker 		free(r->pattern);
63*33b1fccfSAndroid Build Coastguard Worker 	free(r);
64*33b1fccfSAndroid Build Coastguard Worker 	return ERR_PTR(ret);
65*33b1fccfSAndroid Build Coastguard Worker }
66*33b1fccfSAndroid Build Coastguard Worker 
erofs_cleanup_exclude_rules(void)67*33b1fccfSAndroid Build Coastguard Worker void erofs_cleanup_exclude_rules(void)
68*33b1fccfSAndroid Build Coastguard Worker {
69*33b1fccfSAndroid Build Coastguard Worker 	struct erofs_exclude_rule *r, *n;
70*33b1fccfSAndroid Build Coastguard Worker 	struct list_head *h;
71*33b1fccfSAndroid Build Coastguard Worker 
72*33b1fccfSAndroid Build Coastguard Worker 	h = &exclude_head;
73*33b1fccfSAndroid Build Coastguard Worker 	list_for_each_entry_safe(r, n, h, list) {
74*33b1fccfSAndroid Build Coastguard Worker 		list_del(&r->list);
75*33b1fccfSAndroid Build Coastguard Worker 		free(r->pattern);
76*33b1fccfSAndroid Build Coastguard Worker 		free(r);
77*33b1fccfSAndroid Build Coastguard Worker 	}
78*33b1fccfSAndroid Build Coastguard Worker 
79*33b1fccfSAndroid Build Coastguard Worker 	h = &regex_exclude_head;
80*33b1fccfSAndroid Build Coastguard Worker 	list_for_each_entry_safe(r, n, h, list) {
81*33b1fccfSAndroid Build Coastguard Worker 		list_del(&r->list);
82*33b1fccfSAndroid Build Coastguard Worker 		free(r->pattern);
83*33b1fccfSAndroid Build Coastguard Worker 		regfree(&r->reg);
84*33b1fccfSAndroid Build Coastguard Worker 		free(r);
85*33b1fccfSAndroid Build Coastguard Worker 	}
86*33b1fccfSAndroid Build Coastguard Worker }
87*33b1fccfSAndroid Build Coastguard Worker 
erofs_parse_exclude_path(const char * args,bool is_regex)88*33b1fccfSAndroid Build Coastguard Worker int erofs_parse_exclude_path(const char *args, bool is_regex)
89*33b1fccfSAndroid Build Coastguard Worker {
90*33b1fccfSAndroid Build Coastguard Worker 	struct erofs_exclude_rule *r = erofs_insert_exclude(args, is_regex);
91*33b1fccfSAndroid Build Coastguard Worker 
92*33b1fccfSAndroid Build Coastguard Worker 	if (IS_ERR(r)) {
93*33b1fccfSAndroid Build Coastguard Worker 		erofs_cleanup_exclude_rules();
94*33b1fccfSAndroid Build Coastguard Worker 		return PTR_ERR(r);
95*33b1fccfSAndroid Build Coastguard Worker 	}
96*33b1fccfSAndroid Build Coastguard Worker 	return 0;
97*33b1fccfSAndroid Build Coastguard Worker }
98*33b1fccfSAndroid Build Coastguard Worker 
erofs_is_exclude_path(const char * dir,const char * name)99*33b1fccfSAndroid Build Coastguard Worker struct erofs_exclude_rule *erofs_is_exclude_path(const char *dir,
100*33b1fccfSAndroid Build Coastguard Worker 						 const char *name)
101*33b1fccfSAndroid Build Coastguard Worker {
102*33b1fccfSAndroid Build Coastguard Worker 	char buf[PATH_MAX];
103*33b1fccfSAndroid Build Coastguard Worker 	const char *s;
104*33b1fccfSAndroid Build Coastguard Worker 	struct erofs_exclude_rule *r;
105*33b1fccfSAndroid Build Coastguard Worker 
106*33b1fccfSAndroid Build Coastguard Worker 	if (!dir) {
107*33b1fccfSAndroid Build Coastguard Worker 		/* no prefix */
108*33b1fccfSAndroid Build Coastguard Worker 		s = name;
109*33b1fccfSAndroid Build Coastguard Worker 	} else {
110*33b1fccfSAndroid Build Coastguard Worker 		sprintf(buf, "%s/%s", dir, name);
111*33b1fccfSAndroid Build Coastguard Worker 		s = buf;
112*33b1fccfSAndroid Build Coastguard Worker 	}
113*33b1fccfSAndroid Build Coastguard Worker 
114*33b1fccfSAndroid Build Coastguard Worker 	s = erofs_fspath(s);
115*33b1fccfSAndroid Build Coastguard Worker 	list_for_each_entry(r, &exclude_head, list) {
116*33b1fccfSAndroid Build Coastguard Worker 		if (!strcmp(r->pattern, s))
117*33b1fccfSAndroid Build Coastguard Worker 			return r;
118*33b1fccfSAndroid Build Coastguard Worker 	}
119*33b1fccfSAndroid Build Coastguard Worker 
120*33b1fccfSAndroid Build Coastguard Worker 	list_for_each_entry(r, &regex_exclude_head, list) {
121*33b1fccfSAndroid Build Coastguard Worker 		int ret = regexec(&r->reg, s, (size_t)0, NULL, 0);
122*33b1fccfSAndroid Build Coastguard Worker 
123*33b1fccfSAndroid Build Coastguard Worker 		if (!ret)
124*33b1fccfSAndroid Build Coastguard Worker 			return r;
125*33b1fccfSAndroid Build Coastguard Worker 		if (ret != REG_NOMATCH)
126*33b1fccfSAndroid Build Coastguard Worker 			dump_regerror(ret, s, &r->reg);
127*33b1fccfSAndroid Build Coastguard Worker 	}
128*33b1fccfSAndroid Build Coastguard Worker 	return NULL;
129*33b1fccfSAndroid Build Coastguard Worker }
130