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 = ®ex_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 = ®ex_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, ®ex_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