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