|
@@ -0,0 +1,154 @@
|
|
|
+#include <u.h>
|
|
|
+#include <libc.h>
|
|
|
+#include <fcall.h>
|
|
|
+#include <bio.h>
|
|
|
+#include <regexp.h>
|
|
|
+#define Extern
|
|
|
+#include "exportfs.h"
|
|
|
+
|
|
|
+Reprog **exclude, **include;
|
|
|
+char *patternfile;
|
|
|
+
|
|
|
+void
|
|
|
+exclusions(void)
|
|
|
+{
|
|
|
+ Biobuf *f;
|
|
|
+ int ni, nmaxi, ne, nmaxe;
|
|
|
+ char *line;
|
|
|
+
|
|
|
+ if(patternfile == nil)
|
|
|
+ return;
|
|
|
+
|
|
|
+ f = Bopen(patternfile, OREAD);
|
|
|
+ if(f == nil)
|
|
|
+ fatal("cannot open patternfile");
|
|
|
+ ni = 0;
|
|
|
+ nmaxi = 100;
|
|
|
+ include = malloc(nmaxi*sizeof(*include));
|
|
|
+ if(include == nil)
|
|
|
+ fatal("out of memory");
|
|
|
+ include[0] = nil;
|
|
|
+ ne = 0;
|
|
|
+ nmaxe = 100;
|
|
|
+ exclude = malloc(nmaxe*sizeof(*exclude));
|
|
|
+ if(exclude == nil)
|
|
|
+ fatal("out of memory");
|
|
|
+ exclude[0] = nil;
|
|
|
+ while(line = Brdline(f, '\n')){
|
|
|
+ line[Blinelen(f) - 1] = 0;
|
|
|
+ if(strlen(line) < 2 || line[1] != ' ')
|
|
|
+ continue;
|
|
|
+ switch(line[0]){
|
|
|
+ case '+':
|
|
|
+ if(ni+1 >= nmaxi){
|
|
|
+ nmaxi = 2*nmaxi;
|
|
|
+ include = realloc(include, nmaxi*sizeof(*include));
|
|
|
+ if(include == nil)
|
|
|
+ fatal("out of memory");
|
|
|
+ }
|
|
|
+ DEBUG(DFD, "\tinclude %s\n", line+2);
|
|
|
+ include[ni] = regcomp(line+2);
|
|
|
+ include[++ni] = nil;
|
|
|
+ break;
|
|
|
+ case '-':
|
|
|
+ if(ne+1 >= nmaxe){
|
|
|
+ nmaxe = 2*nmaxe;
|
|
|
+ exclude = realloc(exclude, nmaxe*sizeof(*exclude));
|
|
|
+ if(exclude == nil)
|
|
|
+ fatal("out of memory");
|
|
|
+ }
|
|
|
+ DEBUG(DFD, "\texclude %s\n", line+2);
|
|
|
+ exclude[ne] = regcomp(line+2);
|
|
|
+ exclude[++ne] = nil;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ DEBUG(DFD, "ignoring pattern %s\n", line);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Bterm(f);
|
|
|
+}
|
|
|
+
|
|
|
+int
|
|
|
+excludefile(char *path)
|
|
|
+{
|
|
|
+ Reprog **re;
|
|
|
+ char *p;
|
|
|
+
|
|
|
+ if(*(path+1) == 0)
|
|
|
+ p = "/";
|
|
|
+ else
|
|
|
+ p = path+1;
|
|
|
+
|
|
|
+ DEBUG(DFD, "checking %s\n", path);
|
|
|
+ for(re = include; *re != nil; re++){
|
|
|
+ if(regexec(*re, p, nil, 0) != 1){
|
|
|
+ DEBUG(DFD, "excluded+ %s\n", path);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for(re = exclude; *re != nil; re++){
|
|
|
+ if(regexec(*re, p, nil, 0) == 1){
|
|
|
+ DEBUG(DFD, "excluded- %s\n", path);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int
|
|
|
+preaddir(Fid *f, uchar *data, int n, vlong offset)
|
|
|
+{
|
|
|
+ int r = 0, m;
|
|
|
+ Dir *d;
|
|
|
+
|
|
|
+ DEBUG(DFD, "\tpreaddir n=%d wo=%lld fo=%lld\n", n, offset, f->offset);
|
|
|
+ if(offset == 0 && f->offset != 0){
|
|
|
+ if(seek(f->fid, 0, 0) != 0)
|
|
|
+ return -1;
|
|
|
+ f->offset = f->cdir = f->ndir = 0;
|
|
|
+ free(f->dir);
|
|
|
+ f->dir = nil;
|
|
|
+ }else if(offset != f->offset){
|
|
|
+ werrstr("can't seek dir %lld to %lld", f->offset, offset);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ while(n > 0){
|
|
|
+ if(f->dir == nil){
|
|
|
+ f->ndir = dirread(f->fid, &f->dir);
|
|
|
+ if(f->ndir < 0)
|
|
|
+ return f->ndir;
|
|
|
+ if(f->ndir == 0)
|
|
|
+ return r;
|
|
|
+ }
|
|
|
+ d = &f->dir[f->cdir++];
|
|
|
+ if(exclude){
|
|
|
+ char *p = makepath(f->f, d->name);
|
|
|
+ if(excludefile(p)){
|
|
|
+ free(p);
|
|
|
+ goto skipentry;
|
|
|
+ }
|
|
|
+ free(p);
|
|
|
+ }
|
|
|
+ m = convD2M(d, data, n);
|
|
|
+ DEBUG(DFD, "\t\tconvD2M %d\n", m);
|
|
|
+ if(m <= BIT16SZ){
|
|
|
+ DEBUG(DFD, "\t\t\tneeded %d\n", GBIT16(data));
|
|
|
+ /* not enough room for full entry; leave for next time */
|
|
|
+ f->cdir--;
|
|
|
+ return r;
|
|
|
+ }else{
|
|
|
+ data += m;
|
|
|
+ n -= m;
|
|
|
+ r += m;
|
|
|
+ f->offset += m;
|
|
|
+ }
|
|
|
+skipentry: if(f->cdir >= f->ndir){
|
|
|
+ f->cdir = f->ndir = 0;
|
|
|
+ free(f->dir);
|
|
|
+ f->dir = nil;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return r;
|
|
|
+}
|