xref: /plan9/sys/src/cmd/exportfs/pattern.c (revision a960ed1cec55a25d7c4ccbf9707a04427b3c30d1)
1*a960ed1cSDavid du Colombier #include <u.h>
2*a960ed1cSDavid du Colombier #include <libc.h>
3*a960ed1cSDavid du Colombier #include <fcall.h>
4*a960ed1cSDavid du Colombier #include <bio.h>
5*a960ed1cSDavid du Colombier #include <regexp.h>
6*a960ed1cSDavid du Colombier #define Extern
7*a960ed1cSDavid du Colombier #include "exportfs.h"
8*a960ed1cSDavid du Colombier 
9*a960ed1cSDavid du Colombier Reprog	**exclude, **include;
10*a960ed1cSDavid du Colombier char	*patternfile;
11*a960ed1cSDavid du Colombier 
12*a960ed1cSDavid du Colombier void
exclusions(void)13*a960ed1cSDavid du Colombier exclusions(void)
14*a960ed1cSDavid du Colombier {
15*a960ed1cSDavid du Colombier 	Biobuf *f;
16*a960ed1cSDavid du Colombier 	int ni, nmaxi, ne, nmaxe;
17*a960ed1cSDavid du Colombier 	char *line;
18*a960ed1cSDavid du Colombier 
19*a960ed1cSDavid du Colombier 	if(patternfile == nil)
20*a960ed1cSDavid du Colombier 		return;
21*a960ed1cSDavid du Colombier 
22*a960ed1cSDavid du Colombier 	f = Bopen(patternfile, OREAD);
23*a960ed1cSDavid du Colombier 	if(f == nil)
24*a960ed1cSDavid du Colombier 		fatal("cannot open patternfile");
25*a960ed1cSDavid du Colombier 	ni = 0;
26*a960ed1cSDavid du Colombier 	nmaxi = 100;
27*a960ed1cSDavid du Colombier 	include = malloc(nmaxi*sizeof(*include));
28*a960ed1cSDavid du Colombier 	if(include == nil)
29*a960ed1cSDavid du Colombier 		fatal("out of memory");
30*a960ed1cSDavid du Colombier 	include[0] = nil;
31*a960ed1cSDavid du Colombier 	ne = 0;
32*a960ed1cSDavid du Colombier 	nmaxe = 100;
33*a960ed1cSDavid du Colombier 	exclude = malloc(nmaxe*sizeof(*exclude));
34*a960ed1cSDavid du Colombier 	if(exclude == nil)
35*a960ed1cSDavid du Colombier 		fatal("out of memory");
36*a960ed1cSDavid du Colombier 	exclude[0] = nil;
37*a960ed1cSDavid du Colombier 	while(line = Brdline(f, '\n')){
38*a960ed1cSDavid du Colombier 		line[Blinelen(f) - 1] = 0;
39*a960ed1cSDavid du Colombier 		if(strlen(line) < 2 || line[1] != ' ')
40*a960ed1cSDavid du Colombier 			continue;
41*a960ed1cSDavid du Colombier 		switch(line[0]){
42*a960ed1cSDavid du Colombier 		case '+':
43*a960ed1cSDavid du Colombier 			if(ni+1 >= nmaxi){
44*a960ed1cSDavid du Colombier 				nmaxi = 2*nmaxi;
45*a960ed1cSDavid du Colombier 				include = realloc(include, nmaxi*sizeof(*include));
46*a960ed1cSDavid du Colombier 				if(include == nil)
47*a960ed1cSDavid du Colombier 					fatal("out of memory");
48*a960ed1cSDavid du Colombier 			}
49*a960ed1cSDavid du Colombier 			DEBUG(DFD, "\tinclude %s\n", line+2);
50*a960ed1cSDavid du Colombier 			include[ni] = regcomp(line+2);
51*a960ed1cSDavid du Colombier 			include[++ni] = nil;
52*a960ed1cSDavid du Colombier 			break;
53*a960ed1cSDavid du Colombier 		case '-':
54*a960ed1cSDavid du Colombier 			if(ne+1 >= nmaxe){
55*a960ed1cSDavid du Colombier 				nmaxe = 2*nmaxe;
56*a960ed1cSDavid du Colombier 				exclude = realloc(exclude, nmaxe*sizeof(*exclude));
57*a960ed1cSDavid du Colombier 				if(exclude == nil)
58*a960ed1cSDavid du Colombier 					fatal("out of memory");
59*a960ed1cSDavid du Colombier 			}
60*a960ed1cSDavid du Colombier 			DEBUG(DFD, "\texclude %s\n", line+2);
61*a960ed1cSDavid du Colombier 			exclude[ne] = regcomp(line+2);
62*a960ed1cSDavid du Colombier 			exclude[++ne] = nil;
63*a960ed1cSDavid du Colombier 			break;
64*a960ed1cSDavid du Colombier 		default:
65*a960ed1cSDavid du Colombier 			DEBUG(DFD, "ignoring pattern %s\n", line);
66*a960ed1cSDavid du Colombier 			break;
67*a960ed1cSDavid du Colombier 		}
68*a960ed1cSDavid du Colombier 	}
69*a960ed1cSDavid du Colombier 	Bterm(f);
70*a960ed1cSDavid du Colombier }
71*a960ed1cSDavid du Colombier 
72*a960ed1cSDavid du Colombier int
excludefile(char * path)73*a960ed1cSDavid du Colombier excludefile(char *path)
74*a960ed1cSDavid du Colombier {
75*a960ed1cSDavid du Colombier 	Reprog **re;
76*a960ed1cSDavid du Colombier 	char *p;
77*a960ed1cSDavid du Colombier 
78*a960ed1cSDavid du Colombier 	if(*(path+1) == 0)
79*a960ed1cSDavid du Colombier 		p = "/";
80*a960ed1cSDavid du Colombier 	else
81*a960ed1cSDavid du Colombier 		p = path+1;
82*a960ed1cSDavid du Colombier 
83*a960ed1cSDavid du Colombier 	DEBUG(DFD, "checking %s\n", path);
84*a960ed1cSDavid du Colombier 	for(re = include; *re != nil; re++){
85*a960ed1cSDavid du Colombier 		if(regexec(*re, p, nil, 0) != 1){
86*a960ed1cSDavid du Colombier 			DEBUG(DFD, "excluded+ %s\n", path);
87*a960ed1cSDavid du Colombier 			return -1;
88*a960ed1cSDavid du Colombier 		}
89*a960ed1cSDavid du Colombier 	}
90*a960ed1cSDavid du Colombier 	for(re = exclude; *re != nil; re++){
91*a960ed1cSDavid du Colombier 		if(regexec(*re, p, nil, 0) == 1){
92*a960ed1cSDavid du Colombier 			DEBUG(DFD, "excluded- %s\n", path);
93*a960ed1cSDavid du Colombier 			return -1;
94*a960ed1cSDavid du Colombier 		}
95*a960ed1cSDavid du Colombier 	}
96*a960ed1cSDavid du Colombier 	return 0;
97*a960ed1cSDavid du Colombier }
98*a960ed1cSDavid du Colombier 
99*a960ed1cSDavid du Colombier int
preaddir(Fid * f,uchar * data,int n,vlong offset)100*a960ed1cSDavid du Colombier preaddir(Fid *f, uchar *data, int n, vlong offset)
101*a960ed1cSDavid du Colombier {
102*a960ed1cSDavid du Colombier 	int r = 0, m;
103*a960ed1cSDavid du Colombier 	Dir *d;
104*a960ed1cSDavid du Colombier 
105*a960ed1cSDavid du Colombier 	DEBUG(DFD, "\tpreaddir n=%d wo=%lld fo=%lld\n", n, offset, f->offset);
106*a960ed1cSDavid du Colombier 	if(offset == 0 && f->offset != 0){
107*a960ed1cSDavid du Colombier 		if(seek(f->fid, 0, 0) != 0)
108*a960ed1cSDavid du Colombier 			return -1;
109*a960ed1cSDavid du Colombier 		f->offset = f->cdir = f->ndir = 0;
110*a960ed1cSDavid du Colombier 		free(f->dir);
111*a960ed1cSDavid du Colombier 		f->dir = nil;
112*a960ed1cSDavid du Colombier 	}else if(offset != f->offset){
113*a960ed1cSDavid du Colombier 		werrstr("can't seek dir %lld to %lld", f->offset, offset);
114*a960ed1cSDavid du Colombier 		return -1;
115*a960ed1cSDavid du Colombier 	}
116*a960ed1cSDavid du Colombier 
117*a960ed1cSDavid du Colombier 	while(n > 0){
118*a960ed1cSDavid du Colombier 		if(f->dir == nil){
119*a960ed1cSDavid du Colombier 			f->ndir = dirread(f->fid, &f->dir);
120*a960ed1cSDavid du Colombier 			if(f->ndir < 0)
121*a960ed1cSDavid du Colombier 				return f->ndir;
122*a960ed1cSDavid du Colombier 			if(f->ndir == 0)
123*a960ed1cSDavid du Colombier 				return r;
124*a960ed1cSDavid du Colombier 		}
125*a960ed1cSDavid du Colombier 		d = &f->dir[f->cdir++];
126*a960ed1cSDavid du Colombier 		if(exclude){
127*a960ed1cSDavid du Colombier 			char *p = makepath(f->f, d->name);
128*a960ed1cSDavid du Colombier 			if(excludefile(p)){
129*a960ed1cSDavid du Colombier 				free(p);
130*a960ed1cSDavid du Colombier 				goto skipentry;
131*a960ed1cSDavid du Colombier 			}
132*a960ed1cSDavid du Colombier 			free(p);
133*a960ed1cSDavid du Colombier 		}
134*a960ed1cSDavid du Colombier 		m = convD2M(d, data, n);
135*a960ed1cSDavid du Colombier 		DEBUG(DFD, "\t\tconvD2M %d\n", m);
136*a960ed1cSDavid du Colombier 		if(m <= BIT16SZ){
137*a960ed1cSDavid du Colombier 			DEBUG(DFD, "\t\t\tneeded %d\n", GBIT16(data));
138*a960ed1cSDavid du Colombier 			/* not enough room for full entry; leave for next time */
139*a960ed1cSDavid du Colombier 			f->cdir--;
140*a960ed1cSDavid du Colombier 			return r;
141*a960ed1cSDavid du Colombier 		}else{
142*a960ed1cSDavid du Colombier 			data += m;
143*a960ed1cSDavid du Colombier 			n -= m;
144*a960ed1cSDavid du Colombier 			r += m;
145*a960ed1cSDavid du Colombier 			f->offset += m;
146*a960ed1cSDavid du Colombier 		}
147*a960ed1cSDavid du Colombier skipentry:	if(f->cdir >= f->ndir){
148*a960ed1cSDavid du Colombier 			f->cdir = f->ndir = 0;
149*a960ed1cSDavid du Colombier 			free(f->dir);
150*a960ed1cSDavid du Colombier 			f->dir = nil;
151*a960ed1cSDavid du Colombier 		}
152*a960ed1cSDavid du Colombier 	}
153*a960ed1cSDavid du Colombier 	return r;
154*a960ed1cSDavid du Colombier }
155