17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <auth.h>
47dd7cddfSDavid du Colombier #include <fcall.h>
57dd7cddfSDavid du Colombier #include <thread.h>
69a747e4fSDavid du Colombier #include <9p.h>
77dd7cddfSDavid du Colombier
8*22a127bbSDavid du Colombier void (*_forker)(void(*)(void*), void*, int);
9*22a127bbSDavid du Colombier
109a747e4fSDavid du Colombier static char Ebadattach[] = "unknown specifier in attach";
119a747e4fSDavid du Colombier static char Ebadoffset[] = "bad offset";
129a747e4fSDavid du Colombier static char Ebadcount[] = "bad count";
139a747e4fSDavid du Colombier static char Ebotch[] = "9P protocol botch";
149a747e4fSDavid du Colombier static char Ecreatenondir[] = "create in non-directory";
159a747e4fSDavid du Colombier static char Edupfid[] = "duplicate fid";
169a747e4fSDavid du Colombier static char Eduptag[] = "duplicate tag";
179a747e4fSDavid du Colombier static char Eisdir[] = "is a directory";
189a747e4fSDavid du Colombier static char Enocreate[] = "create prohibited";
199a747e4fSDavid du Colombier static char Enomem[] = "out of memory";
209a747e4fSDavid du Colombier static char Enoremove[] = "remove prohibited";
219a747e4fSDavid du Colombier static char Enostat[] = "stat prohibited";
229a747e4fSDavid du Colombier static char Enotfound[] = "file not found";
237dd7cddfSDavid du Colombier static char Enowrite[] = "write prohibited";
247dd7cddfSDavid du Colombier static char Enowstat[] = "wstat prohibited";
259a747e4fSDavid du Colombier static char Eperm[] = "permission denied";
269a747e4fSDavid du Colombier static char Eunknownfid[] = "unknown fid";
279a747e4fSDavid du Colombier static char Ebaddir[] = "bad directory in wstat";
289a747e4fSDavid du Colombier static char Ewalknodir[] = "walk in non-directory";
297dd7cddfSDavid du Colombier
307dd7cddfSDavid du Colombier static void
setfcallerror(Fcall * f,char * err)317dd7cddfSDavid du Colombier setfcallerror(Fcall *f, char *err)
327dd7cddfSDavid du Colombier {
339a747e4fSDavid du Colombier f->ename = err;
347dd7cddfSDavid du Colombier f->type = Rerror;
357dd7cddfSDavid du Colombier }
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier static void
changemsize(Srv * srv,int msize)389a747e4fSDavid du Colombier changemsize(Srv *srv, int msize)
397dd7cddfSDavid du Colombier {
409a747e4fSDavid du Colombier if(srv->rbuf && srv->wbuf && srv->msize == msize)
419a747e4fSDavid du Colombier return;
429a747e4fSDavid du Colombier qlock(&srv->rlock);
439a747e4fSDavid du Colombier qlock(&srv->wlock);
449a747e4fSDavid du Colombier srv->msize = msize;
459a747e4fSDavid du Colombier free(srv->rbuf);
469a747e4fSDavid du Colombier free(srv->wbuf);
479a747e4fSDavid du Colombier srv->rbuf = emalloc9p(msize);
489a747e4fSDavid du Colombier srv->wbuf = emalloc9p(msize);
499a747e4fSDavid du Colombier qunlock(&srv->rlock);
509a747e4fSDavid du Colombier qunlock(&srv->wlock);
517dd7cddfSDavid du Colombier }
527dd7cddfSDavid du Colombier
539a747e4fSDavid du Colombier static Req*
getreq(Srv * s)549a747e4fSDavid du Colombier getreq(Srv *s)
557dd7cddfSDavid du Colombier {
567dd7cddfSDavid du Colombier long n;
579a747e4fSDavid du Colombier uchar *buf;
587dd7cddfSDavid du Colombier Fcall f;
597dd7cddfSDavid du Colombier Req *r;
607dd7cddfSDavid du Colombier
619a747e4fSDavid du Colombier qlock(&s->rlock);
629a747e4fSDavid du Colombier if((n = read9pmsg(s->infd, s->rbuf, s->msize)) <= 0){
639a747e4fSDavid du Colombier qunlock(&s->rlock);
647dd7cddfSDavid du Colombier return nil;
659a747e4fSDavid du Colombier }
667dd7cddfSDavid du Colombier
679a747e4fSDavid du Colombier buf = emalloc9p(n);
689a747e4fSDavid du Colombier memmove(buf, s->rbuf, n);
699a747e4fSDavid du Colombier qunlock(&s->rlock);
709a747e4fSDavid du Colombier
719a747e4fSDavid du Colombier if(convM2S(buf, n, &f) != n){
727dd7cddfSDavid du Colombier free(buf);
737dd7cddfSDavid du Colombier return nil;
747dd7cddfSDavid du Colombier }
759a747e4fSDavid du Colombier
769a747e4fSDavid du Colombier if((r=allocreq(s->rpool, f.tag)) == nil){ /* duplicate tag: cons up a fake Req */
779a747e4fSDavid du Colombier r = emalloc9p(sizeof *r);
787dd7cddfSDavid du Colombier incref(&r->ref);
797dd7cddfSDavid du Colombier r->tag = f.tag;
809a747e4fSDavid du Colombier r->ifcall = f;
817dd7cddfSDavid du Colombier r->error = Eduptag;
827dd7cddfSDavid du Colombier r->buf = buf;
837dd7cddfSDavid du Colombier r->responded = 0;
849a747e4fSDavid du Colombier r->type = 0;
859a747e4fSDavid du Colombier r->srv = s;
869a747e4fSDavid du Colombier r->pool = nil;
879a747e4fSDavid du Colombier if(chatty9p)
889a747e4fSDavid du Colombier fprint(2, "<-%d- %F: dup tag\n", s->infd, &f);
897dd7cddfSDavid du Colombier return r;
907dd7cddfSDavid du Colombier }
917dd7cddfSDavid du Colombier
929a747e4fSDavid du Colombier r->srv = s;
937dd7cddfSDavid du Colombier r->responded = 0;
947dd7cddfSDavid du Colombier r->buf = buf;
959a747e4fSDavid du Colombier r->ifcall = f;
969a747e4fSDavid du Colombier memset(&r->ofcall, 0, sizeof r->ofcall);
979a747e4fSDavid du Colombier r->type = r->ifcall.type;
987dd7cddfSDavid du Colombier
999a747e4fSDavid du Colombier if(chatty9p)
1007dd7cddfSDavid du Colombier if(r->error)
1019a747e4fSDavid du Colombier fprint(2, "<-%d- %F: %s\n", s->infd, &r->ifcall, r->error);
1027dd7cddfSDavid du Colombier else
1039a747e4fSDavid du Colombier fprint(2, "<-%d- %F\n", s->infd, &r->ifcall);
1047dd7cddfSDavid du Colombier
1057dd7cddfSDavid du Colombier return r;
1067dd7cddfSDavid du Colombier }
1077dd7cddfSDavid du Colombier
1089a747e4fSDavid du Colombier static void
filewalk(Req * r)1099a747e4fSDavid du Colombier filewalk(Req *r)
1109a747e4fSDavid du Colombier {
1119a747e4fSDavid du Colombier int i;
1129a747e4fSDavid du Colombier File *f;
1137dd7cddfSDavid du Colombier
1149a747e4fSDavid du Colombier f = r->fid->file;
1159a747e4fSDavid du Colombier assert(f != nil);
1169a747e4fSDavid du Colombier
1179a747e4fSDavid du Colombier incref(f);
1189a747e4fSDavid du Colombier for(i=0; i<r->ifcall.nwname; i++)
1199a747e4fSDavid du Colombier if(f = walkfile(f, r->ifcall.wname[i]))
1209a747e4fSDavid du Colombier r->ofcall.wqid[i] = f->qid;
1219a747e4fSDavid du Colombier else
1229a747e4fSDavid du Colombier break;
1239a747e4fSDavid du Colombier
1249a747e4fSDavid du Colombier r->ofcall.nwqid = i;
1259a747e4fSDavid du Colombier if(f){
1269a747e4fSDavid du Colombier r->newfid->file = f;
1279a747e4fSDavid du Colombier r->newfid->qid = r->newfid->file->qid;
1289a747e4fSDavid du Colombier }
1299a747e4fSDavid du Colombier respond(r, nil);
1309a747e4fSDavid du Colombier }
1319a747e4fSDavid du Colombier
1327fd46167SDavid du Colombier void
walkandclone(Req * r,char * (* walk1)(Fid *,char *,void *),char * (* clone)(Fid *,Fid *,void *),void * arg)1337fd46167SDavid du Colombier walkandclone(Req *r, char *(*walk1)(Fid*, char*, void*), char *(*clone)(Fid*, Fid*, void*), void *arg)
1349a747e4fSDavid du Colombier {
1359a747e4fSDavid du Colombier int i;
1369a747e4fSDavid du Colombier char *e;
1379a747e4fSDavid du Colombier
1389a747e4fSDavid du Colombier if(r->fid == r->newfid && r->ifcall.nwname > 1){
1399a747e4fSDavid du Colombier respond(r, "lib9p: unused documented feature not implemented");
1409a747e4fSDavid du Colombier return;
1419a747e4fSDavid du Colombier }
1429a747e4fSDavid du Colombier
1439a747e4fSDavid du Colombier if(r->fid != r->newfid){
1449a747e4fSDavid du Colombier r->newfid->qid = r->fid->qid;
1457fd46167SDavid du Colombier if(clone && (e = clone(r->fid, r->newfid, arg))){
1469a747e4fSDavid du Colombier respond(r, e);
1479a747e4fSDavid du Colombier return;
1489a747e4fSDavid du Colombier }
1499a747e4fSDavid du Colombier }
1509a747e4fSDavid du Colombier
1519a747e4fSDavid du Colombier e = nil;
1529a747e4fSDavid du Colombier for(i=0; i<r->ifcall.nwname; i++){
1537fd46167SDavid du Colombier if(e = walk1(r->newfid, r->ifcall.wname[i], arg))
1549a747e4fSDavid du Colombier break;
1557fd46167SDavid du Colombier r->ofcall.wqid[i] = r->newfid->qid;
1569a747e4fSDavid du Colombier }
1579a747e4fSDavid du Colombier
1589a747e4fSDavid du Colombier r->ofcall.nwqid = i;
1599a747e4fSDavid du Colombier if(e && i==0)
1609a747e4fSDavid du Colombier respond(r, e);
1619a747e4fSDavid du Colombier else
1629a747e4fSDavid du Colombier respond(r, nil);
1639a747e4fSDavid du Colombier }
1647dd7cddfSDavid du Colombier
1657fd46167SDavid du Colombier static void
sversion(Srv *,Req * r)1667fd46167SDavid du Colombier sversion(Srv*, Req *r)
1677dd7cddfSDavid du Colombier {
1689a747e4fSDavid du Colombier if(strncmp(r->ifcall.version, "9P", 2) != 0){
1699a747e4fSDavid du Colombier r->ofcall.version = "unknown";
1709a747e4fSDavid du Colombier respond(r, nil);
1717fd46167SDavid du Colombier return;
1729a747e4fSDavid du Colombier }
1739a747e4fSDavid du Colombier
1749a747e4fSDavid du Colombier r->ofcall.version = "9P2000";
1759a747e4fSDavid du Colombier r->ofcall.msize = r->ifcall.msize;
1767dd7cddfSDavid du Colombier respond(r, nil);
1777fd46167SDavid du Colombier }
1787fd46167SDavid du Colombier static void
rversion(Req * r,char * error)1797fd46167SDavid du Colombier rversion(Req *r, char *error)
1807fd46167SDavid du Colombier {
1817fd46167SDavid du Colombier assert(error == nil);
1827fd46167SDavid du Colombier changemsize(r->srv, r->ofcall.msize);
1837fd46167SDavid du Colombier }
1847dd7cddfSDavid du Colombier
1857fd46167SDavid du Colombier static void
sauth(Srv * srv,Req * r)1867fd46167SDavid du Colombier sauth(Srv *srv, Req *r)
1877fd46167SDavid du Colombier {
1887fd46167SDavid du Colombier char e[ERRMAX];
1897fd46167SDavid du Colombier
1909a747e4fSDavid du Colombier if((r->afid = allocfid(srv->fpool, r->ifcall.afid)) == nil){
1919a747e4fSDavid du Colombier respond(r, Edupfid);
1927fd46167SDavid du Colombier return;
1939a747e4fSDavid du Colombier }
1949a747e4fSDavid du Colombier if(srv->auth)
1959a747e4fSDavid du Colombier srv->auth(r);
1969a747e4fSDavid du Colombier else{
1979a747e4fSDavid du Colombier snprint(e, sizeof e, "%s: authentication not required", argv0);
1989a747e4fSDavid du Colombier respond(r, e);
1999a747e4fSDavid du Colombier }
2007fd46167SDavid du Colombier }
2017fd46167SDavid du Colombier static void
rauth(Req * r,char * error)2027fd46167SDavid du Colombier rauth(Req *r, char *error)
2037fd46167SDavid du Colombier {
2047fd46167SDavid du Colombier if(error && r->afid)
2057fd46167SDavid du Colombier closefid(removefid(r->srv->fpool, r->afid->fid));
2067fd46167SDavid du Colombier }
2079a747e4fSDavid du Colombier
2087fd46167SDavid du Colombier static void
sattach(Srv * srv,Req * r)2097fd46167SDavid du Colombier sattach(Srv *srv, Req *r)
2107fd46167SDavid du Colombier {
2119a747e4fSDavid du Colombier if((r->fid = allocfid(srv->fpool, r->ifcall.fid)) == nil){
2129a747e4fSDavid du Colombier respond(r, Edupfid);
2137fd46167SDavid du Colombier return;
2149a747e4fSDavid du Colombier }
2159a747e4fSDavid du Colombier r->afid = nil;
2163ff48bf5SDavid du Colombier if(r->ifcall.afid != NOFID && (r->afid = lookupfid(srv->fpool, r->ifcall.afid)) == nil){
2179a747e4fSDavid du Colombier respond(r, Eunknownfid);
2187fd46167SDavid du Colombier return;
2199a747e4fSDavid du Colombier }
2209a747e4fSDavid du Colombier r->fid->uid = estrdup9p(r->ifcall.uname);
2219a747e4fSDavid du Colombier if(srv->tree){
2229a747e4fSDavid du Colombier r->fid->file = srv->tree->root;
22388110b43SDavid du Colombier incref(r->fid->file);
2249a747e4fSDavid du Colombier r->ofcall.qid = r->fid->file->qid;
2259a747e4fSDavid du Colombier r->fid->qid = r->ofcall.qid;
2269a747e4fSDavid du Colombier }
2279a747e4fSDavid du Colombier if(srv->attach)
2289a747e4fSDavid du Colombier srv->attach(r);
2297dd7cddfSDavid du Colombier else
2307dd7cddfSDavid du Colombier respond(r, nil);
2317fd46167SDavid du Colombier return;
2327fd46167SDavid du Colombier }
2337fd46167SDavid du Colombier static void
rattach(Req * r,char * error)2347fd46167SDavid du Colombier rattach(Req *r, char *error)
2357fd46167SDavid du Colombier {
2367fd46167SDavid du Colombier if(error && r->fid)
2377fd46167SDavid du Colombier closefid(removefid(r->srv->fpool, r->fid->fid));
2387fd46167SDavid du Colombier }
2397dd7cddfSDavid du Colombier
2407fd46167SDavid du Colombier static void
sflush(Srv * srv,Req * r)2417fd46167SDavid du Colombier sflush(Srv *srv, Req *r)
2427fd46167SDavid du Colombier {
2439a747e4fSDavid du Colombier r->oldreq = lookupreq(srv->rpool, r->ifcall.oldtag);
2449a747e4fSDavid du Colombier if(r->oldreq == nil || r->oldreq == r)
2459a747e4fSDavid du Colombier respond(r, nil);
2469a747e4fSDavid du Colombier else if(srv->flush)
2479a747e4fSDavid du Colombier srv->flush(r);
2487dd7cddfSDavid du Colombier else
2497fd46167SDavid du Colombier respond(r, nil);
2507fd46167SDavid du Colombier }
2517fd46167SDavid du Colombier static int
rflush(Req * r,char * error)2527fd46167SDavid du Colombier rflush(Req *r, char *error)
2537fd46167SDavid du Colombier {
2547fd46167SDavid du Colombier Req *or;
2557dd7cddfSDavid du Colombier
2567fd46167SDavid du Colombier assert(error == nil);
2577fd46167SDavid du Colombier or = r->oldreq;
2587fd46167SDavid du Colombier if(or){
2597fd46167SDavid du Colombier qlock(&or->lk);
2607fd46167SDavid du Colombier if(or->responded == 0){
2617fd46167SDavid du Colombier or->flush = erealloc9p(or->flush, (or->nflush+1)*sizeof(or->flush[0]));
2627fd46167SDavid du Colombier or->flush[or->nflush++] = r;
2637fd46167SDavid du Colombier qunlock(&or->lk);
2647fd46167SDavid du Colombier return -1; /* delay response until or is responded */
2657fd46167SDavid du Colombier }
2667fd46167SDavid du Colombier qunlock(&or->lk);
2677fd46167SDavid du Colombier closereq(or);
2687fd46167SDavid du Colombier }
2697fd46167SDavid du Colombier r->oldreq = nil;
2707fd46167SDavid du Colombier return 0;
2717fd46167SDavid du Colombier }
2727fd46167SDavid du Colombier
2737fd46167SDavid du Colombier static char*
oldwalk1(Fid * fid,char * name,void * arg)2747fd46167SDavid du Colombier oldwalk1(Fid *fid, char *name, void *arg)
2757fd46167SDavid du Colombier {
2767fd46167SDavid du Colombier char *e;
2777fd46167SDavid du Colombier Qid qid;
2787fd46167SDavid du Colombier Srv *srv;
2797fd46167SDavid du Colombier
2807fd46167SDavid du Colombier srv = arg;
2817fd46167SDavid du Colombier e = srv->walk1(fid, name, &qid);
2827fd46167SDavid du Colombier if(e)
2837fd46167SDavid du Colombier return e;
2842ebbfa15SDavid du Colombier fid->qid = qid;
2857fd46167SDavid du Colombier return nil;
2867fd46167SDavid du Colombier }
2877fd46167SDavid du Colombier
2887fd46167SDavid du Colombier static char*
oldclone(Fid * fid,Fid * newfid,void * arg)2897fd46167SDavid du Colombier oldclone(Fid *fid, Fid *newfid, void *arg)
2907fd46167SDavid du Colombier {
2917fd46167SDavid du Colombier Srv *srv;
2927fd46167SDavid du Colombier
2937fd46167SDavid du Colombier srv = arg;
2947fd46167SDavid du Colombier if(srv->clone == nil)
2957fd46167SDavid du Colombier return nil;
2967fd46167SDavid du Colombier return srv->clone(fid, newfid);
2977fd46167SDavid du Colombier }
2987fd46167SDavid du Colombier
2997fd46167SDavid du Colombier static void
swalk(Srv * srv,Req * r)3007fd46167SDavid du Colombier swalk(Srv *srv, Req *r)
3017fd46167SDavid du Colombier {
3029a747e4fSDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
3039a747e4fSDavid du Colombier respond(r, Eunknownfid);
3047fd46167SDavid du Colombier return;
3057dd7cddfSDavid du Colombier }
3069a747e4fSDavid du Colombier if(r->fid->omode != -1){
3079a747e4fSDavid du Colombier respond(r, "cannot clone open fid");
3087fd46167SDavid du Colombier return;
3099a747e4fSDavid du Colombier }
3109a747e4fSDavid du Colombier if(r->ifcall.nwname && !(r->fid->qid.type&QTDIR)){
3119a747e4fSDavid du Colombier respond(r, Ewalknodir);
3127fd46167SDavid du Colombier return;
3139a747e4fSDavid du Colombier }
3149a747e4fSDavid du Colombier if(r->ifcall.fid != r->ifcall.newfid){
3159a747e4fSDavid du Colombier if((r->newfid = allocfid(srv->fpool, r->ifcall.newfid)) == nil){
3169a747e4fSDavid du Colombier respond(r, Edupfid);
3177fd46167SDavid du Colombier return;
3189a747e4fSDavid du Colombier }
3199a747e4fSDavid du Colombier r->newfid->uid = estrdup9p(r->fid->uid);
3209a747e4fSDavid du Colombier }else{
3219a747e4fSDavid du Colombier incref(&r->fid->ref);
3229a747e4fSDavid du Colombier r->newfid = r->fid;
3239a747e4fSDavid du Colombier }
3249a747e4fSDavid du Colombier if(r->fid->file){
3259a747e4fSDavid du Colombier filewalk(r);
3269a747e4fSDavid du Colombier }else if(srv->walk1)
3277fd46167SDavid du Colombier walkandclone(r, oldwalk1, oldclone, srv);
3289a747e4fSDavid du Colombier else if(srv->walk)
3299a747e4fSDavid du Colombier srv->walk(r);
3309a747e4fSDavid du Colombier else
3319a747e4fSDavid du Colombier sysfatal("no walk function, no file trees");
3327fd46167SDavid du Colombier }
3337fd46167SDavid du Colombier static void
rwalk(Req * r,char * error)3347fd46167SDavid du Colombier rwalk(Req *r, char *error)
3357fd46167SDavid du Colombier {
3367fd46167SDavid du Colombier if(error || r->ofcall.nwqid < r->ifcall.nwname){
3377fd46167SDavid du Colombier if(r->ifcall.fid != r->ifcall.newfid && r->newfid)
3387fd46167SDavid du Colombier closefid(removefid(r->srv->fpool, r->newfid->fid));
3397fd46167SDavid du Colombier if (r->ofcall.nwqid==0){
3407fd46167SDavid du Colombier if(error==nil && r->ifcall.nwname!=0)
3417fd46167SDavid du Colombier r->error = Enotfound;
3427fd46167SDavid du Colombier }else
3437fd46167SDavid du Colombier r->error = nil; // No error on partial walks
3447fd46167SDavid du Colombier }else{
3457fd46167SDavid du Colombier if(r->ofcall.nwqid == 0){
3467fd46167SDavid du Colombier /* Just a clone */
3477fd46167SDavid du Colombier r->newfid->qid = r->fid->qid;
3487fd46167SDavid du Colombier }else{
3497fd46167SDavid du Colombier /* if file trees are in use, filewalk took care of the rest */
3507fd46167SDavid du Colombier r->newfid->qid = r->ofcall.wqid[r->ofcall.nwqid-1];
3517fd46167SDavid du Colombier }
3527fd46167SDavid du Colombier }
3537fd46167SDavid du Colombier }
3547dd7cddfSDavid du Colombier
3557fd46167SDavid du Colombier static void
sopen(Srv * srv,Req * r)3567fd46167SDavid du Colombier sopen(Srv *srv, Req *r)
3577fd46167SDavid du Colombier {
3587fd46167SDavid du Colombier int p;
3597fd46167SDavid du Colombier
3609a747e4fSDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
3619a747e4fSDavid du Colombier respond(r, Eunknownfid);
3627fd46167SDavid du Colombier return;
3639a747e4fSDavid du Colombier }
3647dd7cddfSDavid du Colombier if(r->fid->omode != -1){
3657dd7cddfSDavid du Colombier respond(r, Ebotch);
3667fd46167SDavid du Colombier return;
3677dd7cddfSDavid du Colombier }
3689a747e4fSDavid du Colombier if((r->fid->qid.type&QTDIR) && (r->ifcall.mode&~ORCLOSE) != OREAD){
3699a747e4fSDavid du Colombier respond(r, Eisdir);
3707fd46167SDavid du Colombier return;
3717dd7cddfSDavid du Colombier }
3729a747e4fSDavid du Colombier r->ofcall.qid = r->fid->qid;
3739a747e4fSDavid du Colombier switch(r->ifcall.mode&3){
3749a747e4fSDavid du Colombier default:
3759a747e4fSDavid du Colombier assert(0);
3769a747e4fSDavid du Colombier case OREAD:
3779a747e4fSDavid du Colombier p = AREAD;
3789a747e4fSDavid du Colombier break;
3799a747e4fSDavid du Colombier case OWRITE:
3809a747e4fSDavid du Colombier p = AWRITE;
3819a747e4fSDavid du Colombier break;
3829a747e4fSDavid du Colombier case ORDWR:
3839a747e4fSDavid du Colombier p = AREAD|AWRITE;
3849a747e4fSDavid du Colombier break;
3859a747e4fSDavid du Colombier case OEXEC:
3869a747e4fSDavid du Colombier p = AEXEC;
3879a747e4fSDavid du Colombier break;
3889a747e4fSDavid du Colombier }
3899a747e4fSDavid du Colombier if(r->ifcall.mode&OTRUNC)
3907dd7cddfSDavid du Colombier p |= AWRITE;
3919a747e4fSDavid du Colombier if((r->fid->qid.type&QTDIR) && p!=AREAD){
3929a747e4fSDavid du Colombier respond(r, Eperm);
3937fd46167SDavid du Colombier return;
3949a747e4fSDavid du Colombier }
3959a747e4fSDavid du Colombier if(r->fid->file){
3967dd7cddfSDavid du Colombier if(!hasperm(r->fid->file, r->fid->uid, p)){
3977dd7cddfSDavid du Colombier respond(r, Eperm);
3987fd46167SDavid du Colombier return;
3997dd7cddfSDavid du Colombier }
4009a747e4fSDavid du Colombier /* BUG RACE */
4019a747e4fSDavid du Colombier if((r->ifcall.mode&ORCLOSE)
4027dd7cddfSDavid du Colombier && !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){
4037dd7cddfSDavid du Colombier respond(r, Eperm);
4047fd46167SDavid du Colombier return;
4057dd7cddfSDavid du Colombier }
40680ee5cbfSDavid du Colombier r->ofcall.qid = r->fid->file->qid;
4079a747e4fSDavid du Colombier if((r->ofcall.qid.type&QTDIR)
4089a747e4fSDavid du Colombier && (r->fid->rdir = opendirfile(r->fid->file)) == nil){
4099a747e4fSDavid du Colombier respond(r, "opendirfile failed");
4107fd46167SDavid du Colombier return;
4119a747e4fSDavid du Colombier }
4127dd7cddfSDavid du Colombier }
4137dd7cddfSDavid du Colombier if(srv->open)
4149a747e4fSDavid du Colombier srv->open(r);
4157dd7cddfSDavid du Colombier else
4167dd7cddfSDavid du Colombier respond(r, nil);
4177fd46167SDavid du Colombier }
4187fd46167SDavid du Colombier static void
ropen(Req * r,char * error)4197fd46167SDavid du Colombier ropen(Req *r, char *error)
4207fd46167SDavid du Colombier {
4217fd46167SDavid du Colombier char errbuf[ERRMAX];
4227fd46167SDavid du Colombier if(error)
4237fd46167SDavid du Colombier return;
4247fd46167SDavid du Colombier if(chatty9p){
4257fd46167SDavid du Colombier snprint(errbuf, sizeof errbuf, "fid mode is 0x%ux\n", r->ifcall.mode);
4267fd46167SDavid du Colombier write(2, errbuf, strlen(errbuf));
4277fd46167SDavid du Colombier }
4287fd46167SDavid du Colombier r->fid->omode = r->ifcall.mode;
4297fd46167SDavid du Colombier r->fid->qid = r->ofcall.qid;
4307fd46167SDavid du Colombier if(r->ofcall.qid.type&QTDIR)
4317fd46167SDavid du Colombier r->fid->diroffset = 0;
4327fd46167SDavid du Colombier }
4337dd7cddfSDavid du Colombier
4347fd46167SDavid du Colombier static void
screate(Srv * srv,Req * r)4357fd46167SDavid du Colombier screate(Srv *srv, Req *r)
4367fd46167SDavid du Colombier {
4379a747e4fSDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil)
4389a747e4fSDavid du Colombier respond(r, Eunknownfid);
4399a747e4fSDavid du Colombier else if(r->fid->omode != -1)
4409a747e4fSDavid du Colombier respond(r, Ebotch);
4419a747e4fSDavid du Colombier else if(!(r->fid->qid.type&QTDIR))
4429a747e4fSDavid du Colombier respond(r, Ecreatenondir);
4437dd7cddfSDavid du Colombier else if(r->fid->file && !hasperm(r->fid->file, r->fid->uid, AWRITE))
4449a747e4fSDavid du Colombier respond(r, Eperm);
4459a747e4fSDavid du Colombier else if(srv->create)
4469a747e4fSDavid du Colombier srv->create(r);
4477dd7cddfSDavid du Colombier else
4489a747e4fSDavid du Colombier respond(r, Enocreate);
4497fd46167SDavid du Colombier }
4507fd46167SDavid du Colombier static void
rcreate(Req * r,char * error)4517fd46167SDavid du Colombier rcreate(Req *r, char *error)
4527fd46167SDavid du Colombier {
4537fd46167SDavid du Colombier if(error)
4547fd46167SDavid du Colombier return;
4557fd46167SDavid du Colombier r->fid->omode = r->ifcall.mode;
4567fd46167SDavid du Colombier r->fid->qid = r->ofcall.qid;
4577fd46167SDavid du Colombier }
4587dd7cddfSDavid du Colombier
4597fd46167SDavid du Colombier static void
sread(Srv * srv,Req * r)4607fd46167SDavid du Colombier sread(Srv *srv, Req *r)
4617fd46167SDavid du Colombier {
4627fd46167SDavid du Colombier int o;
4637fd46167SDavid du Colombier
4649a747e4fSDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
4659a747e4fSDavid du Colombier respond(r, Eunknownfid);
4667fd46167SDavid du Colombier return;
4677dd7cddfSDavid du Colombier }
468*22a127bbSDavid du Colombier if((int)r->ifcall.count < 0){
4699a747e4fSDavid du Colombier respond(r, Ebotch);
4707fd46167SDavid du Colombier return;
4719a747e4fSDavid du Colombier }
4729a747e4fSDavid du Colombier if(r->ifcall.offset < 0
4739a747e4fSDavid du Colombier || ((r->fid->qid.type&QTDIR) && r->ifcall.offset != 0 && r->ifcall.offset != r->fid->diroffset)){
4749a747e4fSDavid du Colombier respond(r, Ebadoffset);
4757fd46167SDavid du Colombier return;
4769a747e4fSDavid du Colombier }
4779a747e4fSDavid du Colombier
4789a747e4fSDavid du Colombier if(r->ifcall.count > srv->msize - IOHDRSZ)
4799a747e4fSDavid du Colombier r->ifcall.count = srv->msize - IOHDRSZ;
4807fd46167SDavid du Colombier r->rbuf = emalloc9p(r->ifcall.count);
4819a747e4fSDavid du Colombier r->ofcall.data = r->rbuf;
4829a747e4fSDavid du Colombier o = r->fid->omode & 3;
4839a747e4fSDavid du Colombier if(o != OREAD && o != ORDWR && o != OEXEC){
4849a747e4fSDavid du Colombier respond(r, Ebotch);
4857fd46167SDavid du Colombier return;
4869a747e4fSDavid du Colombier }
4879a747e4fSDavid du Colombier if((r->fid->qid.type&QTDIR) && r->fid->file){
4889a747e4fSDavid du Colombier r->ofcall.count = readdirfile(r->fid->rdir, r->rbuf, r->ifcall.count);
4899a747e4fSDavid du Colombier respond(r, nil);
4907fd46167SDavid du Colombier return;
4919a747e4fSDavid du Colombier }
4929a747e4fSDavid du Colombier if(srv->read)
4939a747e4fSDavid du Colombier srv->read(r);
4949a747e4fSDavid du Colombier else
4959a747e4fSDavid du Colombier respond(r, "no srv->read");
4967fd46167SDavid du Colombier }
4977fd46167SDavid du Colombier static void
rread(Req * r,char * error)4987fd46167SDavid du Colombier rread(Req *r, char *error)
4997fd46167SDavid du Colombier {
5007fd46167SDavid du Colombier if(error==nil && (r->fid->qid.type&QTDIR))
5017fd46167SDavid du Colombier r->fid->diroffset += r->ofcall.count;
5027fd46167SDavid du Colombier }
5037dd7cddfSDavid du Colombier
5047fd46167SDavid du Colombier static void
swrite(Srv * srv,Req * r)5057fd46167SDavid du Colombier swrite(Srv *srv, Req *r)
5067fd46167SDavid du Colombier {
5077fd46167SDavid du Colombier int o;
5087fd46167SDavid du Colombier char e[ERRMAX];
5097fd46167SDavid du Colombier
5109a747e4fSDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
5119a747e4fSDavid du Colombier respond(r, Eunknownfid);
5127fd46167SDavid du Colombier return;
5137dd7cddfSDavid du Colombier }
514*22a127bbSDavid du Colombier if((int)r->ifcall.count < 0){
5159a747e4fSDavid du Colombier respond(r, Ebotch);
5167fd46167SDavid du Colombier return;
5179a747e4fSDavid du Colombier }
5189a747e4fSDavid du Colombier if(r->ifcall.offset < 0){
5199a747e4fSDavid du Colombier respond(r, Ebotch);
5207fd46167SDavid du Colombier return;
5219a747e4fSDavid du Colombier }
5229a747e4fSDavid du Colombier if(r->ifcall.count > srv->msize - IOHDRSZ)
5239a747e4fSDavid du Colombier r->ifcall.count = srv->msize - IOHDRSZ;
5249a747e4fSDavid du Colombier o = r->fid->omode & 3;
5259a747e4fSDavid du Colombier if(o != OWRITE && o != ORDWR){
5269a747e4fSDavid du Colombier snprint(e, sizeof e, "write on fid with open mode 0x%ux", r->fid->omode);
5279a747e4fSDavid du Colombier respond(r, e);
5287fd46167SDavid du Colombier return;
5299a747e4fSDavid du Colombier }
5309a747e4fSDavid du Colombier if(srv->write)
5319a747e4fSDavid du Colombier srv->write(r);
5329a747e4fSDavid du Colombier else
5339a747e4fSDavid du Colombier respond(r, "no srv->write");
5347fd46167SDavid du Colombier }
5357fd46167SDavid du Colombier static void
rwrite(Req * r,char * error)5367fd46167SDavid du Colombier rwrite(Req *r, char *error)
5377fd46167SDavid du Colombier {
5387fd46167SDavid du Colombier if(error)
5397fd46167SDavid du Colombier return;
5407fd46167SDavid du Colombier if(r->fid->file)
5417fd46167SDavid du Colombier r->fid->file->qid.vers++;
5427fd46167SDavid du Colombier }
5437dd7cddfSDavid du Colombier
5447fd46167SDavid du Colombier static void
sclunk(Srv * srv,Req * r)5457fd46167SDavid du Colombier sclunk(Srv *srv, Req *r)
5467fd46167SDavid du Colombier {
5479a747e4fSDavid du Colombier if((r->fid = removefid(srv->fpool, r->ifcall.fid)) == nil)
5489a747e4fSDavid du Colombier respond(r, Eunknownfid);
5499a747e4fSDavid du Colombier else
5507dd7cddfSDavid du Colombier respond(r, nil);
5517fd46167SDavid du Colombier }
5527fd46167SDavid du Colombier static void
rclunk(Req *,char *)5537fd46167SDavid du Colombier rclunk(Req*, char*)
5547fd46167SDavid du Colombier {
5557fd46167SDavid du Colombier }
5567dd7cddfSDavid du Colombier
5577fd46167SDavid du Colombier static void
sremove(Srv * srv,Req * r)5587fd46167SDavid du Colombier sremove(Srv *srv, Req *r)
5597fd46167SDavid du Colombier {
5609a747e4fSDavid du Colombier if((r->fid = removefid(srv->fpool, r->ifcall.fid)) == nil){
5619a747e4fSDavid du Colombier respond(r, Eunknownfid);
5627fd46167SDavid du Colombier return;
5639a747e4fSDavid du Colombier }
5649a747e4fSDavid du Colombier /* BUG RACE */
5659a747e4fSDavid du Colombier if(r->fid->file && !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){
5667dd7cddfSDavid du Colombier respond(r, Eperm);
5677fd46167SDavid du Colombier return;
5687dd7cddfSDavid du Colombier }
5699a747e4fSDavid du Colombier if(srv->remove)
5709a747e4fSDavid du Colombier srv->remove(r);
5717dd7cddfSDavid du Colombier else
5729a747e4fSDavid du Colombier respond(r, r->fid->file ? nil : Enoremove);
5737fd46167SDavid du Colombier }
5747fd46167SDavid du Colombier static void
rremove(Req * r,char * error,char * errbuf)5757fd46167SDavid du Colombier rremove(Req *r, char *error, char *errbuf)
5767fd46167SDavid du Colombier {
5777fd46167SDavid du Colombier if(error)
5787fd46167SDavid du Colombier return;
5797fd46167SDavid du Colombier if(r->fid->file){
5807fd46167SDavid du Colombier if(removefile(r->fid->file) < 0){
5817fd46167SDavid du Colombier snprint(errbuf, ERRMAX, "remove %s: %r",
5827fd46167SDavid du Colombier r->fid->file->name);
5837fd46167SDavid du Colombier r->error = errbuf;
5847fd46167SDavid du Colombier }
5857fd46167SDavid du Colombier r->fid->file = nil;
5867fd46167SDavid du Colombier }
5877fd46167SDavid du Colombier }
5887dd7cddfSDavid du Colombier
5897fd46167SDavid du Colombier static void
sstat(Srv * srv,Req * r)5907fd46167SDavid du Colombier sstat(Srv *srv, Req *r)
5917fd46167SDavid du Colombier {
5929a747e4fSDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
5939a747e4fSDavid du Colombier respond(r, Eunknownfid);
5947fd46167SDavid du Colombier return;
5957dd7cddfSDavid du Colombier }
5969a747e4fSDavid du Colombier if(r->fid->file){
597*22a127bbSDavid du Colombier /* should we rlock the file? */
5989a747e4fSDavid du Colombier r->d = r->fid->file->Dir;
5999a747e4fSDavid du Colombier if(r->d.name)
6009a747e4fSDavid du Colombier r->d.name = estrdup9p(r->d.name);
6019a747e4fSDavid du Colombier if(r->d.uid)
6029a747e4fSDavid du Colombier r->d.uid = estrdup9p(r->d.uid);
6039a747e4fSDavid du Colombier if(r->d.gid)
6049a747e4fSDavid du Colombier r->d.gid = estrdup9p(r->d.gid);
6059a747e4fSDavid du Colombier if(r->d.muid)
6069a747e4fSDavid du Colombier r->d.muid = estrdup9p(r->d.muid);
6079a747e4fSDavid du Colombier }
6087dd7cddfSDavid du Colombier if(srv->stat)
6099a747e4fSDavid du Colombier srv->stat(r);
6109a747e4fSDavid du Colombier else if(r->fid->file)
6117dd7cddfSDavid du Colombier respond(r, nil);
6129a747e4fSDavid du Colombier else
6139a747e4fSDavid du Colombier respond(r, Enostat);
6147fd46167SDavid du Colombier }
6157fd46167SDavid du Colombier static void
rstat(Req * r,char * error)6167fd46167SDavid du Colombier rstat(Req *r, char *error)
6177fd46167SDavid du Colombier {
6187fd46167SDavid du Colombier int n;
6197fd46167SDavid du Colombier uchar *statbuf;
6207fd46167SDavid du Colombier uchar tmp[BIT16SZ];
6217dd7cddfSDavid du Colombier
6227fd46167SDavid du Colombier if(error)
6237fd46167SDavid du Colombier return;
6247fd46167SDavid du Colombier if(convD2M(&r->d, tmp, BIT16SZ) != BIT16SZ){
6257fd46167SDavid du Colombier r->error = "convD2M(_,_,BIT16SZ) did not return BIT16SZ";
6267fd46167SDavid du Colombier return;
6277fd46167SDavid du Colombier }
6287fd46167SDavid du Colombier n = GBIT16(tmp)+BIT16SZ;
6297fd46167SDavid du Colombier statbuf = emalloc9p(n);
6307fd46167SDavid du Colombier if(statbuf == nil){
6317fd46167SDavid du Colombier r->error = "out of memory";
6327fd46167SDavid du Colombier return;
6337fd46167SDavid du Colombier }
6347fd46167SDavid du Colombier r->ofcall.nstat = convD2M(&r->d, statbuf, n);
6357fd46167SDavid du Colombier r->ofcall.stat = statbuf; /* freed in closereq */
636*22a127bbSDavid du Colombier if(r->ofcall.nstat <= BIT16SZ){
6377fd46167SDavid du Colombier r->error = "convD2M fails";
6387fd46167SDavid du Colombier free(statbuf);
6397fd46167SDavid du Colombier return;
6407fd46167SDavid du Colombier }
6417fd46167SDavid du Colombier }
6427fd46167SDavid du Colombier
6437fd46167SDavid du Colombier static void
swstat(Srv * srv,Req * r)6447fd46167SDavid du Colombier swstat(Srv *srv, Req *r)
6457fd46167SDavid du Colombier {
6467fd46167SDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
6479a747e4fSDavid du Colombier respond(r, Eunknownfid);
6487fd46167SDavid du Colombier return;
6497fd46167SDavid du Colombier }
6507fd46167SDavid du Colombier if(srv->wstat == nil){
6519a747e4fSDavid du Colombier respond(r, Enowstat);
6527fd46167SDavid du Colombier return;
6537fd46167SDavid du Colombier }
6547fd46167SDavid du Colombier if(convM2D(r->ifcall.stat, r->ifcall.nstat, &r->d, (char*)r->ifcall.stat) != r->ifcall.nstat){
6557fd46167SDavid du Colombier respond(r, Ebaddir);
6567fd46167SDavid du Colombier return;
6577fd46167SDavid du Colombier }
6587fd46167SDavid du Colombier if((ushort)~r->d.type){
6597fd46167SDavid du Colombier respond(r, "wstat -- attempt to change type");
6607fd46167SDavid du Colombier return;
6617fd46167SDavid du Colombier }
6627fd46167SDavid du Colombier if((uint)~r->d.dev){
6637fd46167SDavid du Colombier respond(r, "wstat -- attempt to change dev");
6647fd46167SDavid du Colombier return;
6657fd46167SDavid du Colombier }
6667fd46167SDavid du Colombier if((uchar)~r->d.qid.type || (ulong)~r->d.qid.vers || (uvlong)~r->d.qid.path){
6677fd46167SDavid du Colombier respond(r, "wstat -- attempt to change qid");
6687fd46167SDavid du Colombier return;
6697fd46167SDavid du Colombier }
6707fd46167SDavid du Colombier if(r->d.muid && r->d.muid[0]){
6717fd46167SDavid du Colombier respond(r, "wstat -- attempt to change muid");
6727fd46167SDavid du Colombier return;
6737fd46167SDavid du Colombier }
67425ea35e3SDavid du Colombier if((ulong)~r->d.mode && ((r->d.mode&DMDIR)>>24) != (r->fid->qid.type&QTDIR)){
6757fd46167SDavid du Colombier respond(r, "wstat -- attempt to change DMDIR bit");
6767fd46167SDavid du Colombier return;
6777fd46167SDavid du Colombier }
6787fd46167SDavid du Colombier srv->wstat(r);
6797fd46167SDavid du Colombier }
6807fd46167SDavid du Colombier static void
rwstat(Req *,char *)6817fd46167SDavid du Colombier rwstat(Req*, char*)
6827fd46167SDavid du Colombier {
6837fd46167SDavid du Colombier }
6847fd46167SDavid du Colombier
6857fd46167SDavid du Colombier void
srv(Srv * srv)6867fd46167SDavid du Colombier srv(Srv *srv)
6877fd46167SDavid du Colombier {
6887fd46167SDavid du Colombier Req *r;
6897fd46167SDavid du Colombier
6907fd46167SDavid du Colombier fmtinstall('D', dirfmt);
6917fd46167SDavid du Colombier fmtinstall('F', fcallfmt);
6927fd46167SDavid du Colombier
6937fd46167SDavid du Colombier if(srv->fpool == nil)
6947fd46167SDavid du Colombier srv->fpool = allocfidpool(srv->destroyfid);
6957fd46167SDavid du Colombier if(srv->rpool == nil)
6967fd46167SDavid du Colombier srv->rpool = allocreqpool(srv->destroyreq);
6977fd46167SDavid du Colombier if(srv->msize == 0)
6987fd46167SDavid du Colombier srv->msize = 8192+IOHDRSZ;
6997fd46167SDavid du Colombier
7007fd46167SDavid du Colombier changemsize(srv, srv->msize);
7017fd46167SDavid du Colombier
7027fd46167SDavid du Colombier srv->fpool->srv = srv;
7037fd46167SDavid du Colombier srv->rpool->srv = srv;
7047fd46167SDavid du Colombier
7057fd46167SDavid du Colombier while(r = getreq(srv)){
7067fd46167SDavid du Colombier if(r->error){
7077fd46167SDavid du Colombier respond(r, r->error);
7087fd46167SDavid du Colombier continue;
7097fd46167SDavid du Colombier }
7107fd46167SDavid du Colombier switch(r->ifcall.type){
7117fd46167SDavid du Colombier default:
7127fd46167SDavid du Colombier respond(r, "unknown message");
7137dd7cddfSDavid du Colombier break;
7147fd46167SDavid du Colombier case Tversion: sversion(srv, r); break;
7157fd46167SDavid du Colombier case Tauth: sauth(srv, r); break;
7167fd46167SDavid du Colombier case Tattach: sattach(srv, r); break;
7177fd46167SDavid du Colombier case Tflush: sflush(srv, r); break;
7187fd46167SDavid du Colombier case Twalk: swalk(srv, r); break;
7197fd46167SDavid du Colombier case Topen: sopen(srv, r); break;
7207fd46167SDavid du Colombier case Tcreate: screate(srv, r); break;
7217fd46167SDavid du Colombier case Tread: sread(srv, r); break;
7227fd46167SDavid du Colombier case Twrite: swrite(srv, r); break;
7237fd46167SDavid du Colombier case Tclunk: sclunk(srv, r); break;
7247fd46167SDavid du Colombier case Tremove: sremove(srv, r); break;
7257fd46167SDavid du Colombier case Tstat: sstat(srv, r); break;
7267fd46167SDavid du Colombier case Twstat: swstat(srv, r); break;
7277dd7cddfSDavid du Colombier }
7287dd7cddfSDavid du Colombier }
7293ff48bf5SDavid du Colombier
730a21ce2d6SDavid du Colombier free(srv->rbuf);
731a21ce2d6SDavid du Colombier srv->rbuf = nil;
732a21ce2d6SDavid du Colombier free(srv->wbuf);
733a21ce2d6SDavid du Colombier srv->wbuf = nil;
734a21ce2d6SDavid du Colombier srv->msize = 0;
735a21ce2d6SDavid du Colombier freefidpool(srv->fpool);
736a21ce2d6SDavid du Colombier srv->fpool = nil;
737a21ce2d6SDavid du Colombier freereqpool(srv->rpool);
738a21ce2d6SDavid du Colombier srv->rpool = nil;
739a21ce2d6SDavid du Colombier
7403ff48bf5SDavid du Colombier if(srv->end)
7413ff48bf5SDavid du Colombier srv->end(srv);
7427dd7cddfSDavid du Colombier }
7437dd7cddfSDavid du Colombier
7447dd7cddfSDavid du Colombier void
respond(Req * r,char * error)7457dd7cddfSDavid du Colombier respond(Req *r, char *error)
7467dd7cddfSDavid du Colombier {
7477fd46167SDavid du Colombier int i, m, n;
7489a747e4fSDavid du Colombier char errbuf[ERRMAX];
7497dd7cddfSDavid du Colombier Srv *srv;
7507dd7cddfSDavid du Colombier
7519a747e4fSDavid du Colombier srv = r->srv;
7529a747e4fSDavid du Colombier assert(srv != nil);
7539a747e4fSDavid du Colombier
7547dd7cddfSDavid du Colombier assert(r->responded == 0);
7557fd46167SDavid du Colombier r->error = error;
7567dd7cddfSDavid du Colombier
7579a747e4fSDavid du Colombier switch(r->ifcall.type){
7587dd7cddfSDavid du Colombier default:
7599a747e4fSDavid du Colombier assert(0);
7607fd46167SDavid du Colombier /*
7617fd46167SDavid du Colombier * Flush is special. If the handler says so, we return
7627fd46167SDavid du Colombier * without further processing. Respond will be called
7637fd46167SDavid du Colombier * again once it is safe.
7647fd46167SDavid du Colombier */
7659a747e4fSDavid du Colombier case Tflush:
7667fd46167SDavid du Colombier if(rflush(r, error)<0)
7677fd46167SDavid du Colombier return;
7687dd7cddfSDavid du Colombier break;
7697fd46167SDavid du Colombier case Tversion: rversion(r, error); break;
7707fd46167SDavid du Colombier case Tauth: rauth(r, error); break;
7717fd46167SDavid du Colombier case Tattach: rattach(r, error); break;
7727fd46167SDavid du Colombier case Twalk: rwalk(r, error); break;
7737fd46167SDavid du Colombier case Topen: ropen(r, error); break;
7747fd46167SDavid du Colombier case Tcreate: rcreate(r, error); break;
7757fd46167SDavid du Colombier case Tread: rread(r, error); break;
7767fd46167SDavid du Colombier case Twrite: rwrite(r, error); break;
7777fd46167SDavid du Colombier case Tclunk: rclunk(r, error); break;
7787fd46167SDavid du Colombier case Tremove: rremove(r, error, errbuf); break;
7797fd46167SDavid du Colombier case Tstat: rstat(r, error); break;
7807fd46167SDavid du Colombier case Twstat: rwstat(r, error); break;
7817dd7cddfSDavid du Colombier }
7827dd7cddfSDavid du Colombier
7839a747e4fSDavid du Colombier r->ofcall.tag = r->ifcall.tag;
7849a747e4fSDavid du Colombier r->ofcall.type = r->ifcall.type+1;
7857fd46167SDavid du Colombier if(r->error)
7867fd46167SDavid du Colombier setfcallerror(&r->ofcall, r->error);
7877dd7cddfSDavid du Colombier
7889a747e4fSDavid du Colombier if(chatty9p)
7899a747e4fSDavid du Colombier fprint(2, "-%d-> %F\n", srv->outfd, &r->ofcall);
7907dd7cddfSDavid du Colombier
7919a747e4fSDavid du Colombier qlock(&srv->wlock);
7929a747e4fSDavid du Colombier n = convS2M(&r->ofcall, srv->wbuf, srv->msize);
7939a747e4fSDavid du Colombier if(n <= 0){
7949a747e4fSDavid du Colombier fprint(2, "n = %d %F\n", n, &r->ofcall);
7959a747e4fSDavid du Colombier abort();
7969a747e4fSDavid du Colombier }
7979a747e4fSDavid du Colombier assert(n > 2);
7987fd46167SDavid du Colombier if(r->pool) /* not a fake */
7999a747e4fSDavid du Colombier closereq(removereq(r->pool, r->ifcall.tag));
8005d459b5aSDavid du Colombier m = write(srv->outfd, srv->wbuf, n);
8015d459b5aSDavid du Colombier if(m != n)
8025d459b5aSDavid du Colombier sysfatal("lib9p srv: write %d returned %d on fd %d: %r", n, m, srv->outfd);
8035d459b5aSDavid du Colombier qunlock(&srv->wlock);
8045d459b5aSDavid du Colombier
8057fd46167SDavid du Colombier qlock(&r->lk); /* no one will add flushes now */
8067fd46167SDavid du Colombier r->responded = 1;
8077fd46167SDavid du Colombier qunlock(&r->lk);
8087fd46167SDavid du Colombier
8097fd46167SDavid du Colombier for(i=0; i<r->nflush; i++)
8107fd46167SDavid du Colombier respond(r->flush[i], nil);
8117fd46167SDavid du Colombier free(r->flush);
8129c06fe1dSDavid du Colombier r->flush = nil;
8139c06fe1dSDavid du Colombier r->nflush = 0;
8147fd46167SDavid du Colombier
8157fd46167SDavid du Colombier if(r->pool)
8167fd46167SDavid du Colombier closereq(r);
8177fd46167SDavid du Colombier else
8187fd46167SDavid du Colombier free(r);
8197dd7cddfSDavid du Colombier }
8207dd7cddfSDavid du Colombier
821*22a127bbSDavid du Colombier void
responderror(Req * r)822*22a127bbSDavid du Colombier responderror(Req *r)
823*22a127bbSDavid du Colombier {
824*22a127bbSDavid du Colombier char errbuf[ERRMAX];
825*22a127bbSDavid du Colombier
826*22a127bbSDavid du Colombier rerrstr(errbuf, sizeof errbuf);
827*22a127bbSDavid du Colombier respond(r, errbuf);
828*22a127bbSDavid du Colombier }
829*22a127bbSDavid du Colombier
8309a747e4fSDavid du Colombier int
postfd(char * name,int pfd)8319a747e4fSDavid du Colombier postfd(char *name, int pfd)
8327dd7cddfSDavid du Colombier {
8337dd7cddfSDavid du Colombier int fd;
8349a747e4fSDavid du Colombier char buf[80];
8357dd7cddfSDavid du Colombier
8367dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "/srv/%s", name);
8379a747e4fSDavid du Colombier if(chatty9p)
8389a747e4fSDavid du Colombier fprint(2, "postfd %s\n", buf);
8399a747e4fSDavid du Colombier fd = create(buf, OWRITE|ORCLOSE|OCEXEC, 0600);
8409a747e4fSDavid du Colombier if(fd < 0){
8419a747e4fSDavid du Colombier if(chatty9p)
8429a747e4fSDavid du Colombier fprint(2, "create fails: %r\n");
8439a747e4fSDavid du Colombier return -1;
8447dd7cddfSDavid du Colombier }
8459a747e4fSDavid du Colombier if(fprint(fd, "%d", pfd) < 0){
8469a747e4fSDavid du Colombier if(chatty9p)
8479a747e4fSDavid du Colombier fprint(2, "write fails: %r\n");
8489a747e4fSDavid du Colombier close(fd);
8499a747e4fSDavid du Colombier return -1;
8507dd7cddfSDavid du Colombier }
8519a747e4fSDavid du Colombier if(chatty9p)
8529a747e4fSDavid du Colombier fprint(2, "postfd successful\n");
8539a747e4fSDavid du Colombier return 0;
8547dd7cddfSDavid du Colombier }
8557dd7cddfSDavid du Colombier
856