#include #include #include "dat.h" #include "fns.h" static char* append(char **p, char *s) { int n; char *o; if(s == nil) return nil; n = strlen(s)+1; memmove(o = *p, s, n); *p += n; return o; } static Dir* xdirdup(Dir *d, int n) { char *p; Dir *o; int i; p = nil; for(i=0; i 0) *d = xdirdup(t, n); else *d = nil; return n; } static Dir* xdirstat0(char **path, int (*namecmp)(char *, char *), char *err) { char *base, *name; Dir *d, *t; int n, i; if(d = dirstat(*path)){ if(d->name[0] == 0) d->name = "/"; return d; } if(!splitpath(*path, &base, &name)) return nil; if((n = xdirread0(&base, namecmp, &t)) < 0) goto out; for(i=0; ipath); free(x->dir); free(x); } static int qidcmp(Qid *q1, Qid *q2) { return (q1->type != q2->type) || (q1->path != q2->path) || (q1->vers != q2->vers); } static XDir *xdirlist; static int xdircount; static int xdirread0(char **path, int (*namecmp)(char *, char *), Dir **d) { XDir *x, *p; int fd, n; Dir *t; t = nil; for(p = nil, x = xdirlist; x; p=x, x=x->next){ if(namecmp(x->path, *path)) continue; if(x == xdirlist) xdirlist = x->next; else p->next = x->next; while(t = dirstat(x->path)){ if(qidcmp(&t->qid, &x->qid)) break; free(t); x->next = xdirlist; xdirlist = x; if(strcmp(x->path, *path)){ free(*path); *path = strdup(x->path); } if(d) *d = x->dir; return x->ndir; } xdircount--; freexdir(x); break; } if((fd = open(*path, OREAD)) < 0){ free(t); if(t = xdirstat0(path, namecmp, "directory entry not found")) fd = open(*path, OREAD); } else if(t == nil) t = dirfstat(fd); n = -1; if(fd < 0 || t == nil) goto out; if((t->qid.type & QTDIR) == 0){ werrstr("not a directory"); goto out; } if((n = dirreadall(fd, d)) < 0) goto out; if(xdircount >= 8){ xdircount--; for(p = xdirlist, x = xdirlist->next; x->next; p = x, x = x->next) ; p->next = nil; freexdir(x); } x = mallocz(sizeof(*x), 1); x->qid = t->qid; x->path = strdup(*path); x->ndir = n; x->dir = *d; x->next = xdirlist; xdirlist = x; xdircount++; out: if(fd >= 0) close(fd); free(t); return n; } void xdirflush(char *path, int (*namecmp)(char *, char *)) { XDir **pp, **xx, *x; char *d, *s; int n; n = strlen(path); if(s = strrchr(path, '/')) n = s - path; d = smprint("%.*s", utfnlen(path, n), path); s = malloc(++n); for(pp = &xdirlist; x = *pp; pp = xx){ xx = &x->next; snprint(s, n, "%s", x->path); if(namecmp(d, s) == 0){ *pp = *xx; xx = pp; xdircount--; freexdir(x); } } free(s); free(d); }