17dd7cddfSDavid du Colombier #include <u.h> 27dd7cddfSDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier #include <draw.h> 47dd7cddfSDavid du Colombier #include <thread.h> 5*9a747e4fSDavid du Colombier #include <cursor.h> 67dd7cddfSDavid du Colombier #include <mouse.h> 77dd7cddfSDavid du Colombier #include <keyboard.h> 87dd7cddfSDavid du Colombier #include <frame.h> 97dd7cddfSDavid du Colombier #include <fcall.h> 107dd7cddfSDavid du Colombier #include <plumb.h> 117dd7cddfSDavid du Colombier #include "dat.h" 127dd7cddfSDavid du Colombier #include "fns.h" 137dd7cddfSDavid du Colombier 147dd7cddfSDavid du Colombier static int cfd; 157dd7cddfSDavid du Colombier static int sfd; 167dd7cddfSDavid du Colombier 177dd7cddfSDavid du Colombier enum 187dd7cddfSDavid du Colombier { 197dd7cddfSDavid du Colombier Nhash = 16, 207dd7cddfSDavid du Colombier DEBUG = 0 217dd7cddfSDavid du Colombier }; 227dd7cddfSDavid du Colombier 237dd7cddfSDavid du Colombier static Fid *fids[Nhash]; 247dd7cddfSDavid du Colombier 257dd7cddfSDavid du Colombier Fid *newfid(int); 267dd7cddfSDavid du Colombier 277dd7cddfSDavid du Colombier static Xfid* fsysflush(Xfid*, Fid*); 28*9a747e4fSDavid du Colombier static Xfid* fsysauth(Xfid*, Fid*); 29*9a747e4fSDavid du Colombier static Xfid* fsysversion(Xfid*, Fid*); 307dd7cddfSDavid du Colombier static Xfid* fsysattach(Xfid*, Fid*); 317dd7cddfSDavid du Colombier static Xfid* fsyswalk(Xfid*, Fid*); 327dd7cddfSDavid du Colombier static Xfid* fsysopen(Xfid*, Fid*); 337dd7cddfSDavid du Colombier static Xfid* fsyscreate(Xfid*, Fid*); 347dd7cddfSDavid du Colombier static Xfid* fsysread(Xfid*, Fid*); 357dd7cddfSDavid du Colombier static Xfid* fsyswrite(Xfid*, Fid*); 367dd7cddfSDavid du Colombier static Xfid* fsysclunk(Xfid*, Fid*); 377dd7cddfSDavid du Colombier static Xfid* fsysremove(Xfid*, Fid*); 387dd7cddfSDavid du Colombier static Xfid* fsysstat(Xfid*, Fid*); 397dd7cddfSDavid du Colombier static Xfid* fsyswstat(Xfid*, Fid*); 407dd7cddfSDavid du Colombier 417dd7cddfSDavid du Colombier Xfid* (*fcall[Tmax])(Xfid*, Fid*) = 427dd7cddfSDavid du Colombier { 437dd7cddfSDavid du Colombier [Tflush] = fsysflush, 44*9a747e4fSDavid du Colombier [Tversion] = fsysversion, 45*9a747e4fSDavid du Colombier [Tauth] = fsysauth, 467dd7cddfSDavid du Colombier [Tattach] = fsysattach, 477dd7cddfSDavid du Colombier [Twalk] = fsyswalk, 487dd7cddfSDavid du Colombier [Topen] = fsysopen, 497dd7cddfSDavid du Colombier [Tcreate] = fsyscreate, 507dd7cddfSDavid du Colombier [Tread] = fsysread, 517dd7cddfSDavid du Colombier [Twrite] = fsyswrite, 527dd7cddfSDavid du Colombier [Tclunk] = fsysclunk, 537dd7cddfSDavid du Colombier [Tremove]= fsysremove, 547dd7cddfSDavid du Colombier [Tstat] = fsysstat, 557dd7cddfSDavid du Colombier [Twstat] = fsyswstat, 567dd7cddfSDavid du Colombier }; 577dd7cddfSDavid du Colombier 587dd7cddfSDavid du Colombier char Eperm[] = "permission denied"; 597dd7cddfSDavid du Colombier char Eexist[] = "file does not exist"; 607dd7cddfSDavid du Colombier char Enotdir[] = "not a directory"; 617dd7cddfSDavid du Colombier 627dd7cddfSDavid du Colombier Dirtab dirtab[]= 637dd7cddfSDavid du Colombier { 64*9a747e4fSDavid du Colombier { ".", QTDIR, Qdir, 0500|DMDIR }, 65*9a747e4fSDavid du Colombier { "acme", QTDIR, Qacme, 0500|DMDIR }, 66*9a747e4fSDavid du Colombier { "cons", QTFILE, Qcons, 0600 }, 67*9a747e4fSDavid du Colombier { "consctl", QTFILE, Qconsctl, 0000 }, 68*9a747e4fSDavid du Colombier { "draw", QTDIR, Qdraw, 0000|DMDIR }, /* to suppress graphics progs started in acme */ 69*9a747e4fSDavid du Colombier { "editout", QTFILE, Qeditout, 0200 }, 70*9a747e4fSDavid du Colombier { "index", QTFILE, Qindex, 0400 }, 71*9a747e4fSDavid du Colombier { "label", QTFILE, Qlabel, 0600 }, 72*9a747e4fSDavid du Colombier { "new", QTDIR, Qnew, 0500|DMDIR }, 737dd7cddfSDavid du Colombier { nil, } 747dd7cddfSDavid du Colombier }; 757dd7cddfSDavid du Colombier 767dd7cddfSDavid du Colombier Dirtab dirtabw[]= 777dd7cddfSDavid du Colombier { 78*9a747e4fSDavid du Colombier { ".", QTDIR, Qdir, 0500|DMDIR }, 79*9a747e4fSDavid du Colombier { "addr", QTFILE, QWaddr, 0600 }, 80*9a747e4fSDavid du Colombier { "body", QTAPPEND, QWbody, 0600|DMAPPEND }, 81*9a747e4fSDavid du Colombier { "ctl", QTFILE, QWctl, 0600 }, 82*9a747e4fSDavid du Colombier { "data", QTFILE, QWdata, 0600 }, 83*9a747e4fSDavid du Colombier { "editout", QTFILE, QWeditout, 0200 }, 84*9a747e4fSDavid du Colombier { "event", QTFILE, QWevent, 0600 }, 85*9a747e4fSDavid du Colombier { "rdsel", QTFILE, QWrdsel, 0400 }, 86*9a747e4fSDavid du Colombier { "wrsel", QTFILE, QWwrsel, 0200 }, 87*9a747e4fSDavid du Colombier { "tag", QTAPPEND, QWtag, 0600|DMAPPEND }, 887dd7cddfSDavid du Colombier { nil, } 897dd7cddfSDavid du Colombier }; 907dd7cddfSDavid du Colombier 917dd7cddfSDavid du Colombier typedef struct Mnt Mnt; 927dd7cddfSDavid du Colombier struct Mnt 937dd7cddfSDavid du Colombier { 947dd7cddfSDavid du Colombier QLock; 957dd7cddfSDavid du Colombier int id; 967dd7cddfSDavid du Colombier Mntdir *md; 977dd7cddfSDavid du Colombier }; 987dd7cddfSDavid du Colombier 997dd7cddfSDavid du Colombier Mnt mnt; 1007dd7cddfSDavid du Colombier 1017dd7cddfSDavid du Colombier Xfid* respond(Xfid*, Fcall*, char*); 102*9a747e4fSDavid du Colombier int dostat(int, Dirtab*, uchar*, int, uint); 1037dd7cddfSDavid du Colombier uint getclock(void); 1047dd7cddfSDavid du Colombier 105*9a747e4fSDavid du Colombier char *user = "Wile E. Coyote"; 1067dd7cddfSDavid du Colombier int clockfd; 1077dd7cddfSDavid du Colombier static int closing = 0; 108*9a747e4fSDavid du Colombier int messagesize = Maxblock+IOHDRSZ; /* good start */ 1097dd7cddfSDavid du Colombier 1107dd7cddfSDavid du Colombier void fsysproc(void *); 1117dd7cddfSDavid du Colombier 1127dd7cddfSDavid du Colombier void 1137dd7cddfSDavid du Colombier fsysinit(void) 1147dd7cddfSDavid du Colombier { 1157dd7cddfSDavid du Colombier int p[2]; 1167dd7cddfSDavid du Colombier int n, fd; 117*9a747e4fSDavid du Colombier char buf[256]; 1187dd7cddfSDavid du Colombier 1197dd7cddfSDavid du Colombier if(pipe(p) < 0) 1207dd7cddfSDavid du Colombier error("can't create pipe"); 1217dd7cddfSDavid du Colombier cfd = p[0]; 1227dd7cddfSDavid du Colombier sfd = p[1]; 123*9a747e4fSDavid du Colombier fmtinstall('F', fcallfmt); 1247dd7cddfSDavid du Colombier clockfd = open("/dev/time", OREAD|OCEXEC); 1257dd7cddfSDavid du Colombier fd = open("/dev/user", OREAD); 1267dd7cddfSDavid du Colombier if(fd >= 0){ 127*9a747e4fSDavid du Colombier n = read(fd, buf, sizeof buf-1); 128*9a747e4fSDavid du Colombier if(n > 0){ 129*9a747e4fSDavid du Colombier buf[n] = 0; 130*9a747e4fSDavid du Colombier user = estrdup(buf); 131*9a747e4fSDavid du Colombier } 1327dd7cddfSDavid du Colombier close(fd); 1337dd7cddfSDavid du Colombier } 1347dd7cddfSDavid du Colombier proccreate(fsysproc, nil, STACK); 1357dd7cddfSDavid du Colombier } 1367dd7cddfSDavid du Colombier 1377dd7cddfSDavid du Colombier void 1387dd7cddfSDavid du Colombier fsysproc(void *) 1397dd7cddfSDavid du Colombier { 1407dd7cddfSDavid du Colombier int n; 1417dd7cddfSDavid du Colombier Xfid *x; 1427dd7cddfSDavid du Colombier Fid *f; 1437dd7cddfSDavid du Colombier Fcall t; 144*9a747e4fSDavid du Colombier uchar *buf; 1457dd7cddfSDavid du Colombier 1467dd7cddfSDavid du Colombier x = nil; 1477dd7cddfSDavid du Colombier for(;;){ 148*9a747e4fSDavid du Colombier buf = emalloc(messagesize+UTFmax); /* overflow for appending partial rune in xfidwrite */ 149*9a747e4fSDavid du Colombier n = read9pmsg(sfd, buf, messagesize); 1507dd7cddfSDavid du Colombier if(n <= 0){ 1517dd7cddfSDavid du Colombier if(closing) 1527dd7cddfSDavid du Colombier break; 1537dd7cddfSDavid du Colombier error("i/o error on server channel"); 1547dd7cddfSDavid du Colombier } 1557dd7cddfSDavid du Colombier if(x == nil){ 1567dd7cddfSDavid du Colombier sendp(cxfidalloc, nil); 1577dd7cddfSDavid du Colombier x = recvp(cxfidalloc); 1587dd7cddfSDavid du Colombier } 1597dd7cddfSDavid du Colombier x->buf = buf; 160*9a747e4fSDavid du Colombier if(convM2S(buf, n, x) != n) 1617dd7cddfSDavid du Colombier error("convert error in convM2S"); 1627dd7cddfSDavid du Colombier if(DEBUG) 1637dd7cddfSDavid du Colombier fprint(2, "%F\n", &x->Fcall); 1647dd7cddfSDavid du Colombier if(fcall[x->type] == nil) 1657dd7cddfSDavid du Colombier x = respond(x, &t, "bad fcall type"); 1667dd7cddfSDavid du Colombier else{ 167*9a747e4fSDavid du Colombier if(x->type==Tversion || x->type==Tauth) 1687dd7cddfSDavid du Colombier f = nil; 1697dd7cddfSDavid du Colombier else 1707dd7cddfSDavid du Colombier f = newfid(x->fid); 1717dd7cddfSDavid du Colombier x->f = f; 1727dd7cddfSDavid du Colombier x = (*fcall[x->type])(x, f); 1737dd7cddfSDavid du Colombier } 1747dd7cddfSDavid du Colombier } 1757dd7cddfSDavid du Colombier } 1767dd7cddfSDavid du Colombier 1777dd7cddfSDavid du Colombier Mntdir* 1787dd7cddfSDavid du Colombier fsysaddid(Rune *dir, int ndir, Rune **incl, int nincl) 1797dd7cddfSDavid du Colombier { 1807dd7cddfSDavid du Colombier Mntdir *m; 1817dd7cddfSDavid du Colombier int id; 1827dd7cddfSDavid du Colombier 1837dd7cddfSDavid du Colombier qlock(&mnt); 1847dd7cddfSDavid du Colombier id = ++mnt.id; 1857dd7cddfSDavid du Colombier m = emalloc(sizeof *m); 1867dd7cddfSDavid du Colombier m->id = id; 1877dd7cddfSDavid du Colombier m->dir = dir; 1887dd7cddfSDavid du Colombier m->ref = 1; /* one for Command, one will be incremented in attach */ 1897dd7cddfSDavid du Colombier m->ndir = ndir; 1907dd7cddfSDavid du Colombier m->next = mnt.md; 1917dd7cddfSDavid du Colombier m->incl = incl; 1927dd7cddfSDavid du Colombier m->nincl = nincl; 1937dd7cddfSDavid du Colombier mnt.md = m; 1947dd7cddfSDavid du Colombier qunlock(&mnt); 1957dd7cddfSDavid du Colombier return m; 1967dd7cddfSDavid du Colombier } 1977dd7cddfSDavid du Colombier 1987dd7cddfSDavid du Colombier void 1997dd7cddfSDavid du Colombier fsysdelid(Mntdir *idm) 2007dd7cddfSDavid du Colombier { 2017dd7cddfSDavid du Colombier Mntdir *m, *prev; 2027dd7cddfSDavid du Colombier int i; 2037dd7cddfSDavid du Colombier char buf[64]; 2047dd7cddfSDavid du Colombier 2057dd7cddfSDavid du Colombier if(idm == nil) 2067dd7cddfSDavid du Colombier return; 2077dd7cddfSDavid du Colombier qlock(&mnt); 2087dd7cddfSDavid du Colombier if(--idm->ref > 0){ 2097dd7cddfSDavid du Colombier qunlock(&mnt); 2107dd7cddfSDavid du Colombier return; 2117dd7cddfSDavid du Colombier } 2127dd7cddfSDavid du Colombier prev = nil; 2137dd7cddfSDavid du Colombier for(m=mnt.md; m; m=m->next){ 2147dd7cddfSDavid du Colombier if(m == idm){ 2157dd7cddfSDavid du Colombier if(prev) 2167dd7cddfSDavid du Colombier prev->next = m->next; 2177dd7cddfSDavid du Colombier else 2187dd7cddfSDavid du Colombier mnt.md = m->next; 2197dd7cddfSDavid du Colombier for(i=0; i<m->nincl; i++) 2207dd7cddfSDavid du Colombier free(m->incl[i]); 2217dd7cddfSDavid du Colombier free(m->incl); 2227dd7cddfSDavid du Colombier free(m->dir); 2237dd7cddfSDavid du Colombier free(m); 2247dd7cddfSDavid du Colombier qunlock(&mnt); 2257dd7cddfSDavid du Colombier return; 2267dd7cddfSDavid du Colombier } 2277dd7cddfSDavid du Colombier prev = m; 2287dd7cddfSDavid du Colombier } 2297dd7cddfSDavid du Colombier qunlock(&mnt); 2307dd7cddfSDavid du Colombier sprint(buf, "fsysdelid: can't find id %d\n", idm->id); 23159cc4ca5SDavid du Colombier sendp(cerr, estrdup(buf)); 2327dd7cddfSDavid du Colombier } 2337dd7cddfSDavid du Colombier 2347dd7cddfSDavid du Colombier /* 235*9a747e4fSDavid du Colombier * Called only in exec.c:/^run(), from a different FD group 2367dd7cddfSDavid du Colombier */ 2377dd7cddfSDavid du Colombier Mntdir* 2387dd7cddfSDavid du Colombier fsysmount(Rune *dir, int ndir, Rune **incl, int nincl) 2397dd7cddfSDavid du Colombier { 240*9a747e4fSDavid du Colombier char buf[256]; 2417dd7cddfSDavid du Colombier Mntdir *m; 2427dd7cddfSDavid du Colombier 2437dd7cddfSDavid du Colombier /* close server side so don't hang if acme is half-exited */ 2447dd7cddfSDavid du Colombier close(sfd); 2457dd7cddfSDavid du Colombier m = fsysaddid(dir, ndir, incl, nincl); 2467dd7cddfSDavid du Colombier sprint(buf, "%d", m->id); 247*9a747e4fSDavid du Colombier if(mount(cfd, -1, "/mnt/acme", MREPL, buf) < 0){ 2487dd7cddfSDavid du Colombier fsysdelid(m); 2497dd7cddfSDavid du Colombier return nil; 2507dd7cddfSDavid du Colombier } 2517dd7cddfSDavid du Colombier close(cfd); 2527dd7cddfSDavid du Colombier bind("/mnt/acme", "/mnt/wsys", MREPL); 2537dd7cddfSDavid du Colombier if(bind("/mnt/acme", "/dev", MBEFORE) < 0){ 2547dd7cddfSDavid du Colombier fsysdelid(m); 2557dd7cddfSDavid du Colombier return nil; 2567dd7cddfSDavid du Colombier } 2577dd7cddfSDavid du Colombier return m; 2587dd7cddfSDavid du Colombier } 2597dd7cddfSDavid du Colombier 2607dd7cddfSDavid du Colombier void 2617dd7cddfSDavid du Colombier fsysclose(void) 2627dd7cddfSDavid du Colombier { 2637dd7cddfSDavid du Colombier closing = 1; 2647dd7cddfSDavid du Colombier close(cfd); 2657dd7cddfSDavid du Colombier close(sfd); 2667dd7cddfSDavid du Colombier } 2677dd7cddfSDavid du Colombier 2687dd7cddfSDavid du Colombier Xfid* 2697dd7cddfSDavid du Colombier respond(Xfid *x, Fcall *t, char *err) 2707dd7cddfSDavid du Colombier { 2717dd7cddfSDavid du Colombier int n; 2727dd7cddfSDavid du Colombier 2737dd7cddfSDavid du Colombier if(err){ 2747dd7cddfSDavid du Colombier t->type = Rerror; 275*9a747e4fSDavid du Colombier t->ename = err; 2767dd7cddfSDavid du Colombier }else 2777dd7cddfSDavid du Colombier t->type = x->type+1; 2787dd7cddfSDavid du Colombier t->fid = x->fid; 2797dd7cddfSDavid du Colombier t->tag = x->tag; 2807dd7cddfSDavid du Colombier if(x->buf == nil) 281*9a747e4fSDavid du Colombier x->buf = emalloc(messagesize); 282*9a747e4fSDavid du Colombier n = convS2M(t, x->buf, messagesize); 283*9a747e4fSDavid du Colombier if(n <= 0) 2847dd7cddfSDavid du Colombier error("convert error in convS2M"); 2857dd7cddfSDavid du Colombier if(write(sfd, x->buf, n) != n) 2867dd7cddfSDavid du Colombier error("write error in respond"); 287*9a747e4fSDavid du Colombier free(x->buf); 2887dd7cddfSDavid du Colombier x->buf = nil; 2897dd7cddfSDavid du Colombier if(DEBUG) 2907dd7cddfSDavid du Colombier fprint(2, "r: %F\n", t); 2917dd7cddfSDavid du Colombier return x; 2927dd7cddfSDavid du Colombier } 2937dd7cddfSDavid du Colombier 2947dd7cddfSDavid du Colombier static 2957dd7cddfSDavid du Colombier Xfid* 296*9a747e4fSDavid du Colombier fsysversion(Xfid *x, Fid*) 2977dd7cddfSDavid du Colombier { 2987dd7cddfSDavid du Colombier Fcall t; 2997dd7cddfSDavid du Colombier 300*9a747e4fSDavid du Colombier if(x->msize < 256) 301*9a747e4fSDavid du Colombier return respond(x, &t, "version: message size too small"); 302*9a747e4fSDavid du Colombier messagesize = x->msize; 303*9a747e4fSDavid du Colombier t.msize = messagesize; 304*9a747e4fSDavid du Colombier if(strncmp(x->version, "9P2000", 6) != 0) 305*9a747e4fSDavid du Colombier return respond(x, &t, "unrecognized 9P version"); 306*9a747e4fSDavid du Colombier t.version = "9P2000"; 3077dd7cddfSDavid du Colombier return respond(x, &t, nil); 3087dd7cddfSDavid du Colombier } 3097dd7cddfSDavid du Colombier 3107dd7cddfSDavid du Colombier static 3117dd7cddfSDavid du Colombier Xfid* 312*9a747e4fSDavid du Colombier fsysauth(Xfid *x, Fid*) 3137dd7cddfSDavid du Colombier { 314*9a747e4fSDavid du Colombier return respond(x, nil, "acme: authentication not required"); 3157dd7cddfSDavid du Colombier } 3167dd7cddfSDavid du Colombier 3177dd7cddfSDavid du Colombier static 3187dd7cddfSDavid du Colombier Xfid* 3197dd7cddfSDavid du Colombier fsysflush(Xfid *x, Fid*) 3207dd7cddfSDavid du Colombier { 3217dd7cddfSDavid du Colombier sendp(x->c, xfidflush); 3227dd7cddfSDavid du Colombier return nil; 3237dd7cddfSDavid du Colombier } 3247dd7cddfSDavid du Colombier 3257dd7cddfSDavid du Colombier static 3267dd7cddfSDavid du Colombier Xfid* 3277dd7cddfSDavid du Colombier fsysattach(Xfid *x, Fid *f) 3287dd7cddfSDavid du Colombier { 3297dd7cddfSDavid du Colombier Fcall t; 3307dd7cddfSDavid du Colombier int id; 3317dd7cddfSDavid du Colombier Mntdir *m; 3327dd7cddfSDavid du Colombier 3337dd7cddfSDavid du Colombier if(strcmp(x->uname, user) != 0) 3347dd7cddfSDavid du Colombier return respond(x, &t, Eperm); 3357dd7cddfSDavid du Colombier f->busy = TRUE; 3367dd7cddfSDavid du Colombier f->open = FALSE; 337*9a747e4fSDavid du Colombier f->qid.path = Qdir; 338*9a747e4fSDavid du Colombier f->qid.type = QTDIR; 339*9a747e4fSDavid du Colombier f->qid.vers = 0; 3407dd7cddfSDavid du Colombier f->dir = dirtab; 3417dd7cddfSDavid du Colombier f->nrpart = 0; 3427dd7cddfSDavid du Colombier f->w = nil; 3437dd7cddfSDavid du Colombier t.qid = f->qid; 3447dd7cddfSDavid du Colombier f->mntdir = nil; 3457dd7cddfSDavid du Colombier id = atoi(x->aname); 3467dd7cddfSDavid du Colombier qlock(&mnt); 3477dd7cddfSDavid du Colombier for(m=mnt.md; m; m=m->next) 3487dd7cddfSDavid du Colombier if(m->id == id){ 3497dd7cddfSDavid du Colombier f->mntdir = m; 3507dd7cddfSDavid du Colombier m->ref++; 3517dd7cddfSDavid du Colombier break; 3527dd7cddfSDavid du Colombier } 3537dd7cddfSDavid du Colombier if(m == nil) 35459cc4ca5SDavid du Colombier sendp(cerr, estrdup("unknown id in attach")); 3557dd7cddfSDavid du Colombier qunlock(&mnt); 3567dd7cddfSDavid du Colombier return respond(x, &t, nil); 3577dd7cddfSDavid du Colombier } 3587dd7cddfSDavid du Colombier 3597dd7cddfSDavid du Colombier static 3607dd7cddfSDavid du Colombier Xfid* 361*9a747e4fSDavid du Colombier fsyswalk(Xfid *x, Fid *f) 3627dd7cddfSDavid du Colombier { 3637dd7cddfSDavid du Colombier Fcall t; 364*9a747e4fSDavid du Colombier int c, i, j, id; 365*9a747e4fSDavid du Colombier Qid q; 366*9a747e4fSDavid du Colombier uchar type; 367*9a747e4fSDavid du Colombier ulong path; 368*9a747e4fSDavid du Colombier Fid *nf; 369*9a747e4fSDavid du Colombier Dirtab *d, *dir; 370*9a747e4fSDavid du Colombier Window *w; 371*9a747e4fSDavid du Colombier char *err; 3727dd7cddfSDavid du Colombier 373*9a747e4fSDavid du Colombier nf = nil; 374*9a747e4fSDavid du Colombier w = nil; 3757dd7cddfSDavid du Colombier if(f->open) 376*9a747e4fSDavid du Colombier return respond(x, &t, "walk of open file"); 377*9a747e4fSDavid du Colombier if(x->fid != x->newfid){ 3787dd7cddfSDavid du Colombier nf = newfid(x->newfid); 379*9a747e4fSDavid du Colombier if(nf->busy) 380*9a747e4fSDavid du Colombier return respond(x, &t, "newfid already in use"); 3817dd7cddfSDavid du Colombier nf->busy = TRUE; 3827dd7cddfSDavid du Colombier nf->open = FALSE; 3837dd7cddfSDavid du Colombier nf->mntdir = f->mntdir; 3847dd7cddfSDavid du Colombier if(f->mntdir) 3857dd7cddfSDavid du Colombier f->mntdir->ref++; 3867dd7cddfSDavid du Colombier nf->dir = f->dir; 3877dd7cddfSDavid du Colombier nf->qid = f->qid; 3887dd7cddfSDavid du Colombier nf->w = f->w; 3897dd7cddfSDavid du Colombier nf->nrpart = 0; /* not open, so must be zero */ 3907dd7cddfSDavid du Colombier if(nf->w) 3917dd7cddfSDavid du Colombier incref(nf->w); 392*9a747e4fSDavid du Colombier f = nf; /* walk f */ 3937dd7cddfSDavid du Colombier } 3947dd7cddfSDavid du Colombier 395*9a747e4fSDavid du Colombier t.nwqid = 0; 396*9a747e4fSDavid du Colombier err = nil; 397*9a747e4fSDavid du Colombier dir = nil; 398*9a747e4fSDavid du Colombier id = WIN(f->qid); 399*9a747e4fSDavid du Colombier q = f->qid; 4007dd7cddfSDavid du Colombier 401*9a747e4fSDavid du Colombier if(x->nwname > 0){ 402*9a747e4fSDavid du Colombier for(i=0; i<x->nwname; i++){ 403*9a747e4fSDavid du Colombier if((q.type & QTDIR) == 0){ 404*9a747e4fSDavid du Colombier err = Enotdir; 405*9a747e4fSDavid du Colombier break; 406*9a747e4fSDavid du Colombier } 407*9a747e4fSDavid du Colombier 408*9a747e4fSDavid du Colombier if(strcmp(x->wname[i], "..") == 0){ 409*9a747e4fSDavid du Colombier type = QTDIR; 410*9a747e4fSDavid du Colombier path = Qdir; 4117dd7cddfSDavid du Colombier id = 0; 412*9a747e4fSDavid du Colombier if(w){ 413*9a747e4fSDavid du Colombier winclose(w); 414*9a747e4fSDavid du Colombier w = nil; 4157dd7cddfSDavid du Colombier } 416*9a747e4fSDavid du Colombier Accept: 417*9a747e4fSDavid du Colombier if(i == MAXWELEM){ 418*9a747e4fSDavid du Colombier err = "name too long"; 419*9a747e4fSDavid du Colombier break; 420*9a747e4fSDavid du Colombier } 421*9a747e4fSDavid du Colombier q.type = type; 422*9a747e4fSDavid du Colombier q.vers = 0; 423*9a747e4fSDavid du Colombier q.path = QID(id, path); 424*9a747e4fSDavid du Colombier t.wqid[t.nwqid++] = q; 425*9a747e4fSDavid du Colombier continue; 426*9a747e4fSDavid du Colombier } 427*9a747e4fSDavid du Colombier 4287dd7cddfSDavid du Colombier /* is it a numeric name? */ 429*9a747e4fSDavid du Colombier for(j=0; (c=x->wname[i][j]); j++) 4307dd7cddfSDavid du Colombier if(c<'0' || '9'<c) 4317dd7cddfSDavid du Colombier goto Regular; 4327dd7cddfSDavid du Colombier /* yes: it's a directory */ 433*9a747e4fSDavid du Colombier if(w) /* name has form 27/23; get out before losing w */ 434*9a747e4fSDavid du Colombier break; 435*9a747e4fSDavid du Colombier id = atoi(x->wname[i]); 4367dd7cddfSDavid du Colombier qlock(&row); 4377dd7cddfSDavid du Colombier w = lookid(id, FALSE); 4387dd7cddfSDavid du Colombier if(w == nil){ 4397dd7cddfSDavid du Colombier qunlock(&row); 440*9a747e4fSDavid du Colombier break; 4417dd7cddfSDavid du Colombier } 442*9a747e4fSDavid du Colombier incref(w); /* we'll drop reference at end if there's an error */ 443*9a747e4fSDavid du Colombier path = Qdir; 444*9a747e4fSDavid du Colombier type = QTDIR; 4457dd7cddfSDavid du Colombier qunlock(&row); 446*9a747e4fSDavid du Colombier dir = dirtabw; 447*9a747e4fSDavid du Colombier goto Accept; 4487dd7cddfSDavid du Colombier 4497dd7cddfSDavid du Colombier Regular: 450*9a747e4fSDavid du Colombier // if(FILE(f->qid) == Qacme) /* empty directory */ 451*9a747e4fSDavid du Colombier // break; 452*9a747e4fSDavid du Colombier if(strcmp(x->wname[i], "new") == 0){ 453*9a747e4fSDavid du Colombier if(w) 454*9a747e4fSDavid du Colombier error("w set in walk to new"); 455*9a747e4fSDavid du Colombier sendp(cnewwindow, nil); /* signal newwindowthread */ 456*9a747e4fSDavid du Colombier w = recvp(cnewwindow); /* receive new window */ 457*9a747e4fSDavid du Colombier incref(w); 458*9a747e4fSDavid du Colombier type = QTDIR; 459*9a747e4fSDavid du Colombier path = QID(w->id, Qdir); 460*9a747e4fSDavid du Colombier id = w->id; 461*9a747e4fSDavid du Colombier dir = dirtabw; 462*9a747e4fSDavid du Colombier goto Accept; 463*9a747e4fSDavid du Colombier } 464*9a747e4fSDavid du Colombier 4657dd7cddfSDavid du Colombier if(id == 0) 4667dd7cddfSDavid du Colombier d = dirtab; 4677dd7cddfSDavid du Colombier else 4687dd7cddfSDavid du Colombier d = dirtabw; 4697dd7cddfSDavid du Colombier d++; /* skip '.' */ 4707dd7cddfSDavid du Colombier for(; d->name; d++) 471*9a747e4fSDavid du Colombier if(strcmp(x->wname[i], d->name) == 0){ 472*9a747e4fSDavid du Colombier path = d->qid; 473*9a747e4fSDavid du Colombier type = d->type; 474*9a747e4fSDavid du Colombier dir = d; 475*9a747e4fSDavid du Colombier goto Accept; 4767dd7cddfSDavid du Colombier } 4777dd7cddfSDavid du Colombier 478*9a747e4fSDavid du Colombier break; /* file not found */ 4797dd7cddfSDavid du Colombier } 4807dd7cddfSDavid du Colombier 481*9a747e4fSDavid du Colombier if(i==0 && err == nil) 482*9a747e4fSDavid du Colombier err = Eexist; 483*9a747e4fSDavid du Colombier } 4847dd7cddfSDavid du Colombier 485*9a747e4fSDavid du Colombier if(err!=nil || t.nwqid<x->nwname){ 486*9a747e4fSDavid du Colombier if(nf){ 487*9a747e4fSDavid du Colombier nf->busy = FALSE; 488*9a747e4fSDavid du Colombier fsysdelid(nf->mntdir); 489*9a747e4fSDavid du Colombier } 490*9a747e4fSDavid du Colombier }else if(t.nwqid == x->nwname){ 491*9a747e4fSDavid du Colombier if(w){ 492*9a747e4fSDavid du Colombier f->w = w; 493*9a747e4fSDavid du Colombier w = nil; /* don't drop the reference */ 494*9a747e4fSDavid du Colombier } 495*9a747e4fSDavid du Colombier if(dir) 496*9a747e4fSDavid du Colombier f->dir = dir; 497*9a747e4fSDavid du Colombier f->qid = q; 498*9a747e4fSDavid du Colombier } 499*9a747e4fSDavid du Colombier 500*9a747e4fSDavid du Colombier if(w != nil) 501*9a747e4fSDavid du Colombier winclose(w); 502*9a747e4fSDavid du Colombier 503*9a747e4fSDavid du Colombier return respond(x, &t, err); 5047dd7cddfSDavid du Colombier } 5057dd7cddfSDavid du Colombier 5067dd7cddfSDavid du Colombier static 5077dd7cddfSDavid du Colombier Xfid* 5087dd7cddfSDavid du Colombier fsysopen(Xfid *x, Fid *f) 5097dd7cddfSDavid du Colombier { 5107dd7cddfSDavid du Colombier Fcall t; 5117dd7cddfSDavid du Colombier int m; 5127dd7cddfSDavid du Colombier 5137dd7cddfSDavid du Colombier /* can't truncate anything, so just disregard */ 5147dd7cddfSDavid du Colombier x->mode &= ~(OTRUNC|OCEXEC); 5157dd7cddfSDavid du Colombier /* can't execute or remove anything */ 5167dd7cddfSDavid du Colombier if(x->mode==OEXEC || (x->mode&ORCLOSE)) 5177dd7cddfSDavid du Colombier goto Deny; 5187dd7cddfSDavid du Colombier switch(x->mode){ 5197dd7cddfSDavid du Colombier default: 5207dd7cddfSDavid du Colombier goto Deny; 5217dd7cddfSDavid du Colombier case OREAD: 5227dd7cddfSDavid du Colombier m = 0400; 5237dd7cddfSDavid du Colombier break; 5247dd7cddfSDavid du Colombier case OWRITE: 5257dd7cddfSDavid du Colombier m = 0200; 5267dd7cddfSDavid du Colombier break; 5277dd7cddfSDavid du Colombier case ORDWR: 5287dd7cddfSDavid du Colombier m = 0600; 5297dd7cddfSDavid du Colombier break; 5307dd7cddfSDavid du Colombier } 531*9a747e4fSDavid du Colombier if(((f->dir->perm&~(DMDIR|DMAPPEND))&m) != m) 5327dd7cddfSDavid du Colombier goto Deny; 5337dd7cddfSDavid du Colombier 5347dd7cddfSDavid du Colombier sendp(x->c, xfidopen); 5357dd7cddfSDavid du Colombier return nil; 5367dd7cddfSDavid du Colombier 5377dd7cddfSDavid du Colombier Deny: 5387dd7cddfSDavid du Colombier return respond(x, &t, Eperm); 5397dd7cddfSDavid du Colombier } 5407dd7cddfSDavid du Colombier 5417dd7cddfSDavid du Colombier static 5427dd7cddfSDavid du Colombier Xfid* 5437dd7cddfSDavid du Colombier fsyscreate(Xfid *x, Fid*) 5447dd7cddfSDavid du Colombier { 5457dd7cddfSDavid du Colombier Fcall t; 5467dd7cddfSDavid du Colombier 5477dd7cddfSDavid du Colombier return respond(x, &t, Eperm); 5487dd7cddfSDavid du Colombier } 5497dd7cddfSDavid du Colombier 5507dd7cddfSDavid du Colombier static 5517dd7cddfSDavid du Colombier int 5527dd7cddfSDavid du Colombier idcmp(void *a, void *b) 5537dd7cddfSDavid du Colombier { 5547dd7cddfSDavid du Colombier return *(int*)a - *(int*)b; 5557dd7cddfSDavid du Colombier } 5567dd7cddfSDavid du Colombier 5577dd7cddfSDavid du Colombier static 5587dd7cddfSDavid du Colombier Xfid* 5597dd7cddfSDavid du Colombier fsysread(Xfid *x, Fid *f) 5607dd7cddfSDavid du Colombier { 5617dd7cddfSDavid du Colombier Fcall t; 562*9a747e4fSDavid du Colombier uchar *b; 5637dd7cddfSDavid du Colombier int i, id, n, o, e, j, k, *ids, nids; 5647dd7cddfSDavid du Colombier Dirtab *d, dt; 5657dd7cddfSDavid du Colombier Column *c; 566*9a747e4fSDavid du Colombier uint clock, len; 5677dd7cddfSDavid du Colombier char buf[16]; 5687dd7cddfSDavid du Colombier 569*9a747e4fSDavid du Colombier if(f->qid.type & QTDIR){ 5707dd7cddfSDavid du Colombier if(FILE(f->qid) == Qacme){ /* empty dir */ 5717dd7cddfSDavid du Colombier t.data = nil; 5727dd7cddfSDavid du Colombier t.count = 0; 5737dd7cddfSDavid du Colombier respond(x, &t, nil); 5747dd7cddfSDavid du Colombier return x; 5757dd7cddfSDavid du Colombier } 5767dd7cddfSDavid du Colombier o = x->offset; 5777dd7cddfSDavid du Colombier e = x->offset+x->count; 5787dd7cddfSDavid du Colombier clock = getclock(); 579*9a747e4fSDavid du Colombier b = emalloc(messagesize); 5807dd7cddfSDavid du Colombier id = WIN(f->qid); 5817dd7cddfSDavid du Colombier n = 0; 5827dd7cddfSDavid du Colombier if(id > 0) 5837dd7cddfSDavid du Colombier d = dirtabw; 5847dd7cddfSDavid du Colombier else 5857dd7cddfSDavid du Colombier d = dirtab; 5867dd7cddfSDavid du Colombier d++; /* first entry is '.' */ 587*9a747e4fSDavid du Colombier for(i=0; d->name!=nil && i<e; i+=len){ 588*9a747e4fSDavid du Colombier len = dostat(WIN(x->f->qid), d, b+n, x->count-n, clock); 589*9a747e4fSDavid du Colombier if(len <= BIT16SZ) 590*9a747e4fSDavid du Colombier break; 591*9a747e4fSDavid du Colombier if(i >= o) 592*9a747e4fSDavid du Colombier n += len; 5937dd7cddfSDavid du Colombier d++; 5947dd7cddfSDavid du Colombier } 5957dd7cddfSDavid du Colombier if(id == 0){ 5967dd7cddfSDavid du Colombier qlock(&row); 5977dd7cddfSDavid du Colombier nids = 0; 5987dd7cddfSDavid du Colombier ids = nil; 5997dd7cddfSDavid du Colombier for(j=0; j<row.ncol; j++){ 6007dd7cddfSDavid du Colombier c = row.col[j]; 6017dd7cddfSDavid du Colombier for(k=0; k<c->nw; k++){ 6027dd7cddfSDavid du Colombier ids = realloc(ids, (nids+1)*sizeof(int)); 6037dd7cddfSDavid du Colombier ids[nids++] = c->w[k]->id; 6047dd7cddfSDavid du Colombier } 6057dd7cddfSDavid du Colombier } 6067dd7cddfSDavid du Colombier qunlock(&row); 6077dd7cddfSDavid du Colombier qsort(ids, nids, sizeof ids[0], idcmp); 6087dd7cddfSDavid du Colombier j = 0; 6097dd7cddfSDavid du Colombier dt.name = buf; 610*9a747e4fSDavid du Colombier for(; j<nids && i<e; i+=len){ 6117dd7cddfSDavid du Colombier k = ids[j]; 6127dd7cddfSDavid du Colombier sprint(dt.name, "%d", k); 613*9a747e4fSDavid du Colombier dt.qid = QID(k, Qdir); 614*9a747e4fSDavid du Colombier dt.type = QTDIR; 615*9a747e4fSDavid du Colombier dt.perm = DMDIR|0700; 616*9a747e4fSDavid du Colombier len = dostat(k, &dt, b+n, x->count-n, clock); 617*9a747e4fSDavid du Colombier if(len == 0) 618*9a747e4fSDavid du Colombier break; 619*9a747e4fSDavid du Colombier if(i >= o) 620*9a747e4fSDavid du Colombier n += len; 6217dd7cddfSDavid du Colombier j++; 6227dd7cddfSDavid du Colombier } 6237dd7cddfSDavid du Colombier free(ids); 6247dd7cddfSDavid du Colombier } 625*9a747e4fSDavid du Colombier t.data = (char*)b; 6267dd7cddfSDavid du Colombier t.count = n; 6277dd7cddfSDavid du Colombier respond(x, &t, nil); 628*9a747e4fSDavid du Colombier free(b); 6297dd7cddfSDavid du Colombier return x; 6307dd7cddfSDavid du Colombier } 6317dd7cddfSDavid du Colombier sendp(x->c, xfidread); 6327dd7cddfSDavid du Colombier return nil; 6337dd7cddfSDavid du Colombier } 6347dd7cddfSDavid du Colombier 6357dd7cddfSDavid du Colombier static 6367dd7cddfSDavid du Colombier Xfid* 6377dd7cddfSDavid du Colombier fsyswrite(Xfid *x, Fid*) 6387dd7cddfSDavid du Colombier { 6397dd7cddfSDavid du Colombier sendp(x->c, xfidwrite); 6407dd7cddfSDavid du Colombier return nil; 6417dd7cddfSDavid du Colombier } 6427dd7cddfSDavid du Colombier 6437dd7cddfSDavid du Colombier static 6447dd7cddfSDavid du Colombier Xfid* 6457dd7cddfSDavid du Colombier fsysclunk(Xfid *x, Fid *f) 6467dd7cddfSDavid du Colombier { 6477dd7cddfSDavid du Colombier fsysdelid(f->mntdir); 6487dd7cddfSDavid du Colombier sendp(x->c, xfidclose); 6497dd7cddfSDavid du Colombier return nil; 6507dd7cddfSDavid du Colombier } 6517dd7cddfSDavid du Colombier 6527dd7cddfSDavid du Colombier static 6537dd7cddfSDavid du Colombier Xfid* 6547dd7cddfSDavid du Colombier fsysremove(Xfid *x, Fid*) 6557dd7cddfSDavid du Colombier { 6567dd7cddfSDavid du Colombier Fcall t; 6577dd7cddfSDavid du Colombier 6587dd7cddfSDavid du Colombier return respond(x, &t, Eperm); 6597dd7cddfSDavid du Colombier } 6607dd7cddfSDavid du Colombier 6617dd7cddfSDavid du Colombier static 6627dd7cddfSDavid du Colombier Xfid* 6637dd7cddfSDavid du Colombier fsysstat(Xfid *x, Fid *f) 6647dd7cddfSDavid du Colombier { 6657dd7cddfSDavid du Colombier Fcall t; 6667dd7cddfSDavid du Colombier 667*9a747e4fSDavid du Colombier t.stat = emalloc(messagesize-IOHDRSZ); 668*9a747e4fSDavid du Colombier t.nstat = dostat(WIN(x->f->qid), f->dir, t.stat, messagesize-IOHDRSZ, getclock()); 669*9a747e4fSDavid du Colombier x = respond(x, &t, nil); 670*9a747e4fSDavid du Colombier free(t.stat); 671*9a747e4fSDavid du Colombier return x; 6727dd7cddfSDavid du Colombier } 6737dd7cddfSDavid du Colombier 6747dd7cddfSDavid du Colombier static 6757dd7cddfSDavid du Colombier Xfid* 6767dd7cddfSDavid du Colombier fsyswstat(Xfid *x, Fid*) 6777dd7cddfSDavid du Colombier { 6787dd7cddfSDavid du Colombier Fcall t; 6797dd7cddfSDavid du Colombier 6807dd7cddfSDavid du Colombier return respond(x, &t, Eperm); 6817dd7cddfSDavid du Colombier } 6827dd7cddfSDavid du Colombier 6837dd7cddfSDavid du Colombier Fid* 6847dd7cddfSDavid du Colombier newfid(int fid) 6857dd7cddfSDavid du Colombier { 6867dd7cddfSDavid du Colombier Fid *f, *ff, **fh; 6877dd7cddfSDavid du Colombier 6887dd7cddfSDavid du Colombier ff = nil; 6897dd7cddfSDavid du Colombier fh = &fids[fid&(Nhash-1)]; 6907dd7cddfSDavid du Colombier for(f=*fh; f; f=f->next) 6917dd7cddfSDavid du Colombier if(f->fid == fid) 6927dd7cddfSDavid du Colombier return f; 6937dd7cddfSDavid du Colombier else if(ff==nil && f->busy==FALSE) 6947dd7cddfSDavid du Colombier ff = f; 6957dd7cddfSDavid du Colombier if(ff){ 6967dd7cddfSDavid du Colombier ff->fid = fid; 6977dd7cddfSDavid du Colombier return ff; 6987dd7cddfSDavid du Colombier } 6997dd7cddfSDavid du Colombier f = emalloc(sizeof *f); 7007dd7cddfSDavid du Colombier f->fid = fid; 7017dd7cddfSDavid du Colombier f->next = *fh; 7027dd7cddfSDavid du Colombier *fh = f; 7037dd7cddfSDavid du Colombier return f; 7047dd7cddfSDavid du Colombier } 7057dd7cddfSDavid du Colombier 7067dd7cddfSDavid du Colombier uint 7077dd7cddfSDavid du Colombier getclock() 7087dd7cddfSDavid du Colombier { 7097dd7cddfSDavid du Colombier char buf[32]; 7107dd7cddfSDavid du Colombier 711*9a747e4fSDavid du Colombier buf[0] = '\0'; 712*9a747e4fSDavid du Colombier pread(clockfd, buf, sizeof buf, 0); 7137dd7cddfSDavid du Colombier return atoi(buf); 7147dd7cddfSDavid du Colombier } 7157dd7cddfSDavid du Colombier 716*9a747e4fSDavid du Colombier int 717*9a747e4fSDavid du Colombier dostat(int id, Dirtab *dir, uchar *buf, int nbuf, uint clock) 7187dd7cddfSDavid du Colombier { 7197dd7cddfSDavid du Colombier Dir d; 7207dd7cddfSDavid du Colombier 7217dd7cddfSDavid du Colombier d.qid.path = QID(id, dir->qid); 7227dd7cddfSDavid du Colombier d.qid.vers = 0; 723*9a747e4fSDavid du Colombier d.qid.type = dir->type; 7247dd7cddfSDavid du Colombier d.mode = dir->perm; 7257dd7cddfSDavid du Colombier d.length = 0; /* would be nice to do better */ 726*9a747e4fSDavid du Colombier d.name = dir->name; 727*9a747e4fSDavid du Colombier d.uid = user; 728*9a747e4fSDavid du Colombier d.gid = user; 729*9a747e4fSDavid du Colombier d.muid = user; 7307dd7cddfSDavid du Colombier d.atime = clock; 7317dd7cddfSDavid du Colombier d.mtime = clock; 732*9a747e4fSDavid du Colombier return convD2M(&d, buf, nbuf); 7337dd7cddfSDavid du Colombier } 734