diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cmd/9pserve.c | 150 |
1 files changed, 135 insertions, 15 deletions
diff --git a/src/cmd/9pserve.c b/src/cmd/9pserve.c index 3ffdf231..32e2a4a7 100644 --- a/src/cmd/9pserve.c +++ b/src/cmd/9pserve.c @@ -30,6 +30,7 @@ struct Fid int ref; int cfid; int openfd; + int isdir; Fid *next; }; @@ -67,6 +68,7 @@ struct Conn Hash *fid[NHASH]; Queue *outq; Queue *inq; + int dotu; }; char *xaname; @@ -82,11 +84,12 @@ int msize = 8192; u32int xafid = NOFID; int attached; int versioned; +int dotu; void *gethash(Hash**, uint); int puthash(Hash**, uint, void*); int delhash(Hash**, uint, void*); -Msg *mread9p(Ioproc*, int); +Msg *mread9p(Ioproc*, int, int); int mwrite9p(Ioproc*, int, uchar*); uchar *read9ppkt(Ioproc*, int); int write9ppkt(int, uchar*); @@ -108,7 +111,7 @@ void listenthread(void*); void outputthread(void*); void inputthread(void*); void rewritehdr(Fcall*, uchar*); -void repack(Fcall*, uchar**); +void repack(Fcall*, uchar**, int); int tlisten(char*, char*); int taccept(int, char*); int iolisten(Ioproc*, char*, char*); @@ -119,6 +122,8 @@ void mainproc(void*); int ignorepipe(void*, char*); int timefmt(Fmt*); void dorootstat(void); +int stripudirread(Msg*); +int stripustat(Fcall*, uchar**, int); void usage(void) @@ -211,7 +216,7 @@ mainproc(void *v) if(!versioned){ f.type = Tversion; - f.version = "9P2000"; + f.version = "9P2000.u"; f.msize = msize; f.tag = NOTAG; n = convS2M(&f, vbuf, sizeof vbuf); @@ -225,6 +230,7 @@ mainproc(void *v) if(f.msize < msize) msize = f.msize; if(verbose > 1) fprint(2, "%T * -> %F\n", &f); + dotu = strncmp(f.version, "9P2000.u", 8) == 0; } threadcreate(inputthread, nil, STACK); @@ -281,9 +287,9 @@ send9pmsg(Msg *m) { int n, nn; - n = sizeS2M(&m->rx); + n = sizeS2Mu(&m->rx, m->c->dotu); m->rpkt = emalloc(n); - nn = convS2M(&m->rx, m->rpkt, n); + nn = convS2Mu(&m->rx, m->rpkt, n, m->c->dotu); if(nn != n) sysfatal("sizeS2M + convS2M disagree"); sendq(m->c->outq, m); @@ -294,9 +300,9 @@ sendomsg(Msg *m) { int n, nn; - n = sizeS2M(&m->tx); + n = sizeS2Mu(&m->tx, m->c->dotu); m->tpkt = emalloc(n); - nn = convS2M(&m->tx, m->tpkt, n); + nn = convS2Mu(&m->tx, m->tpkt, n, m->c->dotu); if(nn != n) sysfatal("sizeS2M + convS2M disagree"); sendq(outq, m); @@ -342,7 +348,7 @@ connthread(void *arg) close(c->fd); c->fd = fd; threadcreate(connoutthread, c, STACK); - while((m = mread9p(io, c->fd)) != nil){ + while((m = mread9p(io, c->fd, c->dotu)) != nil){ if(verbose > 1) fprint(2, "%T fd#%d -> %F\n", c->fd, &m->tx); m->c = c; m->ctag = m->tx.tag; @@ -360,6 +366,11 @@ connthread(void *arg) if(m->rx.msize > msize) m->rx.msize = msize; m->rx.version = "9P2000"; + c->dotu = 0; + if(dotu && strncmp(m->tx.version, "9P2000.u", 8) == 0){ + m->rx.version = "9P2000.u"; + c->dotu = 1; + } m->rx.type = Rversion; send9pmsg(m); continue; @@ -395,7 +406,7 @@ connthread(void *arg) m->tx.afid = xafid; m->tx.aname = xaname; m->tx.uname = estrdup(m->tx.uname); - repack(&m->tx, &m->tpkt); + repack(&m->tx, &m->tpkt, c->dotu); free(m->tx.uname); m->tx.uname = "XXX"; } @@ -452,6 +463,12 @@ connthread(void *arg) continue; } m->fid->ref++; + if(m->tx.type==Twstat && dotu && !c->dotu){ + if(stripustat(&m->tx, &m->tpkt, 1) < 0){ + err(m, "cannot convert stat buffer"); + continue; + } + } break; } @@ -720,6 +737,7 @@ xopenfd(Msg *m) void connoutthread(void *arg) { + char *ename; int err; Conn *c; Queue *outq; @@ -766,6 +784,24 @@ connoutthread(void *arg) if(delhash(m->c->fid, m->newfid->cfid, m->newfid) == 0) fidput(m->newfid); break; + case Tread: + if(!err && m->fid->isdir && dotu && !m->c->dotu) + stripudirread(m); + break; + case Tstat: + if(!err && dotu && !m->c->dotu) + stripustat(&m->rx, &m->rpkt, 0); + break; + case Topen: + case Tcreate: + m->fid->isdir = (m->rx.qid.type & QTDIR); + break; + } + if(m->rx.type==Rerror && dotu && !c->dotu){ + ename = estrdup(m->rx.ename); + m->rx.ename = ename; + repack(&m->rx, &m->rpkt, c->dotu); + free(ename); } if(delhash(m->c->tag, m->ctag, m) == 0) msgput(m); @@ -829,7 +865,7 @@ inputthread(void *arg) free(pkt); continue; } - if((nn = convM2S(pkt, n, &m->rx)) != n){ + if((nn = convM2Su(pkt, n, &m->rx, dotu)) != n){ fprint(2, "%T bad packet - convM2S %d but %d\n", nn, n); free(pkt); msgput(m); @@ -918,6 +954,7 @@ fidnew(int cfid) freefid = f->next; f->cfid = cfid; f->ref = 1; + f->isdir = -1; return f; } @@ -1168,7 +1205,7 @@ read9ppkt(Ioproc *io, int fd) } Msg* -mread9p(Ioproc *io, int fd) +mread9p(Ioproc *io, int fd, int dotu) { int n, nn; uchar *pkt; @@ -1180,7 +1217,7 @@ mread9p(Ioproc *io, int fd) m = msgnew(0); m->tpkt = pkt; n = GBIT32(pkt); - nn = convM2S(pkt, n, &m->tx); + nn = convM2Su(pkt, n, &m->tx, dotu); if(nn != n){ fprint(2, "%T read bad packet from %d\n", fd); return nil; @@ -1225,20 +1262,20 @@ restring(uchar *pkt, int pn, char *s) } void -repack(Fcall *f, uchar **ppkt) +repack(Fcall *f, uchar **ppkt, int dotu) { uint n, nn; uchar *pkt; pkt = *ppkt; n = GBIT32(pkt); - nn = sizeS2M(f); + nn = sizeS2Mu(f, dotu); if(nn > n){ free(pkt); pkt = emalloc(nn); *ppkt = pkt; } - convS2M(f, pkt, nn); + convS2Mu(f, pkt, nn, dotu); } void @@ -1337,3 +1374,86 @@ timefmt(Fmt *fmt) mon[tm.mon], tm.mday, tm.hour, tm.min, tm.sec, (int)(ns%1000000000)/1000000); } + +int +stripustat(Fcall *f, uchar **fpkt, int s2u) +{ + int n; + char *buf; + char *str; + Dir dir; + + str = emalloc(f->nstat); + n = convM2Du(f->stat, f->nstat, &dir, str, s2u); + if(n <= BIT16SZ) + return -1; + n = sizeD2Mu(&dir, !s2u); + buf = emalloc(n); + + n = convD2Mu(&dir, buf, n, !s2u); + if(n <= BIT16SZ) + return -1; + f->nstat = n; + f->stat = buf; + + repack(f, fpkt, dotu); + free(buf); + free(str); + + return 0; +} + +int +stripudirread(Msg* msg) +{ + int i, m, n, nn; + char *buf, *str; + Dir d; + Fcall* rx; + + buf = nil; + str = nil; + rx = &msg->rx; + n = 0; + nn = 0; + for(i = 0; i < rx->count; i += m){ + m = BIT16SZ + GBIT16(&rx->data[i]); + if(statchecku(&rx->data[i], m, 1) < 0) + return -1; + if(nn < m) + nn = m; + n++; + } + + str = emalloc(nn); + buf = emalloc(rx->count); + + nn = 0; + for(i = 0; i < rx->count; i += m){ + m = BIT16SZ + GBIT16(&rx->data[i]); + if(convM2Du(&rx->data[i], m, &d, str, 1) != m){ + free(buf); + free(str); + return -1; + } + + n = convD2M(&d, &buf[nn], rx->count - nn); + if(n <= BIT16SZ){ + free(buf); + free(str); + return -1; + } + + nn += n; + } + + rx->count = nn; + rx->data = buf; + + repack(&msg->rx, &msg->rpkt, 0); + free(str); + free(buf); + + return 0; +} + |