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