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