/* * Main protocol loop */ void io(void) { Fcall rhdr; int n; for(;;) { n = read9pmsg(srvfd, rbuf, sizeof rbuf-1); if(n <= 0) fatal("mount read"); if(convM2S(rbuf, n, &rhdr) == 0) { if(debugfd >= 0) fprint(2, "%s: malformed message\n", argv0); continue; } if(debugfd >= 0) fprint(debugfd, "<-%F\n", &rhdr);/**/ if(!fcalls[rhdr.type]) reply(&rhdr, "bad fcall type"); else (*fcalls[rhdr.type])(&rhdr); } }
void shuffle(void *arg) { int *fd; char *buf, *tbuf; int n; Fcall *t; fd = (int*)arg; buf = emalloc(BLEN+1); t = nil; tbuf = nil; for(;;){ n = read9pmsg(fd[0], buf, BLEN); if(n <= 0){ if(debug) fprint(dfd, "%d->%d read returns %d: %r\n", fd[0], fd[1], n); break; } if(debug){ if(t == nil) t = emalloc(sizeof(Fcall)); if(tbuf == nil) tbuf = emalloc(BLEN+1); memmove(tbuf, buf, n); /* because convM2S is destructive */ if(convM2S((uchar*)tbuf, n, t) != n) fprint(dfd, "%d->%d convert error in convM2S", fd[0], fd[1]); else fprint(dfd, "%d->%d %F\n", fd[0], fd[1], t); } if(write(fd[1], buf, n) != n) break; } threadexitsall(0); }
void io(void) { char *err; int n, nerr; char buf[ERRMAX]; errstr(buf, sizeof buf); for(nerr=0, buf[0]='\0'; nerr<100; nerr++){ /* * reading from a pipe or a network device * will give an error after a few eof reads * however, we cannot tell the difference * between a zero-length read and an interrupt * on the processes writing to us, * so we wait for the error */ n = read9pmsg(mfd[0], mdata, sizeof mdata); if(n==0) continue; if(n < 0){ if(buf[0]=='\0') errstr(buf, sizeof buf); continue; } nerr = 0; buf[0] = '\0'; if(convM2S(mdata, n, &rhdr) != n) error("convert error in convM2S"); if(verbose) fprint(2, "tapefs: <=%F\n", &rhdr);/**/ thdr.data = (char*)mdata + IOHDRSZ; thdr.stat = mdata + IOHDRSZ; if(!fcalls[rhdr.type]) err = "bad fcall type"; else err = (*fcalls[rhdr.type])(newfid(rhdr.fid)); if(err){ thdr.type = Rerror; thdr.ename = err; }else{ thdr.type = rhdr.type + 1; thdr.fid = rhdr.fid; } thdr.tag = rhdr.tag; n = convS2M(&thdr, mdata, messagesize); if(n <= 0) error("convert error in convS2M"); if(verbose) fprint(2, "tapefs: =>%F\n", &thdr);/**/ if(write(mfd[1], mdata, n) != n) error("mount write"); } if(buf[0]=='\0' || strstr(buf, "hungup")) exits(""); fprint(2, "%s: mount read: %s\n", argv0, buf); exits(buf); }
void fsysproc(void *v) { int n; Xfid *x; Fid *f; Fcall t; uchar *buf; threadsetname("fsysproc"); USED(v); x = nil; for(;;){ buf = emalloc(messagesize+UTFmax); /* overflow for appending partial rune in xfidwrite */ n = read9pmsg(sfd, buf, messagesize); if(n <= 0){ if(closing) break; error("i/o error on server channel"); } if(x == nil){ sendp(cxfidalloc, nil); x = recvp(cxfidalloc); } x->buf = buf; if(convM2S(buf, n, &x->fcall) != n) error("convert error in convM2S"); if(DEBUG) fprint(2, "%F\n", &x->fcall); if(fcall[x->fcall.type] == nil) x = respond(x, &t, "bad fcall type"); else{ switch(x->fcall.type){ case Tversion: case Tauth: case Tflush: f = nil; break; case Tattach: f = newfid(x->fcall.fid); break; default: f = newfid(x->fcall.fid); if(!f->busy){ x->f = f; x = respond(x, &t, "fid not in use"); continue; } break; } x->f = f; x = (*fcall[x->fcall.type])(x, f); } } }
static Req* getreq(Srv *s) { long n; uchar *buf; Fcall f; Req *r; qlock(&s->rlock); if((n = read9pmsg(s->infd, s->rbuf, s->msize)) <= 0){ qunlock(&s->rlock); return nil; } buf = emalloc9p(n); memmove(buf, s->rbuf, n); qunlock(&s->rlock); if(convM2S(buf, n, &f) != n){ free(buf); return nil; } if((r=allocreq(s->rpool, f.tag)) == nil){ /* duplicate tag: cons up a fake Req */ r = emalloc9p(sizeof *r); incref(&r->ref); r->tag = f.tag; r->ifcall = f; r->error = Eduptag; r->buf = buf; r->responded = 0; r->type = 0; r->srv = s; r->pool = nil; if(chatty9p) fprint(2, "<-%d- %F: dup tag\n", s->infd, &f); return r; } r->srv = s; r->responded = 0; r->buf = buf; r->ifcall = f; memset(&r->ofcall, 0, sizeof r->ofcall); r->type = r->ifcall.type; if(chatty9p) if(r->error) fprint(2, "<-%d- %F: %s\n", s->infd, &r->ifcall, r->error); else fprint(2, "<-%d- %F\n", s->infd, &r->ifcall); return r; }
static int getfcall(int fd, Fcall* f) { int r; r = read9pmsg(fd, rxbuf, sizeof(rxbuf)); if (r <= 0) return 0; if (convM2S(rxbuf, sizeof(rxbuf), f) == 0) return -1; return 1; }
void io(int srvfd) { int n, pid; pid = getpid(); fmtinstall('F', fcallfmt); for(;;){ /* * reading from a pipe or a network device * will give an error after a few eof reads. * however, we cannot tell the difference * between a zero-length read and an interrupt * on the processes writing to us, * so we wait for the error. */ n = read9pmsg(srvfd, mdata, sizeof mdata); if(n < 0) break; if(n == 0) continue; if(convM2S(mdata, n, req) == 0) continue; if(chatty) fprint(2, "dossrv %d:<-%F\n", pid, req); errno = 0; if(!fcalls[req->type]) errno = Ebadfcall; else (*fcalls[req->type])(); if(errno){ rep->type = Rerror; rep->ename = xerrstr(errno); }else{ rep->type = req->type + 1; rep->fid = req->fid; } rep->tag = req->tag; if(chatty) fprint(2, "dossrv %d:->%F\n", pid, rep); n = convS2M(rep, mdata, sizeof mdata); if(n == 0) panic("convS2M error on write"); if(write(srvfd, mdata, n) != n) panic("mount write"); } chat("server shut down"); }
int xmesg(Session *s, int t) { int n; if(chatty){ if(0 <= t && t < nelem(tnames) && tnames[t]) chat("T%s...", tnames[t]); else chat("T%d...", t); } s->f.type = t; s->f.tag = ++s->tag; if(p9debug) fprint(2, "xmseg\tsend %F\n", &s->f); n = convS2M(&s->f, s->data, messagesize); if(niwrite(s->fd, s->data, n) != n){ clog("xmesg write error on %d: %r\n", s->fd); return -1; } again: n = read9pmsg(s->fd, s->data, messagesize); if(n < 0){ clog("xmesg read error: %r\n"); return -1; } if(convM2S(s->data, n, &s->f) <= 0){ clog("xmesg bad convM2S %d %.2x %.2x %.2x %.2x\n", n, ((uchar*)s->data)[0], ((uchar*)s->data)[1], ((uchar*)s->data)[2], ((uchar*)s->data)[3]); return -1; } if(p9debug) fprint(2, "\trecv %F\n", &s->f); if(s->f.tag != s->tag){ clog("xmesg tag %d for %d\n", s->f.tag, s->tag); goto again; } if(s->f.type == Rerror){ if(t == Tclunk) clog("xmesg clunk: %s", s->f.ename); chat("xmesg %d error %s...", t, s->f.ename); return -1; } if(s->f.type != t+1){ clog("xmesg type mismatch: %d, expected %d\n", s->f.type, t+1); return -1; } return 0; }
void fsrun(void *a) { struct Fsarg *fsarg; Fs* fs; char *root; int n, t; Request *r; Fid *f; Dir *d; fsarg = a; fs = fsarg->fs; fs->fd = fsarg->fd; root = fsarg->root; d = dirstat("/"); if(d == nil) fatal("root %s inaccessible: %r", root); fs->rootqid = d->qid; free(d); for(;;){ r = allocreq(messagesize); qlock(&iolock); n = read9pmsg(fs->fd, r->buf, messagesize); qunlock(&iolock); if(n <= 0) fatal("read9pmsg error: %r"); if(convM2S(r->buf, n, &r->f) == 0){ fprint(2, "can't convert %ux %ux %ux\n", r->buf[0], r->buf[1], r->buf[2]); free(r); continue; } f = fsgetfid(fs, r->f.fid); r->fid = f; if(debug) fprint(2, "%F path %llux\n", &r->f, f->qid.path); t = r->f.type; r->f.type++; (*fcall[t])(fs, r, f); fsputfid(fs, f); } }
void inputthread(void *arg) { uchar *pkt; int n, nn, tag; Msg *m; Ioproc *io; threadsetname("input"); if(verbose) fprint(2, "%T input thread\n"); io = ioproc(); USED(arg); while((pkt = read9ppkt(io, 0)) != nil){ n = GBIT32(pkt); if(n < 7){ fprint(2, "%T short 9P packet from server\n"); free(pkt); continue; } if(verbose > 2) fprint(2, "%T read %.*H\n", n, pkt); tag = GBIT16(pkt+5); if((m = msgget(tag)) == nil){ fprint(2, "%T unexpected 9P response tag %d\n", tag); free(pkt); continue; } if((nn = convM2S(pkt, n, &m->rx)) != n){ fprint(2, "%T bad packet - convM2S %d but %d\n", nn, n); free(pkt); msgput(m); continue; } if(verbose > 1) fprint(2, "%T * -> %F%s\n", &m->rx, m->internal ? " (internal)" : ""); m->rpkt = pkt; m->rx.tag = m->ctag; if(m->internal) sendp(m->c->internal, m); else if(m->c->outq) sendq(m->c->outq, m); else msgput(m); } closeioproc(io); /*fprint(2, "%T input eof\n"); */ threadexitsall(0); }
void mainproc(void *v) { int n, nn; Fcall f; USED(v); atnotify(ignorepipe, 1); fmtinstall('D', dirfmt); fmtinstall('M', dirmodefmt); fmtinstall('F', fcallfmt); fmtinstall('H', encodefmt); outq = qalloc(); inq = qalloc(); if(!versioned){ f.type = Tversion; f.version = "9P2000"; f.msize = msize; f.tag = NOTAG; n = convS2M(&f, vbuf, sizeof vbuf); if(n <= BIT16SZ) sysfatal("convS2M conversion error"); if(verbose > 1) fprint(2, "%T * <- %F\n", &f); nn = write(1, vbuf, n); if(n != nn) sysfatal("error writing Tversion: %r\n"); n = read9pmsg(0, vbuf, sizeof vbuf); if(n < 0) sysfatal("read9pmsg failure"); if(convM2S(vbuf, n, &f) != n) sysfatal("convM2S failure"); if(f.msize < msize) msize = f.msize; if(verbose > 1) fprint(2, "%T * -> %F\n", &f); } threadcreate(inputthread, nil, STACK); threadcreate(outputthread, nil, STACK); /* if(rootfid) */ /* dorootstat(); */ threadcreate(listenthread, nil, STACK); threadexits(0); }
static void filsysproc(void *arg) { int n; Xfid *x; Fid *f; Fcall t; uint8_t *buf; Filsys *fs; threadsetname("FILSYSPROC"); fs = arg; fs->pid = getpid(); x = nil; for(;;){ buf = emalloc(messagesize+UTFmax); /* UTFmax for appending partial rune in xfidwrite */ n = read9pmsg(fs->sfd, buf, messagesize); if(n <= 0){ yield(); /* if threadexitsall'ing, will not return */ fprint(2, "rio: %d: read9pmsg: %d %r\n", getpid(), n); errorshouldabort = 0; error("eof or i/o error on server channel"); } if(x == nil){ send(fs->cxfidalloc, nil); recv(fs->cxfidalloc, &x); x->fs = fs; } x->buf = buf; if(convM2S(buf, n, x) != n) error("convert error in convM2S"); if(DEBUG) fprint(2, "rio:<-%F\n", &x->Fcall); if(fcall[x->type] == nil) x = filsysrespond(fs, x, &t, Ebadfcall); else{ if(x->type==Tversion || x->type==Tauth) f = nil; else f = newfid(fs, x->fid); x->f = f; x = (*fcall[x->type])(fs, x, f); } firstmessage = 0; } }
void io(void) { char *err; int n; for(;;){ n = read9pmsg(mfd[0], mdata, sizeof mdata); if(n <= 0) break; if(convM2S(mdata, n, &rhdr) != n) sysfatal("convM2S conversion error"); if(dflag) fprint(2, "vacfs:<-%F\n", &rhdr); thdr.data = (char*)mdata + IOHDRSZ; if(!fcalls[rhdr.type]) err = "bad fcall type"; else err = (*fcalls[rhdr.type])(newfid(rhdr.fid)); if(err){ thdr.type = Rerror; thdr.ename = err; #ifdef PLAN9PORT thdr.errornum = 0; #endif }else{ thdr.type = rhdr.type + 1; thdr.fid = rhdr.fid; } thdr.tag = rhdr.tag; if(dflag) fprint(2, "vacfs:->%F\n", &thdr); n = convS2M(&thdr, mdata, messagesize); if(n <= BIT16SZ) sysfatal("convS2M conversion error"); if(err) vtfree(err); if(write(mfd[1], mdata, n) != n) sysfatal("mount write: %r"); } }
Msg* mread9p(Ioproc *io, int fd) { int n, nn; uchar *pkt; Msg *m; if((pkt = read9ppkt(io, fd)) == nil) return nil; m = msgnew(0); m->tpkt = pkt; n = GBIT32(pkt); nn = convM2S(pkt, n, &m->tx); if(nn != n){ fprint(2, "%T read bad packet from %d\n", fd); return nil; } return m; }
static void io(void) { long n; uint8_t mdata[IOHDRSZ + Maxfdata]; struct job *job; pthread_attr_t pth_attr; /* * each request is handled via a thread. Somewhat less efficient than * the old cs but way cleaner. */ pthread_attr_init(&pth_attr); pthread_attr_setdetachstate(&pth_attr, PTHREAD_CREATE_DETACHED); for (;;) { n = read9pmsg(mfd[0], mdata, sizeof(mdata)); if (n <= 0) error(1, 0, "%s: %r", "mount read"); job = newjob(); if (convM2S(mdata, n, &job->request) != n) { fprintf(stderr, "convM2S went south: format error %ux %ux %ux %ux %ux", mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]); error(1, 0, "format error %ux %ux %ux %ux %ux", mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]); freejob(job); continue; } /* stash the thread in the job so we can join them all * later if we want to. */ if (pthread_create(&job->thread, &pth_attr, &job_thread, job)) { error(1, 0, "%s: %r", "Failed to create job"); continue; } } }
static int p_seprint(Msg *m) { Fcall f; char *p; memset(&f, 0, sizeof(f)); f.type = 0; f.data = 0; /* protection for %F */ if(convM2S(m->ps, m->pe-m->ps, &f)){ p = m->p; m->p = seprint(m->p, m->e, "%F", &f); while(p < m->p){ p = strchr(p, '\n'); if(p == nil) break; *p = '\\'; } } else dump.seprint(m); m->pr = nil; return 0; }
void ioproc0(void *v) { long n; Mfile *mf; uchar mdata[IOHDRSZ + Maxfdata]; Request req; Job *job; USED(v); for(;;){ n = read9pmsg(mfd[0], mdata, sizeof mdata); if(n <= 0){ syslog(0, logfile, "error reading mntpt: %r"); break; } job = newjob(); if(convM2S(mdata, n, &job->request) != n){ freejob(job); continue; } if(debug) syslog(0, logfile, "%F", &job->request); getactivity(&req); req.aborttime = now + 60; /* don't spend more than 60 seconds */ mf = nil; switch(job->request.type){ case Tversion: case Tauth: case Tflush: break; case Tattach: mf = newfid(job->request.fid, 1); if(mf == nil){ sendmsg(job, "fid in use"); goto skip; } break; default: mf = newfid(job->request.fid, 0); if(mf == nil){ sendmsg(job, "unknown fid"); goto skip; } break; } switch(job->request.type){ default: syslog(1, logfile, "unknown request type %d", job->request.type); break; case Tversion: rversion(job); break; case Tauth: rauth(job); break; case Tflush: rflush(job); break; case Tattach: rattach(job, mf); break; case Twalk: rwalk(job, mf); break; case Topen: ropen(job, mf); break; case Tcreate: rcreate(job, mf); break; case Tread: rread(job, mf); break; case Twrite: rwrite(job, mf, &req); break; case Tclunk: rclunk(job, mf); break; case Tremove: rremove(job, mf); break; case Tstat: rstat(job, mf); break; case Twstat: rwstat(job, mf); break; } skip: freejob(job); putactivity(); } }
void io(void) { volatile long n; volatile uchar mdata[IOHDRSZ + Maxfdata]; Job *volatile job; Mfile *volatile mf; volatile Request req; memset(&req, 0, sizeof req); /* * a slave process is sometimes forked to wait for replies from other * servers. The master process returns immediately via a longjmp * through 'mret'. */ if(setjmp(req.mret)) putactivity(0); req.isslave = 0; stop = 0; while(!stop){ procsetname("%d %s/dns Twrites of %d 9p rpcs read; %d alarms", stats.qrecvd9p, mntpt, stats.qrecvd9prpc, stats.alarms); n = read9pmsg(mfd[0], mdata, sizeof mdata); if(n<=0){ dnslog("error reading 9P from %s: %r", mntpt); sleep(2000); /* don't thrash after read error */ return; } stats.qrecvd9prpc++; job = newjob(); if(convM2S(mdata, n, &job->request) != n){ freejob(job); continue; } mf = newfid(job->request.fid, 0); if(debug) dnslog("%F", &job->request); getactivity(&req, 0); req.aborttime = timems() + Maxreqtm; req.from = "9p"; switch(job->request.type){ default: warning("unknown request type %d", job->request.type); break; case Tversion: rversion(job); break; case Tauth: rauth(job); break; case Tflush: rflush(job); break; case Tattach: rattach(job, mf); break; case Twalk: rwalk(job, mf); break; case Topen: ropen(job, mf); break; case Tcreate: rcreate(job, mf); break; case Tread: rread(job, mf); break; case Twrite: /* &req is handed to dnresolve() */ rwrite(job, mf, &req); break; case Tclunk: rclunk(job, mf); break; case Tremove: rremove(job, mf); break; case Tstat: rstat(job, mf); break; case Twstat: rwstat(job, mf); break; } freejob(job); /* * slave processes die after replying */ if(req.isslave){ putactivity(0); _exits(0); } putactivity(0); } /* kill any udp server, notifier, etc. processes */ postnote(PNGROUP, getpid(), "die"); sleep(1000); }
void io(int srvfd) { int n, pid; Fcall xreq, xrep; req = &xreq; rep = &xrep; pid = getpid(); fmtinstall('F', fcallfmt); for(;;){ /* * reading from a pipe or a network device * will give an error after a few eof reads. * however, we cannot tell the difference * between a zero-length read and an interrupt * on the processes writing to us, * so we wait for the error. */ n = read9pmsg(srvfd, mdata, sizeof mdata); if(n < 0) break; if(n == 0) continue; if(convM2S(mdata, n, req) == 0) continue; if(chatty) fprint(2, "9660srv %d:<-%F\n", pid, req); errno = 0; if(!waserror()){ err_msg[0] = 0; if(req->type >= nelem(fcalls) || !fcalls[req->type]) error("bad fcall type"); (*fcalls[req->type])(); poperror(); } if(err_msg[0]){ rep->type = Rerror; rep->ename = err_msg; }else{ rep->type = req->type + 1; rep->fid = req->fid; } rep->tag = req->tag; if(chatty) fprint(2, "9660srv %d:->%F\n", pid, rep); n = convS2M(rep, mdata, sizeof mdata); if(n == 0) panic(1, "convS2M error on write"); if(write(srvfd, mdata, n) != n) panic(1, "mount write"); if(nerr_lab != 0) panic(0, "err stack %d"); } chat("server shut down"); }
void notefs(int fd) { uchar buf[IOHDRSZ+Maxfdata]; int i, n, ncpunote; Fcall f; Qid wqid[MAXWELEM]; Fid *fid, *nfid; int doreply; rfork(RFNOTEG); fmtinstall('F', fcallfmt); for(n = 0; n < Nfid; n++){ fids[n].file = -1; fids[n].omode = -1; } ncpunote = 0; for(;;){ n = read9pmsg(fd, buf, sizeof(buf)); if(n <= 0){ if(dbg) fprint(2, "read9pmsg(%d) returns %d: %r\n", fd, n); break; } if(convM2S(buf, n, &f) <= BIT16SZ) break; if(dbg) fprint(2, "notefs: ->%F\n", &f); doreply = 1; fid = getfid(f.fid); if(fid == nil){ nofids: f.type = Rerror; f.ename = Enofile; fsreply(fd, &f); continue; } switch(f.type++){ default: f.type = Rerror; f.ename = "unknown type"; break; case Tflush: flushreq(f.oldtag); break; case Tversion: if(f.msize > IOHDRSZ+Maxfdata) f.msize = IOHDRSZ+Maxfdata; break; case Tauth: f.type = Rerror; f.ename = "authentication not required"; break; case Tattach: f.qid = fstab[Qdir].qid; fid->file = Qdir; break; case Twalk: nfid = nil; if(f.newfid != f.fid){ nfid = getfid(f.newfid); if(nfid == nil) goto nofids; nfid->file = fid->file; fid = nfid; } for(i=0; i<f.nwname && i<MAXWELEM; i++){ if(fid->file != Qdir){ f.type = Rerror; f.ename = Enotdir; break; } if(strcmp(f.wname[i], "..") == 0){ wqid[i] = fstab[Qdir].qid; continue; } if(strcmp(f.wname[i], "cpunote") != 0){ if(i == 0){ f.type = Rerror; f.ename = "file does not exist"; } break; } fid->file = Qcpunote; wqid[i] = fstab[Qcpunote].qid; } if(nfid != nil && (f.type == Rerror || i < f.nwname)) nfid ->file = -1; if(f.type != Rerror){ f.nwqid = i; for(i=0; i<f.nwqid; i++) f.wqid[i] = wqid[i]; } break; case Topen: if(f.mode != OREAD){ f.type = Rerror; f.ename = Eperm; break; } fid->omode = f.mode; if(fid->file == Qcpunote) ncpunote++; f.qid = fstab[fid->file].qid; f.iounit = 0; break; case Tread: if(fsread(fd, fid, &f) < 0) goto err; doreply = 0; break; case Tclunk: if(fid->omode != -1 && fid->file == Qcpunote){ ncpunote--; if(ncpunote == 0) /* remote side is done */ goto err; } fid->file = -1; fid->omode = -1; break; case Tstat: if(fsstat(fd, fid, &f) < 0) goto err; doreply = 0; break; case Tcreate: case Twrite: case Tremove: case Twstat: f.type = Rerror; f.ename = Eperm; break; } if(doreply) if(fsreply(fd, &f) < 0) break; } err: if(dbg) fprint(2, "notefs exiting: %r\n"); werrstr("success"); postnote(PNGROUP, exportpid, "kill"); if(dbg) fprint(2, "postnote PNGROUP %d: %r\n", exportpid); close(fd); }
static void lfssrvwrite(Devlogfs *d, void *buf, long n) { volatile int locked = 0; qlock(&d->wlock); if(waserror()){ qunlock(&d->wlock); nexterror(); } if (d->state == Hungup) error(Ehungup); Sleep(&d->writerendez, writeok, d); if (convM2S(buf, n, &d->in) != n) { /* * someone is writing drivel; have nothing to do with them anymore * most common cause; trying to mount authenticated */ d->state = Hungup; error(Ehungup); } d->out.tag = d->in.tag; d->out.fid = d->in.fid; d->out.type = d->in.type + 1; if (waserror()) { if (locked) qunlock(&d->qlock); rerror(d, up->env->errstr); goto Replied; } if (d->in.type != Tversion && d->in.type != Tattach) { if (d->state != Attached) error("must be attached"); qlock(&d->qlock); locked = 1; } switch (d->in.type) { case Tauth: error("no authentication needed"); case Tversion: { char *rversion; if (d->state != NeedVersion) error("unexpected Tversion"); if (d->in.tag != NOTAG) error("protocol botch"); /* * check the version string */ if (strcmp(d->in.version, devlogfs9pversion) != 0) rversion = "unknown"; else rversion = devlogfs9pversion; /* * allocate the reply buffer */ d->readbufsize = d->in.msize; if (d->readbufsize > MAXMSIZE) d->readbufsize = MAXMSIZE; d->readbuf = emalloc(d->readbufsize); /* * compose the Rversion */ d->out.msize = d->readbufsize; d->out.version = rversion; d->state = NeedAttach; break; } case Tattach: if (d->state != NeedAttach) error("unexpected attach"); if (d->in.afid != NOFID) error("unexpected afid"); errorany(logfsserverattach(d->server, d->in.fid, d->in.uname, &d->out.qid)); d->state = Attached; break; case Tclunk: errorany(logfsserverclunk(d->server, d->in.fid)); break; case Tcreate: errorany(logfsservercreate(d->server, d->in.fid, d->in.name, d->in.perm, d->in.mode, &d->out.qid)); d->out.iounit = d->readbufsize - 11; break; case Tflush: break; case Topen: errorany(logfsserveropen(d->server, d->in.fid, d->in.mode, &d->out.qid)); d->out.iounit = d->readbufsize - 11; break; case Tread: d->out.data = (char *)d->readbuf + 11; /* TODO - avoid memmove */ errorany(logfsserverread(d->server, d->in.fid, d->in.offset, d->in.count, (uchar *)d->out.data, d->readbufsize - 11, &d->out.count)); break; case Tremove: errorany(logfsserverremove(d->server, d->in.fid)); break; case Tstat: d->out.stat = d->readbuf + 9; /* TODO - avoid memmove */ errorany(logfsserverstat(d->server, d->in.fid, d->out.stat, d->readbufsize - 9, &d->out.nstat)); // print("nstat %d\n", d->out.nstat); break; case Twalk: errorany(logfsserverwalk(d->server, d->in.fid, d->in.newfid, d->in.nwname, d->in.wname, &d->out.nwqid, d->out.wqid)); break; case Twrite: errorany(logfsserverwrite(d->server, d->in.fid, d->in.offset, d->in.count, (uchar *)d->in.data, &d->out.count)); break; case Twstat: errorany(logfsserverwstat(d->server, d->in.fid, d->in.stat, d->in.nstat)); break; default: print("lfssrvwrite: msg %d unimplemented\n", d->in.type); error("unimplemented"); } poperror(); if (locked) qunlock(&d->qlock); reply(d); Replied: poperror(); qunlock(&d->wlock); }