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 89a747e4fSDavid du Colombier static char Ebadattach[] = "unknown specifier in attach"; 99a747e4fSDavid du Colombier static char Ebadoffset[] = "bad offset"; 109a747e4fSDavid du Colombier static char Ebadcount[] = "bad count"; 119a747e4fSDavid du Colombier static char Ebotch[] = "9P protocol botch"; 129a747e4fSDavid du Colombier static char Ecreatenondir[] = "create in non-directory"; 139a747e4fSDavid du Colombier static char Edupfid[] = "duplicate fid"; 149a747e4fSDavid du Colombier static char Eduptag[] = "duplicate tag"; 159a747e4fSDavid du Colombier static char Eisdir[] = "is a directory"; 169a747e4fSDavid du Colombier static char Enocreate[] = "create prohibited"; 179a747e4fSDavid du Colombier static char Enomem[] = "out of memory"; 189a747e4fSDavid du Colombier static char Enoremove[] = "remove prohibited"; 199a747e4fSDavid du Colombier static char Enostat[] = "stat prohibited"; 209a747e4fSDavid du Colombier static char Enotfound[] = "file not found"; 217dd7cddfSDavid du Colombier static char Enowrite[] = "write prohibited"; 227dd7cddfSDavid du Colombier static char Enowstat[] = "wstat prohibited"; 239a747e4fSDavid du Colombier static char Eperm[] = "permission denied"; 249a747e4fSDavid du Colombier static char Eunknownfid[] = "unknown fid"; 259a747e4fSDavid du Colombier static char Ebaddir[] = "bad directory in wstat"; 269a747e4fSDavid du Colombier static char Ewalknodir[] = "walk in non-directory"; 277dd7cddfSDavid du Colombier 287dd7cddfSDavid du Colombier static void 297dd7cddfSDavid du Colombier setfcallerror(Fcall *f, char *err) 307dd7cddfSDavid du Colombier { 319a747e4fSDavid du Colombier f->ename = err; 327dd7cddfSDavid du Colombier f->type = Rerror; 337dd7cddfSDavid du Colombier } 347dd7cddfSDavid du Colombier 357dd7cddfSDavid du Colombier static void 369a747e4fSDavid du Colombier changemsize(Srv *srv, int msize) 377dd7cddfSDavid du Colombier { 389a747e4fSDavid du Colombier if(srv->rbuf && srv->wbuf && srv->msize == msize) 399a747e4fSDavid du Colombier return; 409a747e4fSDavid du Colombier qlock(&srv->rlock); 419a747e4fSDavid du Colombier qlock(&srv->wlock); 429a747e4fSDavid du Colombier srv->msize = msize; 439a747e4fSDavid du Colombier free(srv->rbuf); 449a747e4fSDavid du Colombier free(srv->wbuf); 459a747e4fSDavid du Colombier srv->rbuf = emalloc9p(msize); 469a747e4fSDavid du Colombier srv->wbuf = emalloc9p(msize); 479a747e4fSDavid du Colombier qunlock(&srv->rlock); 489a747e4fSDavid du Colombier qunlock(&srv->wlock); 497dd7cddfSDavid du Colombier } 507dd7cddfSDavid du Colombier 519a747e4fSDavid du Colombier static Req* 529a747e4fSDavid du Colombier getreq(Srv *s) 537dd7cddfSDavid du Colombier { 547dd7cddfSDavid du Colombier long n; 559a747e4fSDavid du Colombier uchar *buf; 567dd7cddfSDavid du Colombier Fcall f; 577dd7cddfSDavid du Colombier Req *r; 587dd7cddfSDavid du Colombier 599a747e4fSDavid du Colombier qlock(&s->rlock); 609a747e4fSDavid du Colombier if((n = read9pmsg(s->infd, s->rbuf, s->msize)) <= 0){ 619a747e4fSDavid du Colombier qunlock(&s->rlock); 627dd7cddfSDavid du Colombier return nil; 639a747e4fSDavid du Colombier } 647dd7cddfSDavid du Colombier 659a747e4fSDavid du Colombier buf = emalloc9p(n); 669a747e4fSDavid du Colombier memmove(buf, s->rbuf, n); 679a747e4fSDavid du Colombier qunlock(&s->rlock); 689a747e4fSDavid du Colombier 699a747e4fSDavid du Colombier if(convM2S(buf, n, &f) != n){ 707dd7cddfSDavid du Colombier free(buf); 717dd7cddfSDavid du Colombier return nil; 727dd7cddfSDavid du Colombier } 739a747e4fSDavid du Colombier 749a747e4fSDavid du Colombier if((r=allocreq(s->rpool, f.tag)) == nil){ /* duplicate tag: cons up a fake Req */ 759a747e4fSDavid du Colombier r = emalloc9p(sizeof *r); 767dd7cddfSDavid du Colombier incref(&r->ref); 777dd7cddfSDavid du Colombier r->tag = f.tag; 789a747e4fSDavid du Colombier r->ifcall = f; 797dd7cddfSDavid du Colombier r->error = Eduptag; 807dd7cddfSDavid du Colombier r->buf = buf; 817dd7cddfSDavid du Colombier r->responded = 0; 829a747e4fSDavid du Colombier r->type = 0; 839a747e4fSDavid du Colombier r->srv = s; 849a747e4fSDavid du Colombier r->pool = nil; 859a747e4fSDavid du Colombier if(chatty9p) 869a747e4fSDavid du Colombier fprint(2, "<-%d- %F: dup tag\n", s->infd, &f); 877dd7cddfSDavid du Colombier return r; 887dd7cddfSDavid du Colombier } 897dd7cddfSDavid du Colombier 909a747e4fSDavid du Colombier r->srv = s; 917dd7cddfSDavid du Colombier r->responded = 0; 927dd7cddfSDavid du Colombier r->buf = buf; 939a747e4fSDavid du Colombier r->ifcall = f; 949a747e4fSDavid du Colombier memset(&r->ofcall, 0, sizeof r->ofcall); 959a747e4fSDavid du Colombier r->type = r->ifcall.type; 967dd7cddfSDavid du Colombier 979a747e4fSDavid du Colombier if(chatty9p) 987dd7cddfSDavid du Colombier if(r->error) 999a747e4fSDavid du Colombier fprint(2, "<-%d- %F: %s\n", s->infd, &r->ifcall, r->error); 1007dd7cddfSDavid du Colombier else 1019a747e4fSDavid du Colombier fprint(2, "<-%d- %F\n", s->infd, &r->ifcall); 1027dd7cddfSDavid du Colombier 1037dd7cddfSDavid du Colombier return r; 1047dd7cddfSDavid du Colombier } 1057dd7cddfSDavid du Colombier 1069a747e4fSDavid du Colombier static void 1079a747e4fSDavid du Colombier filewalk(Req *r) 1089a747e4fSDavid du Colombier { 1099a747e4fSDavid du Colombier int i; 1109a747e4fSDavid du Colombier File *f; 1117dd7cddfSDavid du Colombier 1129a747e4fSDavid du Colombier f = r->fid->file; 1139a747e4fSDavid du Colombier assert(f != nil); 1149a747e4fSDavid du Colombier 1159a747e4fSDavid du Colombier incref(f); 1169a747e4fSDavid du Colombier for(i=0; i<r->ifcall.nwname; i++) 1179a747e4fSDavid du Colombier if(f = walkfile(f, r->ifcall.wname[i])) 1189a747e4fSDavid du Colombier r->ofcall.wqid[i] = f->qid; 1199a747e4fSDavid du Colombier else 1209a747e4fSDavid du Colombier break; 1219a747e4fSDavid du Colombier 1229a747e4fSDavid du Colombier r->ofcall.nwqid = i; 1239a747e4fSDavid du Colombier if(f){ 1249a747e4fSDavid du Colombier r->newfid->file = f; 1259a747e4fSDavid du Colombier r->newfid->qid = r->newfid->file->qid; 1269a747e4fSDavid du Colombier } 1279a747e4fSDavid du Colombier respond(r, nil); 1289a747e4fSDavid du Colombier } 1299a747e4fSDavid du Colombier 1307fd46167SDavid du Colombier void 1317fd46167SDavid du Colombier walkandclone(Req *r, char *(*walk1)(Fid*, char*, void*), char *(*clone)(Fid*, Fid*, void*), void *arg) 1329a747e4fSDavid du Colombier { 1339a747e4fSDavid du Colombier int i; 1349a747e4fSDavid du Colombier char *e; 1359a747e4fSDavid du Colombier 1369a747e4fSDavid du Colombier if(r->fid == r->newfid && r->ifcall.nwname > 1){ 1379a747e4fSDavid du Colombier respond(r, "lib9p: unused documented feature not implemented"); 1389a747e4fSDavid du Colombier return; 1399a747e4fSDavid du Colombier } 1409a747e4fSDavid du Colombier 1419a747e4fSDavid du Colombier if(r->fid != r->newfid){ 1429a747e4fSDavid du Colombier r->newfid->qid = r->fid->qid; 1437fd46167SDavid du Colombier if(clone && (e = clone(r->fid, r->newfid, arg))){ 1449a747e4fSDavid du Colombier respond(r, e); 1459a747e4fSDavid du Colombier return; 1469a747e4fSDavid du Colombier } 1479a747e4fSDavid du Colombier } 1489a747e4fSDavid du Colombier 1499a747e4fSDavid du Colombier e = nil; 1509a747e4fSDavid du Colombier for(i=0; i<r->ifcall.nwname; i++){ 1517fd46167SDavid du Colombier if(e = walk1(r->newfid, r->ifcall.wname[i], arg)) 1529a747e4fSDavid du Colombier break; 1537fd46167SDavid du Colombier r->ofcall.wqid[i] = r->newfid->qid; 1549a747e4fSDavid du Colombier } 1559a747e4fSDavid du Colombier 1569a747e4fSDavid du Colombier r->ofcall.nwqid = i; 1579a747e4fSDavid du Colombier if(e && i==0) 1589a747e4fSDavid du Colombier respond(r, e); 1599a747e4fSDavid du Colombier else 1609a747e4fSDavid du Colombier respond(r, nil); 1619a747e4fSDavid du Colombier } 1627dd7cddfSDavid du Colombier 1637fd46167SDavid du Colombier static void 1647fd46167SDavid du Colombier sversion(Srv*, Req *r) 1657dd7cddfSDavid du Colombier { 1669a747e4fSDavid du Colombier if(strncmp(r->ifcall.version, "9P", 2) != 0){ 1679a747e4fSDavid du Colombier r->ofcall.version = "unknown"; 1689a747e4fSDavid du Colombier respond(r, nil); 1697fd46167SDavid du Colombier return; 1709a747e4fSDavid du Colombier } 1719a747e4fSDavid du Colombier 1729a747e4fSDavid du Colombier r->ofcall.version = "9P2000"; 1739a747e4fSDavid du Colombier r->ofcall.msize = r->ifcall.msize; 1747dd7cddfSDavid du Colombier respond(r, nil); 1757fd46167SDavid du Colombier } 1767fd46167SDavid du Colombier static void 1777fd46167SDavid du Colombier rversion(Req *r, char *error) 1787fd46167SDavid du Colombier { 1797fd46167SDavid du Colombier assert(error == nil); 1807fd46167SDavid du Colombier changemsize(r->srv, r->ofcall.msize); 1817fd46167SDavid du Colombier } 1827dd7cddfSDavid du Colombier 1837fd46167SDavid du Colombier static void 1847fd46167SDavid du Colombier sauth(Srv *srv, Req *r) 1857fd46167SDavid du Colombier { 1867fd46167SDavid du Colombier char e[ERRMAX]; 1877fd46167SDavid du Colombier 1889a747e4fSDavid du Colombier if((r->afid = allocfid(srv->fpool, r->ifcall.afid)) == nil){ 1899a747e4fSDavid du Colombier respond(r, Edupfid); 1907fd46167SDavid du Colombier return; 1919a747e4fSDavid du Colombier } 1929a747e4fSDavid du Colombier if(srv->auth) 1939a747e4fSDavid du Colombier srv->auth(r); 1949a747e4fSDavid du Colombier else{ 1959a747e4fSDavid du Colombier snprint(e, sizeof e, "%s: authentication not required", argv0); 1969a747e4fSDavid du Colombier respond(r, e); 1979a747e4fSDavid du Colombier } 1987fd46167SDavid du Colombier } 1997fd46167SDavid du Colombier static void 2007fd46167SDavid du Colombier rauth(Req *r, char *error) 2017fd46167SDavid du Colombier { 2027fd46167SDavid du Colombier if(error && r->afid) 2037fd46167SDavid du Colombier closefid(removefid(r->srv->fpool, r->afid->fid)); 2047fd46167SDavid du Colombier } 2059a747e4fSDavid du Colombier 2067fd46167SDavid du Colombier static void 2077fd46167SDavid du Colombier sattach(Srv *srv, Req *r) 2087fd46167SDavid du Colombier { 2099a747e4fSDavid du Colombier if((r->fid = allocfid(srv->fpool, r->ifcall.fid)) == nil){ 2109a747e4fSDavid du Colombier respond(r, Edupfid); 2117fd46167SDavid du Colombier return; 2129a747e4fSDavid du Colombier } 2139a747e4fSDavid du Colombier r->afid = nil; 2143ff48bf5SDavid du Colombier if(r->ifcall.afid != NOFID && (r->afid = lookupfid(srv->fpool, r->ifcall.afid)) == nil){ 2159a747e4fSDavid du Colombier respond(r, Eunknownfid); 2167fd46167SDavid du Colombier return; 2179a747e4fSDavid du Colombier } 2189a747e4fSDavid du Colombier r->fid->uid = estrdup9p(r->ifcall.uname); 2199a747e4fSDavid du Colombier if(srv->tree){ 2209a747e4fSDavid du Colombier r->fid->file = srv->tree->root; 2219a747e4fSDavid du Colombier /* BUG? incref(r->fid->file) ??? */ 2229a747e4fSDavid du Colombier r->ofcall.qid = r->fid->file->qid; 2239a747e4fSDavid du Colombier r->fid->qid = r->ofcall.qid; 2249a747e4fSDavid du Colombier } 2259a747e4fSDavid du Colombier if(srv->attach) 2269a747e4fSDavid du Colombier srv->attach(r); 2277dd7cddfSDavid du Colombier else 2287dd7cddfSDavid du Colombier respond(r, nil); 2297fd46167SDavid du Colombier return; 2307fd46167SDavid du Colombier } 2317fd46167SDavid du Colombier static void 2327fd46167SDavid du Colombier rattach(Req *r, char *error) 2337fd46167SDavid du Colombier { 2347fd46167SDavid du Colombier if(error && r->fid) 2357fd46167SDavid du Colombier closefid(removefid(r->srv->fpool, r->fid->fid)); 2367fd46167SDavid du Colombier } 2377dd7cddfSDavid du Colombier 2387fd46167SDavid du Colombier static void 2397fd46167SDavid du Colombier sflush(Srv *srv, Req *r) 2407fd46167SDavid du Colombier { 2419a747e4fSDavid du Colombier r->oldreq = lookupreq(srv->rpool, r->ifcall.oldtag); 2429a747e4fSDavid du Colombier if(r->oldreq == nil || r->oldreq == r) 2439a747e4fSDavid du Colombier respond(r, nil); 2449a747e4fSDavid du Colombier else if(srv->flush) 2459a747e4fSDavid du Colombier srv->flush(r); 2467dd7cddfSDavid du Colombier else 2477fd46167SDavid du Colombier respond(r, nil); 2487fd46167SDavid du Colombier } 2497fd46167SDavid du Colombier static int 2507fd46167SDavid du Colombier rflush(Req *r, char *error) 2517fd46167SDavid du Colombier { 2527fd46167SDavid du Colombier Req *or; 2537dd7cddfSDavid du Colombier 2547fd46167SDavid du Colombier assert(error == nil); 2557fd46167SDavid du Colombier or = r->oldreq; 2567fd46167SDavid du Colombier if(or){ 2577fd46167SDavid du Colombier qlock(&or->lk); 2587fd46167SDavid du Colombier if(or->responded == 0){ 2597fd46167SDavid du Colombier or->flush = erealloc9p(or->flush, (or->nflush+1)*sizeof(or->flush[0])); 2607fd46167SDavid du Colombier or->flush[or->nflush++] = r; 2617fd46167SDavid du Colombier qunlock(&or->lk); 2627fd46167SDavid du Colombier return -1; /* delay response until or is responded */ 2637fd46167SDavid du Colombier } 2647fd46167SDavid du Colombier qunlock(&or->lk); 2657fd46167SDavid du Colombier closereq(or); 2667fd46167SDavid du Colombier } 2677fd46167SDavid du Colombier r->oldreq = nil; 2687fd46167SDavid du Colombier return 0; 2697fd46167SDavid du Colombier } 2707fd46167SDavid du Colombier 2717fd46167SDavid du Colombier static char* 2727fd46167SDavid du Colombier oldwalk1(Fid *fid, char *name, void *arg) 2737fd46167SDavid du Colombier { 2747fd46167SDavid du Colombier char *e; 2757fd46167SDavid du Colombier Qid qid; 2767fd46167SDavid du Colombier Srv *srv; 2777fd46167SDavid du Colombier 2787fd46167SDavid du Colombier srv = arg; 2797fd46167SDavid du Colombier e = srv->walk1(fid, name, &qid); 2807fd46167SDavid du Colombier if(e) 2817fd46167SDavid du Colombier return e; 282*2ebbfa15SDavid du Colombier fid->qid = qid; 2837fd46167SDavid du Colombier return nil; 2847fd46167SDavid du Colombier } 2857fd46167SDavid du Colombier 2867fd46167SDavid du Colombier static char* 2877fd46167SDavid du Colombier oldclone(Fid *fid, Fid *newfid, void *arg) 2887fd46167SDavid du Colombier { 2897fd46167SDavid du Colombier Srv *srv; 2907fd46167SDavid du Colombier 2917fd46167SDavid du Colombier srv = arg; 2927fd46167SDavid du Colombier if(srv->clone == nil) 2937fd46167SDavid du Colombier return nil; 2947fd46167SDavid du Colombier return srv->clone(fid, newfid); 2957fd46167SDavid du Colombier } 2967fd46167SDavid du Colombier 2977fd46167SDavid du Colombier static void 2987fd46167SDavid du Colombier swalk(Srv *srv, Req *r) 2997fd46167SDavid du Colombier { 3009a747e4fSDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){ 3019a747e4fSDavid du Colombier respond(r, Eunknownfid); 3027fd46167SDavid du Colombier return; 3037dd7cddfSDavid du Colombier } 3049a747e4fSDavid du Colombier if(r->fid->omode != -1){ 3059a747e4fSDavid du Colombier respond(r, "cannot clone open fid"); 3067fd46167SDavid du Colombier return; 3079a747e4fSDavid du Colombier } 3089a747e4fSDavid du Colombier if(r->ifcall.nwname && !(r->fid->qid.type&QTDIR)){ 3099a747e4fSDavid du Colombier respond(r, Ewalknodir); 3107fd46167SDavid du Colombier return; 3119a747e4fSDavid du Colombier } 3129a747e4fSDavid du Colombier if(r->ifcall.fid != r->ifcall.newfid){ 3139a747e4fSDavid du Colombier if((r->newfid = allocfid(srv->fpool, r->ifcall.newfid)) == nil){ 3149a747e4fSDavid du Colombier respond(r, Edupfid); 3157fd46167SDavid du Colombier return; 3169a747e4fSDavid du Colombier } 3179a747e4fSDavid du Colombier r->newfid->uid = estrdup9p(r->fid->uid); 3189a747e4fSDavid du Colombier }else{ 3199a747e4fSDavid du Colombier incref(&r->fid->ref); 3209a747e4fSDavid du Colombier r->newfid = r->fid; 3219a747e4fSDavid du Colombier } 3229a747e4fSDavid du Colombier if(r->fid->file){ 3239a747e4fSDavid du Colombier filewalk(r); 3249a747e4fSDavid du Colombier }else if(srv->walk1) 3257fd46167SDavid du Colombier walkandclone(r, oldwalk1, oldclone, srv); 3269a747e4fSDavid du Colombier else if(srv->walk) 3279a747e4fSDavid du Colombier srv->walk(r); 3289a747e4fSDavid du Colombier else 3299a747e4fSDavid du Colombier sysfatal("no walk function, no file trees"); 3307fd46167SDavid du Colombier } 3317fd46167SDavid du Colombier static void 3327fd46167SDavid du Colombier rwalk(Req *r, char *error) 3337fd46167SDavid du Colombier { 3347fd46167SDavid du Colombier if(error || r->ofcall.nwqid < r->ifcall.nwname){ 3357fd46167SDavid du Colombier if(r->ifcall.fid != r->ifcall.newfid && r->newfid) 3367fd46167SDavid du Colombier closefid(removefid(r->srv->fpool, r->newfid->fid)); 3377fd46167SDavid du Colombier if (r->ofcall.nwqid==0){ 3387fd46167SDavid du Colombier if(error==nil && r->ifcall.nwname!=0) 3397fd46167SDavid du Colombier r->error = Enotfound; 3407fd46167SDavid du Colombier }else 3417fd46167SDavid du Colombier r->error = nil; // No error on partial walks 3427fd46167SDavid du Colombier }else{ 3437fd46167SDavid du Colombier if(r->ofcall.nwqid == 0){ 3447fd46167SDavid du Colombier /* Just a clone */ 3457fd46167SDavid du Colombier r->newfid->qid = r->fid->qid; 3467fd46167SDavid du Colombier }else{ 3477fd46167SDavid du Colombier /* if file trees are in use, filewalk took care of the rest */ 3487fd46167SDavid du Colombier r->newfid->qid = r->ofcall.wqid[r->ofcall.nwqid-1]; 3497fd46167SDavid du Colombier } 3507fd46167SDavid du Colombier } 3517fd46167SDavid du Colombier } 3527dd7cddfSDavid du Colombier 3537fd46167SDavid du Colombier static void 3547fd46167SDavid du Colombier sopen(Srv *srv, Req *r) 3557fd46167SDavid du Colombier { 3567fd46167SDavid du Colombier int p; 3577fd46167SDavid du Colombier 3589a747e4fSDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){ 3599a747e4fSDavid du Colombier respond(r, Eunknownfid); 3607fd46167SDavid du Colombier return; 3619a747e4fSDavid du Colombier } 3627dd7cddfSDavid du Colombier if(r->fid->omode != -1){ 3637dd7cddfSDavid du Colombier respond(r, Ebotch); 3647fd46167SDavid du Colombier return; 3657dd7cddfSDavid du Colombier } 3669a747e4fSDavid du Colombier if((r->fid->qid.type&QTDIR) && (r->ifcall.mode&~ORCLOSE) != OREAD){ 3679a747e4fSDavid du Colombier respond(r, Eisdir); 3687fd46167SDavid du Colombier return; 3697dd7cddfSDavid du Colombier } 3709a747e4fSDavid du Colombier r->ofcall.qid = r->fid->qid; 3719a747e4fSDavid du Colombier switch(r->ifcall.mode&3){ 3729a747e4fSDavid du Colombier default: 3739a747e4fSDavid du Colombier assert(0); 3749a747e4fSDavid du Colombier case OREAD: 3759a747e4fSDavid du Colombier p = AREAD; 3769a747e4fSDavid du Colombier break; 3779a747e4fSDavid du Colombier case OWRITE: 3789a747e4fSDavid du Colombier p = AWRITE; 3799a747e4fSDavid du Colombier break; 3809a747e4fSDavid du Colombier case ORDWR: 3819a747e4fSDavid du Colombier p = AREAD|AWRITE; 3829a747e4fSDavid du Colombier break; 3839a747e4fSDavid du Colombier case OEXEC: 3849a747e4fSDavid du Colombier p = AEXEC; 3859a747e4fSDavid du Colombier break; 3869a747e4fSDavid du Colombier } 3879a747e4fSDavid du Colombier if(r->ifcall.mode&OTRUNC) 3887dd7cddfSDavid du Colombier p |= AWRITE; 3899a747e4fSDavid du Colombier if((r->fid->qid.type&QTDIR) && p!=AREAD){ 3909a747e4fSDavid du Colombier respond(r, Eperm); 3917fd46167SDavid du Colombier return; 3929a747e4fSDavid du Colombier } 3939a747e4fSDavid du Colombier if(r->fid->file){ 3947dd7cddfSDavid du Colombier if(!hasperm(r->fid->file, r->fid->uid, p)){ 3957dd7cddfSDavid du Colombier respond(r, Eperm); 3967fd46167SDavid du Colombier return; 3977dd7cddfSDavid du Colombier } 3989a747e4fSDavid du Colombier /* BUG RACE */ 3999a747e4fSDavid du Colombier if((r->ifcall.mode&ORCLOSE) 4007dd7cddfSDavid du Colombier && !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){ 4017dd7cddfSDavid du Colombier respond(r, Eperm); 4027fd46167SDavid du Colombier return; 4037dd7cddfSDavid du Colombier } 40480ee5cbfSDavid du Colombier r->ofcall.qid = r->fid->file->qid; 4059a747e4fSDavid du Colombier if((r->ofcall.qid.type&QTDIR) 4069a747e4fSDavid du Colombier && (r->fid->rdir = opendirfile(r->fid->file)) == nil){ 4079a747e4fSDavid du Colombier respond(r, "opendirfile failed"); 4087fd46167SDavid du Colombier return; 4099a747e4fSDavid du Colombier } 4107dd7cddfSDavid du Colombier } 4117dd7cddfSDavid du Colombier if(srv->open) 4129a747e4fSDavid du Colombier srv->open(r); 4137dd7cddfSDavid du Colombier else 4147dd7cddfSDavid du Colombier respond(r, nil); 4157fd46167SDavid du Colombier } 4167fd46167SDavid du Colombier static void 4177fd46167SDavid du Colombier ropen(Req *r, char *error) 4187fd46167SDavid du Colombier { 4197fd46167SDavid du Colombier char errbuf[ERRMAX]; 4207fd46167SDavid du Colombier if(error) 4217fd46167SDavid du Colombier return; 4227fd46167SDavid du Colombier if(chatty9p){ 4237fd46167SDavid du Colombier snprint(errbuf, sizeof errbuf, "fid mode is 0x%ux\n", r->ifcall.mode); 4247fd46167SDavid du Colombier write(2, errbuf, strlen(errbuf)); 4257fd46167SDavid du Colombier } 4267fd46167SDavid du Colombier r->fid->omode = r->ifcall.mode; 4277fd46167SDavid du Colombier r->fid->qid = r->ofcall.qid; 4287fd46167SDavid du Colombier if(r->ofcall.qid.type&QTDIR) 4297fd46167SDavid du Colombier r->fid->diroffset = 0; 4307fd46167SDavid du Colombier } 4317dd7cddfSDavid du Colombier 4327fd46167SDavid du Colombier static void 4337fd46167SDavid du Colombier screate(Srv *srv, Req *r) 4347fd46167SDavid du Colombier { 4359a747e4fSDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil) 4369a747e4fSDavid du Colombier respond(r, Eunknownfid); 4379a747e4fSDavid du Colombier else if(r->fid->omode != -1) 4389a747e4fSDavid du Colombier respond(r, Ebotch); 4399a747e4fSDavid du Colombier else if(!(r->fid->qid.type&QTDIR)) 4409a747e4fSDavid du Colombier respond(r, Ecreatenondir); 4417dd7cddfSDavid du Colombier else if(r->fid->file && !hasperm(r->fid->file, r->fid->uid, AWRITE)) 4429a747e4fSDavid du Colombier respond(r, Eperm); 4439a747e4fSDavid du Colombier else if(srv->create) 4449a747e4fSDavid du Colombier srv->create(r); 4457dd7cddfSDavid du Colombier else 4469a747e4fSDavid du Colombier respond(r, Enocreate); 4477fd46167SDavid du Colombier } 4487fd46167SDavid du Colombier static void 4497fd46167SDavid du Colombier rcreate(Req *r, char *error) 4507fd46167SDavid du Colombier { 4517fd46167SDavid du Colombier if(error) 4527fd46167SDavid du Colombier return; 4537fd46167SDavid du Colombier r->fid->omode = r->ifcall.mode; 4547fd46167SDavid du Colombier r->fid->qid = r->ofcall.qid; 4557fd46167SDavid du Colombier } 4567dd7cddfSDavid du Colombier 4577fd46167SDavid du Colombier static void 4587fd46167SDavid du Colombier sread(Srv *srv, Req *r) 4597fd46167SDavid du Colombier { 4607fd46167SDavid du Colombier int o; 4617fd46167SDavid du Colombier 4629a747e4fSDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){ 4639a747e4fSDavid du Colombier respond(r, Eunknownfid); 4647fd46167SDavid du Colombier return; 4657dd7cddfSDavid du Colombier } 4669a747e4fSDavid du Colombier if(r->ifcall.count < 0){ 4679a747e4fSDavid du Colombier respond(r, Ebotch); 4687fd46167SDavid du Colombier return; 4699a747e4fSDavid du Colombier } 4709a747e4fSDavid du Colombier if(r->ifcall.offset < 0 4719a747e4fSDavid du Colombier || ((r->fid->qid.type&QTDIR) && r->ifcall.offset != 0 && r->ifcall.offset != r->fid->diroffset)){ 4729a747e4fSDavid du Colombier respond(r, Ebadoffset); 4737fd46167SDavid du Colombier return; 4749a747e4fSDavid du Colombier } 4759a747e4fSDavid du Colombier 4769a747e4fSDavid du Colombier if(r->ifcall.count > srv->msize - IOHDRSZ) 4779a747e4fSDavid du Colombier r->ifcall.count = srv->msize - IOHDRSZ; 4787fd46167SDavid du Colombier r->rbuf = emalloc9p(r->ifcall.count); 4799a747e4fSDavid du Colombier r->ofcall.data = r->rbuf; 4809a747e4fSDavid du Colombier o = r->fid->omode & 3; 4819a747e4fSDavid du Colombier if(o != OREAD && o != ORDWR && o != OEXEC){ 4829a747e4fSDavid du Colombier respond(r, Ebotch); 4837fd46167SDavid du Colombier return; 4849a747e4fSDavid du Colombier } 4859a747e4fSDavid du Colombier if((r->fid->qid.type&QTDIR) && r->fid->file){ 4869a747e4fSDavid du Colombier r->ofcall.count = readdirfile(r->fid->rdir, r->rbuf, r->ifcall.count); 4879a747e4fSDavid du Colombier respond(r, nil); 4887fd46167SDavid du Colombier return; 4899a747e4fSDavid du Colombier } 4909a747e4fSDavid du Colombier if(srv->read) 4919a747e4fSDavid du Colombier srv->read(r); 4929a747e4fSDavid du Colombier else 4939a747e4fSDavid du Colombier respond(r, "no srv->read"); 4947fd46167SDavid du Colombier } 4957fd46167SDavid du Colombier static void 4967fd46167SDavid du Colombier rread(Req *r, char *error) 4977fd46167SDavid du Colombier { 4987fd46167SDavid du Colombier if(error==nil && (r->fid->qid.type&QTDIR)) 4997fd46167SDavid du Colombier r->fid->diroffset += r->ofcall.count; 5007fd46167SDavid du Colombier } 5017dd7cddfSDavid du Colombier 5027fd46167SDavid du Colombier static void 5037fd46167SDavid du Colombier swrite(Srv *srv, Req *r) 5047fd46167SDavid du Colombier { 5057fd46167SDavid du Colombier int o; 5067fd46167SDavid du Colombier char e[ERRMAX]; 5077fd46167SDavid du Colombier 5089a747e4fSDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){ 5099a747e4fSDavid du Colombier respond(r, Eunknownfid); 5107fd46167SDavid du Colombier return; 5117dd7cddfSDavid du Colombier } 5129a747e4fSDavid du Colombier if(r->ifcall.count < 0){ 5139a747e4fSDavid du Colombier respond(r, Ebotch); 5147fd46167SDavid du Colombier return; 5159a747e4fSDavid du Colombier } 5169a747e4fSDavid du Colombier if(r->ifcall.offset < 0){ 5179a747e4fSDavid du Colombier respond(r, Ebotch); 5187fd46167SDavid du Colombier return; 5199a747e4fSDavid du Colombier } 5209a747e4fSDavid du Colombier if(r->ifcall.count > srv->msize - IOHDRSZ) 5219a747e4fSDavid du Colombier r->ifcall.count = srv->msize - IOHDRSZ; 5229a747e4fSDavid du Colombier o = r->fid->omode & 3; 5239a747e4fSDavid du Colombier if(o != OWRITE && o != ORDWR){ 5249a747e4fSDavid du Colombier snprint(e, sizeof e, "write on fid with open mode 0x%ux", r->fid->omode); 5259a747e4fSDavid du Colombier respond(r, e); 5267fd46167SDavid du Colombier return; 5279a747e4fSDavid du Colombier } 5289a747e4fSDavid du Colombier if(srv->write) 5299a747e4fSDavid du Colombier srv->write(r); 5309a747e4fSDavid du Colombier else 5319a747e4fSDavid du Colombier respond(r, "no srv->write"); 5327fd46167SDavid du Colombier } 5337fd46167SDavid du Colombier static void 5347fd46167SDavid du Colombier rwrite(Req *r, char *error) 5357fd46167SDavid du Colombier { 5367fd46167SDavid du Colombier if(error) 5377fd46167SDavid du Colombier return; 5387fd46167SDavid du Colombier if(r->fid->file) 5397fd46167SDavid du Colombier r->fid->file->qid.vers++; 5407fd46167SDavid du Colombier } 5417dd7cddfSDavid du Colombier 5427fd46167SDavid du Colombier static void 5437fd46167SDavid du Colombier sclunk(Srv *srv, Req *r) 5447fd46167SDavid du Colombier { 5459a747e4fSDavid du Colombier if((r->fid = removefid(srv->fpool, r->ifcall.fid)) == nil) 5469a747e4fSDavid du Colombier respond(r, Eunknownfid); 5479a747e4fSDavid du Colombier else 5487dd7cddfSDavid du Colombier respond(r, nil); 5497fd46167SDavid du Colombier } 5507fd46167SDavid du Colombier static void 5517fd46167SDavid du Colombier rclunk(Req*, char*) 5527fd46167SDavid du Colombier { 5537fd46167SDavid du Colombier } 5547dd7cddfSDavid du Colombier 5557fd46167SDavid du Colombier static void 5567fd46167SDavid du Colombier sremove(Srv *srv, Req *r) 5577fd46167SDavid du Colombier { 5589a747e4fSDavid du Colombier if((r->fid = removefid(srv->fpool, r->ifcall.fid)) == nil){ 5599a747e4fSDavid du Colombier respond(r, Eunknownfid); 5607fd46167SDavid du Colombier return; 5619a747e4fSDavid du Colombier } 5629a747e4fSDavid du Colombier /* BUG RACE */ 5639a747e4fSDavid du Colombier if(r->fid->file && !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){ 5647dd7cddfSDavid du Colombier respond(r, Eperm); 5657fd46167SDavid du Colombier return; 5667dd7cddfSDavid du Colombier } 5679a747e4fSDavid du Colombier if(srv->remove) 5689a747e4fSDavid du Colombier srv->remove(r); 5697dd7cddfSDavid du Colombier else 5709a747e4fSDavid du Colombier respond(r, r->fid->file ? nil : Enoremove); 5717fd46167SDavid du Colombier } 5727fd46167SDavid du Colombier static void 5737fd46167SDavid du Colombier rremove(Req *r, char *error, char *errbuf) 5747fd46167SDavid du Colombier { 5757fd46167SDavid du Colombier if(error) 5767fd46167SDavid du Colombier return; 5777fd46167SDavid du Colombier if(r->fid->file){ 5787fd46167SDavid du Colombier if(removefile(r->fid->file) < 0){ 5797fd46167SDavid du Colombier snprint(errbuf, ERRMAX, "remove %s: %r", 5807fd46167SDavid du Colombier r->fid->file->name); 5817fd46167SDavid du Colombier r->error = errbuf; 5827fd46167SDavid du Colombier } 5837fd46167SDavid du Colombier r->fid->file = nil; 5847fd46167SDavid du Colombier } 5857fd46167SDavid du Colombier } 5867dd7cddfSDavid du Colombier 5877fd46167SDavid du Colombier static void 5887fd46167SDavid du Colombier sstat(Srv *srv, Req *r) 5897fd46167SDavid du Colombier { 5909a747e4fSDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){ 5919a747e4fSDavid du Colombier respond(r, Eunknownfid); 5927fd46167SDavid du Colombier return; 5937dd7cddfSDavid du Colombier } 5949a747e4fSDavid du Colombier if(r->fid->file){ 5959a747e4fSDavid du Colombier r->d = r->fid->file->Dir; 5969a747e4fSDavid du Colombier if(r->d.name) 5979a747e4fSDavid du Colombier r->d.name = estrdup9p(r->d.name); 5989a747e4fSDavid du Colombier if(r->d.uid) 5999a747e4fSDavid du Colombier r->d.uid = estrdup9p(r->d.uid); 6009a747e4fSDavid du Colombier if(r->d.gid) 6019a747e4fSDavid du Colombier r->d.gid = estrdup9p(r->d.gid); 6029a747e4fSDavid du Colombier if(r->d.muid) 6039a747e4fSDavid du Colombier r->d.muid = estrdup9p(r->d.muid); 6049a747e4fSDavid du Colombier } 6057dd7cddfSDavid du Colombier if(srv->stat) 6069a747e4fSDavid du Colombier srv->stat(r); 6079a747e4fSDavid du Colombier else if(r->fid->file) 6087dd7cddfSDavid du Colombier respond(r, nil); 6099a747e4fSDavid du Colombier else 6109a747e4fSDavid du Colombier respond(r, Enostat); 6117fd46167SDavid du Colombier } 6127fd46167SDavid du Colombier static void 6137fd46167SDavid du Colombier rstat(Req *r, char *error) 6147fd46167SDavid du Colombier { 6157fd46167SDavid du Colombier int n; 6167fd46167SDavid du Colombier uchar *statbuf; 6177fd46167SDavid du Colombier uchar tmp[BIT16SZ]; 6187dd7cddfSDavid du Colombier 6197fd46167SDavid du Colombier if(error) 6207fd46167SDavid du Colombier return; 6217fd46167SDavid du Colombier if(convD2M(&r->d, tmp, BIT16SZ) != BIT16SZ){ 6227fd46167SDavid du Colombier r->error = "convD2M(_,_,BIT16SZ) did not return BIT16SZ"; 6237fd46167SDavid du Colombier return; 6247fd46167SDavid du Colombier } 6257fd46167SDavid du Colombier n = GBIT16(tmp)+BIT16SZ; 6267fd46167SDavid du Colombier statbuf = emalloc9p(n); 6277fd46167SDavid du Colombier if(statbuf == nil){ 6287fd46167SDavid du Colombier r->error = "out of memory"; 6297fd46167SDavid du Colombier return; 6307fd46167SDavid du Colombier } 6317fd46167SDavid du Colombier r->ofcall.nstat = convD2M(&r->d, statbuf, n); 6327fd46167SDavid du Colombier r->ofcall.stat = statbuf; /* freed in closereq */ 6337fd46167SDavid du Colombier if(r->ofcall.nstat < 0){ 6347fd46167SDavid du Colombier r->error = "convD2M fails"; 6357fd46167SDavid du Colombier free(statbuf); 6367fd46167SDavid du Colombier return; 6377fd46167SDavid du Colombier } 6387fd46167SDavid du Colombier } 6397fd46167SDavid du Colombier 6407fd46167SDavid du Colombier static void 6417fd46167SDavid du Colombier swstat(Srv *srv, Req *r) 6427fd46167SDavid du Colombier { 6437fd46167SDavid du Colombier if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){ 6449a747e4fSDavid du Colombier respond(r, Eunknownfid); 6457fd46167SDavid du Colombier return; 6467fd46167SDavid du Colombier } 6477fd46167SDavid du Colombier if(srv->wstat == nil){ 6489a747e4fSDavid du Colombier respond(r, Enowstat); 6497fd46167SDavid du Colombier return; 6507fd46167SDavid du Colombier } 6517fd46167SDavid du Colombier if(convM2D(r->ifcall.stat, r->ifcall.nstat, &r->d, (char*)r->ifcall.stat) != r->ifcall.nstat){ 6527fd46167SDavid du Colombier respond(r, Ebaddir); 6537fd46167SDavid du Colombier return; 6547fd46167SDavid du Colombier } 6557fd46167SDavid du Colombier if((ushort)~r->d.type){ 6567fd46167SDavid du Colombier respond(r, "wstat -- attempt to change type"); 6577fd46167SDavid du Colombier return; 6587fd46167SDavid du Colombier } 6597fd46167SDavid du Colombier if((uint)~r->d.dev){ 6607fd46167SDavid du Colombier respond(r, "wstat -- attempt to change dev"); 6617fd46167SDavid du Colombier return; 6627fd46167SDavid du Colombier } 6637fd46167SDavid du Colombier if((uchar)~r->d.qid.type || (ulong)~r->d.qid.vers || (uvlong)~r->d.qid.path){ 6647fd46167SDavid du Colombier respond(r, "wstat -- attempt to change qid"); 6657fd46167SDavid du Colombier return; 6667fd46167SDavid du Colombier } 6677fd46167SDavid du Colombier if(r->d.muid && r->d.muid[0]){ 6687fd46167SDavid du Colombier respond(r, "wstat -- attempt to change muid"); 6697fd46167SDavid du Colombier return; 6707fd46167SDavid du Colombier } 6717fd46167SDavid du Colombier if((ulong)~r->d.atime != 0){ 6727fd46167SDavid du Colombier respond(r, "wstat -- attempt to change atime"); 6737fd46167SDavid du Colombier return; 6747fd46167SDavid du Colombier } 6757fd46167SDavid du Colombier if((ulong)~r->d.mode && (r->d.mode&DMDIR) != (r->fid->qid.type&DMDIR)){ 6767fd46167SDavid du Colombier respond(r, "wstat -- attempt to change DMDIR bit"); 6777fd46167SDavid du Colombier return; 6787fd46167SDavid du Colombier } 6797fd46167SDavid du Colombier srv->wstat(r); 6807fd46167SDavid du Colombier } 6817fd46167SDavid du Colombier static void 6827fd46167SDavid du Colombier rwstat(Req*, char*) 6837fd46167SDavid du Colombier { 6847fd46167SDavid du Colombier } 6857fd46167SDavid du Colombier 6867fd46167SDavid du Colombier void 6877fd46167SDavid du Colombier srv(Srv *srv) 6887fd46167SDavid du Colombier { 6897fd46167SDavid du Colombier Req *r; 6907fd46167SDavid du Colombier 6917fd46167SDavid du Colombier fmtinstall('D', dirfmt); 6927fd46167SDavid du Colombier fmtinstall('F', fcallfmt); 6937fd46167SDavid du Colombier 6947fd46167SDavid du Colombier if(srv->fpool == nil) 6957fd46167SDavid du Colombier srv->fpool = allocfidpool(srv->destroyfid); 6967fd46167SDavid du Colombier if(srv->rpool == nil) 6977fd46167SDavid du Colombier srv->rpool = allocreqpool(srv->destroyreq); 6987fd46167SDavid du Colombier if(srv->msize == 0) 6997fd46167SDavid du Colombier srv->msize = 8192+IOHDRSZ; 7007fd46167SDavid du Colombier 7017fd46167SDavid du Colombier changemsize(srv, srv->msize); 7027fd46167SDavid du Colombier 7037fd46167SDavid du Colombier srv->fpool->srv = srv; 7047fd46167SDavid du Colombier srv->rpool->srv = srv; 7057fd46167SDavid du Colombier 7067fd46167SDavid du Colombier while(r = getreq(srv)){ 7077fd46167SDavid du Colombier if(r->error){ 7087fd46167SDavid du Colombier respond(r, r->error); 7097fd46167SDavid du Colombier continue; 7107fd46167SDavid du Colombier } 7117fd46167SDavid du Colombier switch(r->ifcall.type){ 7127fd46167SDavid du Colombier default: 7137fd46167SDavid du Colombier respond(r, "unknown message"); 7147dd7cddfSDavid du Colombier break; 7157fd46167SDavid du Colombier case Tversion: sversion(srv, r); break; 7167fd46167SDavid du Colombier case Tauth: sauth(srv, r); break; 7177fd46167SDavid du Colombier case Tattach: sattach(srv, r); break; 7187fd46167SDavid du Colombier case Tflush: sflush(srv, r); break; 7197fd46167SDavid du Colombier case Twalk: swalk(srv, r); break; 7207fd46167SDavid du Colombier case Topen: sopen(srv, r); break; 7217fd46167SDavid du Colombier case Tcreate: screate(srv, r); break; 7227fd46167SDavid du Colombier case Tread: sread(srv, r); break; 7237fd46167SDavid du Colombier case Twrite: swrite(srv, r); break; 7247fd46167SDavid du Colombier case Tclunk: sclunk(srv, r); break; 7257fd46167SDavid du Colombier case Tremove: sremove(srv, r); break; 7267fd46167SDavid du Colombier case Tstat: sstat(srv, r); break; 7277fd46167SDavid du Colombier case Twstat: swstat(srv, r); break; 7287dd7cddfSDavid du Colombier } 7297dd7cddfSDavid du Colombier } 7303ff48bf5SDavid du Colombier 7313ff48bf5SDavid du Colombier if(srv->end) 7323ff48bf5SDavid du Colombier srv->end(srv); 7337dd7cddfSDavid du Colombier } 7347dd7cddfSDavid du Colombier 7357dd7cddfSDavid du Colombier void 7367dd7cddfSDavid du Colombier respond(Req *r, char *error) 7377dd7cddfSDavid du Colombier { 7387fd46167SDavid du Colombier int i, m, n; 7399a747e4fSDavid du Colombier char errbuf[ERRMAX]; 7407dd7cddfSDavid du Colombier Srv *srv; 7417dd7cddfSDavid du Colombier 7429a747e4fSDavid du Colombier srv = r->srv; 7439a747e4fSDavid du Colombier assert(srv != nil); 7449a747e4fSDavid du Colombier 7457dd7cddfSDavid du Colombier assert(r->responded == 0); 7467fd46167SDavid du Colombier r->error = error; 7477dd7cddfSDavid du Colombier 7489a747e4fSDavid du Colombier switch(r->ifcall.type){ 7497dd7cddfSDavid du Colombier default: 7509a747e4fSDavid du Colombier assert(0); 7517fd46167SDavid du Colombier /* 7527fd46167SDavid du Colombier * Flush is special. If the handler says so, we return 7537fd46167SDavid du Colombier * without further processing. Respond will be called 7547fd46167SDavid du Colombier * again once it is safe. 7557fd46167SDavid du Colombier */ 7569a747e4fSDavid du Colombier case Tflush: 7577fd46167SDavid du Colombier if(rflush(r, error)<0) 7587fd46167SDavid du Colombier return; 7597dd7cddfSDavid du Colombier break; 7607fd46167SDavid du Colombier case Tversion: rversion(r, error); break; 7617fd46167SDavid du Colombier case Tauth: rauth(r, error); break; 7627fd46167SDavid du Colombier case Tattach: rattach(r, error); break; 7637fd46167SDavid du Colombier case Twalk: rwalk(r, error); break; 7647fd46167SDavid du Colombier case Topen: ropen(r, error); break; 7657fd46167SDavid du Colombier case Tcreate: rcreate(r, error); break; 7667fd46167SDavid du Colombier case Tread: rread(r, error); break; 7677fd46167SDavid du Colombier case Twrite: rwrite(r, error); break; 7687fd46167SDavid du Colombier case Tclunk: rclunk(r, error); break; 7697fd46167SDavid du Colombier case Tremove: rremove(r, error, errbuf); break; 7707fd46167SDavid du Colombier case Tstat: rstat(r, error); break; 7717fd46167SDavid du Colombier case Twstat: rwstat(r, error); break; 7727dd7cddfSDavid du Colombier } 7737dd7cddfSDavid du Colombier 7749a747e4fSDavid du Colombier r->ofcall.tag = r->ifcall.tag; 7759a747e4fSDavid du Colombier r->ofcall.type = r->ifcall.type+1; 7767fd46167SDavid du Colombier if(r->error) 7777fd46167SDavid du Colombier setfcallerror(&r->ofcall, r->error); 7787dd7cddfSDavid du Colombier 7799a747e4fSDavid du Colombier if(chatty9p) 7809a747e4fSDavid du Colombier fprint(2, "-%d-> %F\n", srv->outfd, &r->ofcall); 7817dd7cddfSDavid du Colombier 7829a747e4fSDavid du Colombier qlock(&srv->wlock); 7839a747e4fSDavid du Colombier n = convS2M(&r->ofcall, srv->wbuf, srv->msize); 7849a747e4fSDavid du Colombier if(n <= 0){ 7859a747e4fSDavid du Colombier fprint(2, "n = %d %F\n", n, &r->ofcall); 7869a747e4fSDavid du Colombier abort(); 7879a747e4fSDavid du Colombier } 7889a747e4fSDavid du Colombier assert(n > 2); 7897fd46167SDavid du Colombier if(r->pool) /* not a fake */ 7909a747e4fSDavid du Colombier closereq(removereq(r->pool, r->ifcall.tag)); 7915d459b5aSDavid du Colombier m = write(srv->outfd, srv->wbuf, n); 7925d459b5aSDavid du Colombier if(m != n) 7935d459b5aSDavid du Colombier sysfatal("lib9p srv: write %d returned %d on fd %d: %r", n, m, srv->outfd); 7945d459b5aSDavid du Colombier qunlock(&srv->wlock); 7955d459b5aSDavid du Colombier 7967fd46167SDavid du Colombier qlock(&r->lk); /* no one will add flushes now */ 7977fd46167SDavid du Colombier r->responded = 1; 7987fd46167SDavid du Colombier qunlock(&r->lk); 7997fd46167SDavid du Colombier 8007fd46167SDavid du Colombier for(i=0; i<r->nflush; i++) 8017fd46167SDavid du Colombier respond(r->flush[i], nil); 8027fd46167SDavid du Colombier free(r->flush); 8037fd46167SDavid du Colombier 8047fd46167SDavid du Colombier if(r->pool) 8057fd46167SDavid du Colombier closereq(r); 8067fd46167SDavid du Colombier else 8077fd46167SDavid du Colombier free(r); 8087dd7cddfSDavid du Colombier } 8097dd7cddfSDavid du Colombier 8109a747e4fSDavid du Colombier int 8119a747e4fSDavid du Colombier postfd(char *name, int pfd) 8127dd7cddfSDavid du Colombier { 8137dd7cddfSDavid du Colombier int fd; 8149a747e4fSDavid du Colombier char buf[80]; 8157dd7cddfSDavid du Colombier 8167dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "/srv/%s", name); 8179a747e4fSDavid du Colombier if(chatty9p) 8189a747e4fSDavid du Colombier fprint(2, "postfd %s\n", buf); 8199a747e4fSDavid du Colombier fd = create(buf, OWRITE|ORCLOSE|OCEXEC, 0600); 8209a747e4fSDavid du Colombier if(fd < 0){ 8219a747e4fSDavid du Colombier if(chatty9p) 8229a747e4fSDavid du Colombier fprint(2, "create fails: %r\n"); 8239a747e4fSDavid du Colombier return -1; 8247dd7cddfSDavid du Colombier } 8259a747e4fSDavid du Colombier if(fprint(fd, "%d", pfd) < 0){ 8269a747e4fSDavid du Colombier if(chatty9p) 8279a747e4fSDavid du Colombier fprint(2, "write fails: %r\n"); 8289a747e4fSDavid du Colombier close(fd); 8299a747e4fSDavid du Colombier return -1; 8307dd7cddfSDavid du Colombier } 8319a747e4fSDavid du Colombier if(chatty9p) 8329a747e4fSDavid du Colombier fprint(2, "postfd successful\n"); 8339a747e4fSDavid du Colombier return 0; 8347dd7cddfSDavid du Colombier } 8357dd7cddfSDavid du Colombier 836