📄 srv.c
字号:
r->fid->qid = r->ofcall.qid; if(r->ofcall.qid.type&QTDIR) r->fid->diroffset = 0;}static voidscreate(Srv *srv, Req *r){ if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil) respond(r, Eunknownfid); else if(r->fid->omode != -1) respond(r, Ebotch); else if(!(r->fid->qid.type&QTDIR)) respond(r, Ecreatenondir); else if(r->fid->file && !hasperm(r->fid->file, r->fid->uid, AWRITE)) respond(r, Eperm); else if(srv->create) srv->create(r); else respond(r, Enocreate);}static voidrcreate(Req *r, char *error){ if(error) return; r->fid->omode = r->ifcall.mode; r->fid->qid = r->ofcall.qid;}static voidsread(Srv *srv, Req *r){ int o; if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){ respond(r, Eunknownfid); return; } if((int)r->ifcall.count < 0){ respond(r, Ebotch); return; } if(r->ifcall.offset < 0 || ((r->fid->qid.type&QTDIR) && r->ifcall.offset != 0 && r->ifcall.offset != r->fid->diroffset)){ respond(r, Ebadoffset); return; } if(r->ifcall.count > srv->msize - IOHDRSZ) r->ifcall.count = srv->msize - IOHDRSZ; r->rbuf = emalloc9p(r->ifcall.count); r->ofcall.data = r->rbuf; o = r->fid->omode & 3; if(o != OREAD && o != ORDWR && o != OEXEC){ respond(r, Ebotch); return; } if((r->fid->qid.type&QTDIR) && r->fid->file){ r->ofcall.count = readdirfile(r->fid->rdir, r->rbuf, r->ifcall.count); respond(r, nil); return; } if(srv->read) srv->read(r); else respond(r, "no srv->read");}static voidrread(Req *r, char *error){ if(error==nil && (r->fid->qid.type&QTDIR)) r->fid->diroffset += r->ofcall.count;}static voidswrite(Srv *srv, Req *r){ int o; char e[ERRMAX]; if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){ respond(r, Eunknownfid); return; } if((int)r->ifcall.count < 0){ respond(r, Ebotch); return; } if(r->ifcall.offset < 0){ respond(r, Ebotch); return; } if(r->ifcall.count > srv->msize - IOHDRSZ) r->ifcall.count = srv->msize - IOHDRSZ; o = r->fid->omode & 3; if(o != OWRITE && o != ORDWR){ snprint(e, sizeof e, "write on fid with open mode 0x%ux", r->fid->omode); respond(r, e); return; } if(srv->write) srv->write(r); else respond(r, "no srv->write");}static voidrwrite(Req *r, char *error){ if(error) return; if(r->fid->file) r->fid->file->qid.vers++;}static voidsclunk(Srv *srv, Req *r){ if((r->fid = removefid(srv->fpool, r->ifcall.fid)) == nil) respond(r, Eunknownfid); else respond(r, nil);}static voidrclunk(Req*, char*){}static voidsremove(Srv *srv, Req *r){ if((r->fid = removefid(srv->fpool, r->ifcall.fid)) == nil){ respond(r, Eunknownfid); return; } /* BUG RACE */ if(r->fid->file && !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){ respond(r, Eperm); return; } if(srv->remove) srv->remove(r); else respond(r, r->fid->file ? nil : Enoremove);}static voidrremove(Req *r, char *error, char *errbuf){ if(error) return; if(r->fid->file){ if(removefile(r->fid->file) < 0){ snprint(errbuf, ERRMAX, "remove %s: %r", r->fid->file->name); r->error = errbuf; } r->fid->file = nil; }}static voidsstat(Srv *srv, Req *r){ if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){ respond(r, Eunknownfid); return; } if(r->fid->file){ /* should we rlock the file? */ r->d = r->fid->file->Dir; if(r->d.name) r->d.name = estrdup9p(r->d.name); if(r->d.uid) r->d.uid = estrdup9p(r->d.uid); if(r->d.gid) r->d.gid = estrdup9p(r->d.gid); if(r->d.muid) r->d.muid = estrdup9p(r->d.muid); } if(srv->stat) srv->stat(r); else if(r->fid->file) respond(r, nil); else respond(r, Enostat);}static voidrstat(Req *r, char *error){ int n; uchar *statbuf; uchar tmp[BIT16SZ]; if(error) return; if(convD2M(&r->d, tmp, BIT16SZ) != BIT16SZ){ r->error = "convD2M(_,_,BIT16SZ) did not return BIT16SZ"; return; } n = GBIT16(tmp)+BIT16SZ; statbuf = emalloc9p(n); if(statbuf == nil){ r->error = "out of memory"; return; } r->ofcall.nstat = convD2M(&r->d, statbuf, n); r->ofcall.stat = statbuf; /* freed in closereq */ if(r->ofcall.nstat <= BIT16SZ){ r->error = "convD2M fails"; free(statbuf); return; }}static voidswstat(Srv *srv, Req *r){ if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){ respond(r, Eunknownfid); return; } if(srv->wstat == nil){ respond(r, Enowstat); return; } if(convM2D(r->ifcall.stat, r->ifcall.nstat, &r->d, (char*)r->ifcall.stat) != r->ifcall.nstat){ respond(r, Ebaddir); return; } if((ushort)~r->d.type){ respond(r, "wstat -- attempt to change type"); return; } if((uint)~r->d.dev){ respond(r, "wstat -- attempt to change dev"); return; } if((uchar)~r->d.qid.type || (ulong)~r->d.qid.vers || (uvlong)~r->d.qid.path){ respond(r, "wstat -- attempt to change qid"); return; } if(r->d.muid && r->d.muid[0]){ respond(r, "wstat -- attempt to change muid"); return; } if((ulong)~r->d.mode && ((r->d.mode&DMDIR)>>24) != (r->fid->qid.type&QTDIR)){ respond(r, "wstat -- attempt to change DMDIR bit"); return; } srv->wstat(r);}static voidrwstat(Req*, char*){}voidsrv(Srv *srv){ Req *r; fmtinstall('D', dirfmt); fmtinstall('F', fcallfmt); if(srv->fpool == nil) srv->fpool = allocfidpool(srv->destroyfid); if(srv->rpool == nil) srv->rpool = allocreqpool(srv->destroyreq); if(srv->msize == 0) srv->msize = 8192+IOHDRSZ; changemsize(srv, srv->msize); srv->fpool->srv = srv; srv->rpool->srv = srv; while(r = getreq(srv)){ if(r->error){ respond(r, r->error); continue; } switch(r->ifcall.type){ default: respond(r, "unknown message"); break; case Tversion: sversion(srv, r); break; case Tauth: sauth(srv, r); break; case Tattach: sattach(srv, r); break; case Tflush: sflush(srv, r); break; case Twalk: swalk(srv, r); break; case Topen: sopen(srv, r); break; case Tcreate: screate(srv, r); break; case Tread: sread(srv, r); break; case Twrite: swrite(srv, r); break; case Tclunk: sclunk(srv, r); break; case Tremove: sremove(srv, r); break; case Tstat: sstat(srv, r); break; case Twstat: swstat(srv, r); break; } } free(srv->rbuf); srv->rbuf = nil; free(srv->wbuf); srv->wbuf = nil; srv->msize = 0; freefidpool(srv->fpool); srv->fpool = nil; freereqpool(srv->rpool); srv->rpool = nil; if(srv->end) srv->end(srv);}voidrespond(Req *r, char *error){ int i, m, n; char errbuf[ERRMAX]; Srv *srv; srv = r->srv; assert(srv != nil); assert(r->responded == 0); r->error = error; switch(r->ifcall.type){ default: assert(0); /* * Flush is special. If the handler says so, we return * without further processing. Respond will be called * again once it is safe. */ case Tflush: if(rflush(r, error)<0) return; break; case Tversion: rversion(r, error); break; case Tauth: rauth(r, error); break; case Tattach: rattach(r, error); break; case Twalk: rwalk(r, error); break; case Topen: ropen(r, error); break; case Tcreate: rcreate(r, error); break; case Tread: rread(r, error); break; case Twrite: rwrite(r, error); break; case Tclunk: rclunk(r, error); break; case Tremove: rremove(r, error, errbuf); break; case Tstat: rstat(r, error); break; case Twstat: rwstat(r, error); break; } r->ofcall.tag = r->ifcall.tag; r->ofcall.type = r->ifcall.type+1; if(r->error) setfcallerror(&r->ofcall, r->error);if(chatty9p) fprint(2, "-%d-> %F\n", srv->outfd, &r->ofcall); qlock(&srv->wlock); n = convS2M(&r->ofcall, srv->wbuf, srv->msize); if(n <= 0){ fprint(2, "n = %d %F\n", n, &r->ofcall); abort(); } assert(n > 2); if(r->pool) /* not a fake */ closereq(removereq(r->pool, r->ifcall.tag)); m = write(srv->outfd, srv->wbuf, n); if(m != n) sysfatal("lib9p srv: write %d returned %d on fd %d: %r", n, m, srv->outfd); qunlock(&srv->wlock); qlock(&r->lk); /* no one will add flushes now */ r->responded = 1; qunlock(&r->lk); for(i=0; i<r->nflush; i++) respond(r->flush[i], nil); free(r->flush); r->flush = nil; r->nflush = 0; if(r->pool) closereq(r); else free(r);}voidresponderror(Req *r){ char errbuf[ERRMAX]; rerrstr(errbuf, sizeof errbuf); respond(r, errbuf);}intpostfd(char *name, int pfd){ int fd; char buf[80]; snprint(buf, sizeof buf, "/srv/%s", name); if(chatty9p) fprint(2, "postfd %s\n", buf); fd = create(buf, OWRITE|ORCLOSE|OCEXEC, 0600); if(fd < 0){ if(chatty9p) fprint(2, "create fails: %r\n"); return -1; } if(fprint(fd, "%d", pfd) < 0){ if(chatty9p) fprint(2, "write fails: %r\n"); close(fd); return -1; } if(chatty9p) fprint(2, "postfd successful\n"); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -