1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123 |
- #include <u.h>
- #include <libc.h>
- #include <auth.h>
- #include <fcall.h>
- #include <libsec.h>
- #include "9p1.h"
- char *user;
- int newfd;
- int roldfd;
- int woldfd;
- int debug;
- int dofcall;
- QLock servelock;
- QLock fidlock;
- QLock taglock;
- int mainpid;
- int ntag;
- int nfork;
- char FLUSHED[] = "FLUSHED";
- enum{
- Maxfdata = 8192
- };
- enum{
- Command,
- Network,
- File,
- Stdio,
- };
- typedef struct Tag Tag;
- struct Tag
- {
- int tag;
- int flushed;
- int received;
- int ref;
- Tag *next;
- };
- typedef struct Message Message;
- struct Message
- {
- char *data;
- int n;
- };
- typedef struct Fid Fid;
- struct Fid
- {
- short busy;
- short allocated;
- int fid;
- Qid qid;
- ulong newoffset;
- ulong oldoffset;
- Fid *next;
- };
- Fid *fids;
- Tag *tags;
- char *rflush(Fcall*, Fcall*, char*),
- *rversion(Fcall*, Fcall*, char*),
- *rauth(Fcall*, Fcall*, char*),
- *rattach(Fcall*, Fcall*, char*),
- *rwalk(Fcall*, Fcall*, char*),
- *ropen(Fcall*, Fcall*, char*),
- *rcreate(Fcall*, Fcall*, char*),
- *rread(Fcall*, Fcall*, char*),
- *rwrite(Fcall*, Fcall*, char*),
- *rclunk(Fcall*, Fcall*, char*),
- *rremove(Fcall*, Fcall*, char*),
- *rstat(Fcall*, Fcall*, char*),
- *rwstat(Fcall*, Fcall*, char*);
- char *(*fcalls[])(Fcall*, Fcall*, char*) = {
- [Tversion] rversion,
- [Tflush] rflush,
- [Tauth] rauth,
- [Tattach] rattach,
- [Twalk] rwalk,
- [Topen] ropen,
- [Tcreate] rcreate,
- [Tread] rread,
- [Twrite] rwrite,
- [Tclunk] rclunk,
- [Tremove] rremove,
- [Tstat] rstat,
- [Twstat] rwstat,
- };
- char Etoolong[] = "name too long";
- void connect(int, char*);
- void post(int, char*);
- void serve(void);
- void demux(void);
- void* emalloc(ulong);
- char* transact9p1(Fcall9p1*, Fcall9p1*, char*);
- Fid* newfid(int);
- struct
- {
- char chal[CHALLEN]; /* my challenge */
- char rchal[CHALLEN]; /* his challenge */
- char authid[NAMEREC];
- char authdom[DOMLEN];
- int id;
- } ai;
- void
- usage(void)
- {
- fprint(2, "usage: srvold9p [-abcCd] [-u user] [-s | [-m mountpoint]] [-x 'command' | -n network-addr | -f file] [-F] [-p servicename]\n");
- exits("usage");
- }
- void
- main(int argc, char *argv[])
- {
- int method;
- char *oldstring;
- char *mountpoint, *postname;
- int mountflag, mountfd;
- int p[2];
- int i;
- fmtinstall('F', fcallfmt);
- fmtinstall('G', fcallfmt9p1);
- fmtinstall('D', dirfmt);
- user = getuser();
- mountpoint = nil;
- mountflag = 0;
- postname = nil;
- oldstring = nil;
- method = -1;
- mountfd = -1;
- ARGBEGIN{
- case 'a':
- mountflag |= MAFTER;
- break;
- case 'b':
- mountflag |= MBEFORE;
- break;
- case 'c':
- mountflag |= MCREATE;
- break;
- case 'C':
- mountflag |= MCACHE;
- break;
- case 'd':
- debug++;
- break;
- case 'f':
- method = File;
- oldstring = ARGF();
- break;
- case 'F':
- dofcall++;
- break;
- case 'm':
- mountpoint = EARGF(usage());
- break;
- case 'n':
- method = Network;
- oldstring = ARGF();
- break;
- case 'p':
- postname = ARGF();
- if(postname == nil)
- usage();
- break;
- case 's':
- method = Stdio;
- break;
- case 'u':
- user = EARGF(usage());
- break;
- case 'x':
- method = Command;
- oldstring = ARGF();
- break;
- default:
- usage();
- }ARGEND;
- if(method == Stdio){
- if(mountpoint!=nil || argc!=0)
- usage();
- }else{
- if(oldstring == nil || argc != 0 || (mountflag!=0 && mountpoint==nil))
- usage();
- }
- rfork(RFNOTEG|RFREND);
- connect(method, oldstring);
- if(method == Stdio)
- newfd = 0;
- else{
- if(pipe(p) < 0)
- fatal("pipe: %r");
- if(postname != nil)
- post(p[0], postname);
- mountfd = p[0];
- newfd = p[1];
- }
- if(debug)
- fprint(2, "connected and posted\n");
- switch(rfork(RFPROC|RFMEM|RFNAMEG|RFFDG)){
- case 0:
- mainpid = getpid();
- /* child does all the work */
- if(mountfd >= 0)
- close(mountfd);
- switch(rfork(RFPROC|RFMEM|RFFDG)){
- case 0:
- for(i = 0; i < 20; i++)
- if (i != roldfd) close(i);
- demux();
- return;
- case -1:
- fatal("fork error: %r");
- break;
- }
- for(i = 0; i < 20; i++)
- if (i != newfd && i != woldfd && (debug == 0 || i != 2)) close(i);
- serve();
- break;
- case -1:
- fatal("fork error: %r");
- break;
- default:
- /* parent mounts if required, then exits */
- if(mountpoint){
- if(mount(mountfd, -1, mountpoint, mountflag, "") < 0)
- fatal("can't mount: %r");
- }
- break;
- }
- exits(nil);
- }
- void
- connect(int method, char *oldstring)
- {
- char *s;
- char dir[256];
- switch(method){
- default:
- roldfd = -1;
- woldfd = -1;
- fatal("can't handle method type %d", method);
- break;
- case Network:
- s = netmkaddr(oldstring, 0, "9fs");
- roldfd = dial(s, 0, dir, 0);
- if(roldfd < 0)
- fatal("dial %s: %r", s);
- woldfd = roldfd;
- if(dofcall)
- roldfd = fcall(woldfd);
- break;
- case File:
- roldfd = open(oldstring, ORDWR);
- if(roldfd < 0)
- fatal("can't open %s: %r", oldstring);
- woldfd = roldfd;
- if(dofcall)
- roldfd = fcall(woldfd);
- break;
- case Stdio:
- roldfd = fcall(1);
- woldfd = 1;
- break;
- }
- }
- void
- post(int fd, char *srv)
- {
- int f;
- char buf[128];
- snprint(buf, sizeof buf, "/srv/%s", srv);
- f = create(buf, OWRITE, 0666);
- if(f < 0)
- fatal("can't create %s: %r", buf);
- sprint(buf, "%d", fd);
- if(write(f, buf, strlen(buf)) != strlen(buf))
- fatal("post write: %r");
- close(f);
- }
- Fid *
- newfid(int fid)
- {
- Fid *f, *ff;
- ff = 0;
- qlock(&fidlock);
- for(f = fids; f; f = f->next)
- if(f->fid == fid){
- f->allocated = 1;
- qunlock(&fidlock);
- return f;
- }
- else if(!ff && !f->allocated)
- ff = f;
- if(ff){
- ff->fid = fid;
- ff->allocated = 1;
- qunlock(&fidlock);
- return ff;
- }
- f = emalloc(sizeof *f);
- f->fid = fid;
- f->next = fids;
- f->allocated = 1;
- fids = f;
- qunlock(&fidlock);
- return f;
- }
- /*
- * Reads returning 9P1 messages and demultiplexes them.
- * BUG: assumes one read per message.
- */
- void
- demux(void)
- {
- int m, n;
- char *data;
- Fcall9p1 r;
- Message *msg;
- Tag *t;
- for(;;){
- data = malloc(IOHDRSZ+Maxfdata); /* no need to clear memory */
- if(data == nil)
- fatal("demux malloc: %r");
- m = read(roldfd, data, IOHDRSZ+Maxfdata);
- if(m <= 0)
- fatal("read error talking to old system: %r");
- n = convM2S9p1(data, &r, m);
- if(n == 0)
- fatal("bad conversion receiving from old system");
- if(debug)
- fprint(2, "srvold9p:<=%G\n", &r);
- qlock(&taglock);
- for(t=tags; t!=nil; t=t->next)
- if(t->tag == r.tag){
- t->received = 1;
- break;
- }
- qunlock(&taglock);
- /*
- * Fcall9p1 tag is used to rendezvous.
- * Recipient converts message a second time, but that's OK.
- */
- msg = emalloc(sizeof(Message));
- msg->data = data;
- msg->n = n;
- rendezvous(r.tag, (ulong)msg);
- }
- }
- Tag*
- newtag(int tag)
- {
- Tag *t;
- t = emalloc(sizeof(Tag));
- t->tag = tag;
- t->flushed = 0;
- t->received = 0;
- t->ref = 1;
- qlock(&taglock);
- t->next = tags;
- tags = t;
- qunlock(&taglock);
- return t;
- }
- void
- freetag(Tag *tag) /* called with taglock set */
- {
- Tag *t, *prev;
- if(tag->ref-- == 1){
- prev = nil;
- for(t=tags; t!=nil; t=t->next){
- if(t == tag){
- if(prev == nil)
- tags = t->next;
- else
- prev->next = t->next;
- break;
- }
- prev = t;
- }
- if(t == nil)
- sysfatal("freetag");
- free(tag);
- }
- }
- void
- serve(void)
- {
- char *err;
- int n;
- Fcall thdr;
- Fcall rhdr;
- uchar mdata[IOHDRSZ+Maxfdata];
- char mdata9p1[IOHDRSZ+Maxfdata];
- Tag *tag;
- for(;;){
- qlock(&servelock);
- for(;;){
- n = read9pmsg(newfd, mdata, sizeof mdata);
- if(n == 0)
- continue;
- if(n < 0)
- break;
- if(n > 0 && convM2S(mdata, n, &thdr) > 0)
- break;
- }
- if(n>0 && servelock.head==nil) /* no other processes waiting to read */
- switch(rfork(RFPROC|RFMEM)){
- case 0:
- /* child starts serving */
- continue;
- break;
- case -1:
- fatal("fork error: %r");
- break;
- default:
- break;
- }
- qunlock(&servelock);
- if(n < 0)
- fatal(nil); /* exit quietly; remote end has just hung up */
- if(debug)
- fprint(2, "srvold9p:<-%F\n", &thdr);
- tag = newtag(thdr.tag);
- if(!fcalls[thdr.type])
- err = "bad fcall type";
- else
- err = (*fcalls[thdr.type])(&thdr, &rhdr, mdata9p1);
- qlock(&taglock);
- if(tag->flushed){
- freetag(tag);
- qunlock(&taglock);
- continue;
- }
- qunlock(&taglock);
- if(err){
- rhdr.type = Rerror;
- rhdr.ename = err;
- }else{
- rhdr.type = thdr.type + 1;
- rhdr.fid = thdr.fid;
- }
- rhdr.tag = thdr.tag;
- if(debug)
- fprint(2, "srvold9p:->%F\n", &rhdr);/**/
- n = convS2M(&rhdr, mdata, sizeof mdata);
- if(n == 0)
- fatal("convS2M error on write");
- if(write(newfd, mdata, n) != n)
- fatal("mount write");
- qlock(&taglock);
- freetag(tag);
- qunlock(&taglock);
- }
- }
- void
- send9p1(Fcall9p1 *t, char *data)
- {
- int m, n;
- if(debug)
- fprint(2, "srvold9p:=>%G\n", t);
- n = convS2M9p1(t, data);
- if(n == 0)
- fatal("bad conversion sending to old system");
- m = write(woldfd, data, n);
- if(m != n)
- fatal("wrote %d to old system; should be %d", m, n);
- }
- int
- recv9p1(Fcall9p1 *r, int tag, char *data)
- {
- int n;
- Message *msg;
- msg = (Message*)rendezvous(tag, 0);
- if((ulong)msg == ~0UL)
- fatal("rendezvous: %r");
- if(msg == nil){
- if(debug)
- fprint(2, "recv flushed\n");
- return -1;
- }
- /* copy data to local buffer */
- memmove(data, msg->data, msg->n);
- n = convM2S9p1(data, r, msg->n);
- if(n == 0)
- fatal("bad conversion receiving from old system");
- free(msg->data);
- free(msg);
- return 1;
- }
- char*
- transact9p1(Fcall9p1 *t, Fcall9p1 *r, char *mdata9p1)
- {
- send9p1(t, mdata9p1);
- if(recv9p1(r, t->tag, mdata9p1) < 0)
- return FLUSHED;
- if(r->type == Rerror9p1)
- return r->ename;
- if(r->type != t->type+1)
- fatal("bad message type; expected %d got %d", t->type+1, r->type);
- return nil;
- }
- char*
- rflush(Fcall *t, Fcall *, char *mdata9p1)
- {
- Fcall9p1 t9, r9;
- Tag *oldt;
- t9.type = Tflush9p1;
- t9.tag = t->tag;
- t9.oldtag = t->oldtag;
- qlock(&taglock);
- for(oldt=tags; oldt!=nil; oldt=oldt->next)
- if(oldt->tag == t->oldtag){
- oldt->flushed = 1;
- oldt->ref++;
- break;
- }
- qunlock(&taglock);
- if(oldt == nil){ /* nothing to flush */
- if(debug)
- fprint(2, "no such tag to flush\n");
- return 0;
- }
- transact9p1(&t9, &r9, mdata9p1); /* can't error */
- qlock(&taglock);
- if(oldt->received == 0){ /* wake up receiver */
- if(debug)
- fprint(2, "wake up receiver\n");
- oldt->received = 1;
- rendezvous(t->oldtag, 0);
- }
- freetag(oldt);
- qunlock(&taglock);
- return 0;
- }
- char*
- rversion(Fcall *t, Fcall *r, char*)
- {
- Fid *f;
- /* just ack; this one doesn't go to old service */
- if(t->msize > IOHDRSZ+Maxfdata)
- r->msize = IOHDRSZ+Maxfdata;
- else
- r->msize = t->msize;
- if(strncmp(t->version, "9P2000", 6) != 0)
- return "unknown 9P version";
- r->version = "9P2000";
- qlock(&fidlock);
- for(f = fids; f; f = f->next){
- f->busy = 0;
- f->allocated = 0;
- }
- qunlock(&fidlock);
- return 0;
- }
- char*
- rauth(Fcall *, Fcall *, char *)
- {
- return "srvold9p: authentication not supported";
- }
- #ifdef asdf
- void
- memrandom(void *p, int n)
- {
- ulong *lp;
- uchar *cp;
- for(lp = p; n >= sizeof(ulong); n -= sizeof(ulong))
- *lp++ = fastrand();
- for(cp = (uchar*)lp; n > 0; n--)
- *cp++ = fastrand();
- }
- char*
- rsession(Fcall *t, Fcall *r, char *mdata9p1)
- {
- char *err;
- Fcall9p1 t9, r9;
- Fid *f;
- t9.type = Tsession9p1;
- t9.tag = t->tag;
- if(doauth)
- memrandom(t9.chal, sizeof t9.chal);
- else
- memset(t9.chal, 0, sizeof t9.chal);
- err = transact9p1(&t9, &r9, mdata9p1);
- if(err)
- return err;
- qlock(&fidlock);
- for(f = fids; f; f = f->next){
- f->busy = 0;
- f->allocated = 0;
- }
- qunlock(&fidlock);
- if(doauth){
- memmove(ai.authid, r9.authid, sizeof ai.authid);
- memmove(ai.authdom, r9.authdom, sizeof ai.authid);
- memmove(ai.rchal, r9.chal, sizeof ai.rchal);
- memmove(ai.chal, t9.chal, sizeof ai.chal);
- r->authid = ai.authid;
- r->authdom = ai.authdom;
- r->chal = (uchar*)ai.rchal;
- r->nchal = CHALLEN;
- } else {
- r->authid = "";
- r->authdom = "";
- r->nchal = 0;
- r->chal = nil;
- }
- return 0;
- }
- #endif
- char*
- rattach(Fcall *t, Fcall *r, char *mdata9p1)
- {
- char *err;
- Fcall9p1 t9, r9;
- Fid *f;
- f = newfid(t->fid);
- if(f->busy)
- return "attach: fid in use";
- /* no authentication! */
- t9.type = Tattach9p1;
- t9.tag = t->tag;
- t9.fid = t->fid;
- strncpy(t9.uname, t->uname, NAMEREC);
- if(strcmp(user, "none") == 0)
- strncpy(t9.uname, user, NAMEREC);
- strncpy(t9.aname, t->aname, NAMEREC);
- memset(t9.ticket, 0, sizeof t9.ticket);
- memset(t9.auth, 0, sizeof t9.auth);
- err = transact9p1(&t9, &r9, mdata9p1);
- if(err)
- return err;
- r->qid.path = r9.qid.path & ~0x80000000;
- r->qid.vers = r9.qid.version;
- r->qid.type = QTDIR;
- f->busy = 1;
- f->qid = r->qid;
- return 0;
- }
- char*
- rwalk(Fcall *t, Fcall *r, char *mdata9p1)
- {
- char *err;
- Fcall9p1 t9, r9;
- int i, fid;
- Qid *q;
- Fid *f, *nf;
- f = newfid(t->fid);
- if(!f->busy)
- return "walk: bad fid";
- fid = t->fid;
- nf = nil;
- if(t->fid != t->newfid){
- nf = newfid(t->newfid);
- if(nf->busy)
- return "walk: newfid in use";
- t9.type = Tclone9p1;
- t9.tag = t->tag;
- t9.fid = t->fid;
- t9.newfid = t->newfid;
- err = transact9p1(&t9, &r9, mdata9p1);
- if(err){
- nf->busy = 0;
- nf->allocated = 0;
- return err;
- }
- fid = t->newfid;
- nf->busy = 1;
- }
- err = nil;
- r->nwqid = 0;
- for(i=0; i<t->nwname && err==nil; i++){
- if(i > MAXWELEM)
- break;
- t9.type = Twalk9p1;
- t9.tag = t->tag;
- t9.fid = fid;
- strncpy(t9.name, t->wname[i], NAMEREC);
- err = transact9p1(&t9, &r9, mdata9p1);
- if(err == FLUSHED){
- i = -1; /* guarantee cleanup */
- break;
- }
- if(err == nil){
- q = &r->wqid[r->nwqid++];
- q->type = QTFILE;
- if(r9.qid.path & 0x80000000)
- q->type = QTDIR;
- q->vers = r9.qid.version;
- q->path = r9.qid.path & ~0x80000000;
- }
- }
- if(nf!=nil && (err!=nil || i<t->nwname)){
- /* clunk the new fid */
- t9.type = Tclunk9p1;
- t9.tag = t->tag;
- t9.fid = t->newfid;
- transact9p1(&t9, &r9, mdata9p1);
- /* ignore more errors */
- nf->busy = 0;
- nf->allocated = 0;
- }
- if(i>0 && i==t->nwname && err==nil)
- f->qid = r->wqid[r->nwqid-1];
- if(i > 0)
- return 0;
- return err;
- }
- char*
- ropen(Fcall *t, Fcall *r, char *mdata9p1)
- {
- char *err;
- Fcall9p1 t9, r9;
- Fid *f;
- f = newfid(t->fid);
- if(!f->busy)
- return "open: bad fid";
- t9.type = Topen9p1;
- t9.tag = t->tag;
- t9.fid = t->fid;
- t9.mode = t->mode;
- err = transact9p1(&t9, &r9, mdata9p1);
- if(err)
- return err;
- r->qid.path = r9.qid.path & ~0x80000000;
- r->qid.vers = r9.qid.version;
- r->qid.type = QTFILE;
- if(r9.qid.path & 0x80000000)
- r->qid.type = QTDIR;
- f->qid = r->qid;
- f->newoffset = 0;
- f->oldoffset = 0;
- r->iounit = 0;
- return 0;
- }
- char*
- rcreate(Fcall *t, Fcall *r, char *mdata9p1)
- {
- char *err;
- Fcall9p1 t9, r9;
- Fid *f;
- f = newfid(t->fid);
- if(!f->busy)
- return "create: bad fid";
- t9.type = Tcreate9p1;
- t9.tag = t->tag;
- t9.fid = t->fid;
- if(strlen(t->name)+1 >= NAMEREC)
- return "file name element too long";
- strncpy(t9.name, t->name, NAMEREC);
- t9.perm = t->perm;
- t9.mode = t->mode;
- err = transact9p1(&t9, &r9, mdata9p1);
- if(err)
- return err;
- r->qid.path = r9.qid.path & ~0x80000000;
- r->qid.vers = r9.qid.version;
- r->qid.type = QTFILE;
- if(r9.qid.path & 0x80000000)
- r->qid.type = QTDIR;
- if(r9.qid.path & 0x40000000)
- r->qid.type |= QTAPPEND;
- if(r9.qid.path & 0x20000000)
- r->qid.type |= QTEXCL;
- f->qid = r->qid;
- r->iounit = 0;
- return 0;
- }
- char*
- dirrread(Fcall *t, Fcall *r, char *mdata9p1)
- {
- char *err;
- Fcall9p1 t9, r9;
- Fid *f;
- int i, ndir, n, count;
- Dir d;
- uchar buf[Maxfdata];
- char *old;
- f = newfid(t->fid);
- if(!f->busy)
- return "dirread: bad fid";
- if(f->newoffset != t->offset)
- return "seek in directory disallowed";
- t9.type = Tread9p1;
- t9.tag = t->tag;
- t9.fid = t->fid;
- t9.offset = f->oldoffset;
- t9.count = t->count; /* new directories tend to be smaller, so this may overshoot */
- err = transact9p1(&t9, &r9, mdata9p1);
- if(err)
- return err;
- ndir = r9.count/DIRREC;
- old = r9.data;
- count = 0;
- for(i=0; i<ndir; i++){
- if(convM2D9p1(old, &d) != DIRREC)
- return "bad dir conversion in read";
- n = convD2M(&d, buf+count, sizeof buf-count);
- if(n<=BIT16SZ || count+n>t->count)
- break;
- old += DIRREC;
- f->oldoffset += DIRREC;
- f->newoffset += n;
- count += n;
- }
- memmove(r9.data, buf, count); /* put it back in stable storage */
- r->data = r9.data;
- r->count = count;
- return 0;
- }
- char*
- rread(Fcall *t, Fcall *r, char *mdata9p1)
- {
- char *err;
- Fcall9p1 t9, r9;
- Fid *f;
- f = newfid(t->fid);
- if(!f->busy)
- return "read: bad fid";
- if(f->qid.type & QTDIR)
- return dirrread(t, r, mdata9p1);
- t9.type = Tread9p1;
- t9.tag = t->tag;
- t9.fid = t->fid;
- t9.offset = t->offset;
- t9.count = t->count;
- err = transact9p1(&t9, &r9, mdata9p1);
- if(err)
- return err;
- r->count = r9.count;
- r->data = r9.data; /* points to stable storage */
- return 0;
- }
- char*
- rwrite(Fcall *t, Fcall *r, char *mdata9p1)
- {
- char *err;
- Fcall9p1 t9, r9;
- Fid *f;
- f = newfid(t->fid);
- if(!f->busy)
- return "write: bad fid";
- t9.type = Twrite9p1;
- t9.tag = t->tag;
- t9.fid = t->fid;
- t9.offset = t->offset;
- t9.count = t->count;
- t9.data = t->data;
- err = transact9p1(&t9, &r9, mdata9p1);
- if(err)
- return err;
- r->count = r9.count;
- return 0;
- }
- char*
- rclunk(Fcall *t, Fcall *, char *mdata9p1)
- {
- Fcall9p1 t9, r9;
- Fid *f;
- f = newfid(t->fid);
- if(!f->busy)
- return "clunk: bad fid";
- t9.type = Tclunk9p1;
- t9.tag = t->tag;
- t9.fid = t->fid;
- transact9p1(&t9, &r9, mdata9p1);
- f->busy = 0;
- f->allocated = 0;
- /* disregard error */
- return 0;
- }
- char*
- rremove(Fcall *t, Fcall*, char *mdata9p1)
- {
- char *err;
- Fcall9p1 t9, r9;
- Fid *f;
- f = newfid(t->fid);
- if(!f->busy)
- return "remove: bad fid";
- t9.type = Tremove9p1;
- t9.tag = t->tag;
- t9.fid = t->fid;
- err = transact9p1(&t9, &r9, mdata9p1);
- f->busy = 0;
- f->allocated = 0;
- return err;
- }
- char*
- rstat(Fcall *t, Fcall *r, char *mdata9p1)
- {
- Fcall9p1 t9, r9;
- char *err;
- Fid *f;
- Dir d;
- uchar buf[256]; /* big enough; there's no long names */
- f = newfid(t->fid);
- if(!f->busy)
- return "stat: bad fid";
- t9.type = Tstat9p1;
- t9.tag = t->tag;
- t9.fid = t->fid;
- err = transact9p1(&t9, &r9, mdata9p1);
- if(err)
- return err;
- if(convM2D9p1(r9.stat, &d) != DIRREC)
- return "bad conversion in stat";
- r->stat = buf;
- r->nstat = convD2M(&d, buf, sizeof buf);
- return 0;
- }
- int
- anydefault(Dir *d)
- {
- if(d->name[0] == '\0')
- return 1;
- if(d->uid[0] == '\0')
- return 1;
- if(d->gid[0] == '\0')
- return 1;
- if(d->mode == ~0)
- return 1;
- if(d->mtime == ~0)
- return 1;
- return 0;
- }
- char*
- rwstat(Fcall *t, Fcall *, char *mdata9p1)
- {
- Fcall9p1 t9, r9;
- char strs[DIRREC];
- char *err;
- Fid *f;
- Dir d, cd;
- f = newfid(t->fid);
- if(!f->busy)
- return "wstat: bad fid";
- convM2D(t->stat, t->nstat, &d, strs);
- cd = d;
- if(anydefault(&d)){
- /* must first stat file so we can copy current values */
- t9.type = Tstat9p1;
- t9.tag = t->tag;
- t9.fid = t->fid;
- err = transact9p1(&t9, &r9, mdata9p1);
- if(err)
- return err;
- if(convM2D9p1(r9.stat, &cd) != DIRREC)
- return "bad in conversion in wstat";
-
- /* fill in default values */
- if(d.name[0] != '\0'){
- if(strlen(d.name) >= NAMEREC)
- return Etoolong;
- cd.name = d.name;
- }
- if(d.uid[0] != '\0'){
- if(strlen(d.uid) >= NAMEREC)
- return Etoolong;
- cd.uid = d.uid;
- }
- if(d.gid[0] != '\0'){
- if(strlen(d.gid) >= NAMEREC)
- return Etoolong;
- cd.gid = d.gid;
- }
- if(d.mode != ~0)
- cd.mode = d.mode;
- if(d.mtime != ~0)
- cd.mtime = d.mtime;
- if(d.length != ~0LL)
- cd.length = d.length;
- }
- if(convD2M9p1(&cd, t9.stat) != DIRREC)
- return "bad out conversion in wstat";
- t9.type = Twstat9p1;
- t9.tag = t->tag;
- t9.fid = t->fid;
- err = transact9p1(&t9, &r9, mdata9p1);
- if(err)
- return err;
- return 0;
- }
- void *
- emalloc(ulong n)
- {
- void *p;
- p = malloc(n);
- if(!p)
- fatal("out of memory: %r");
- memset(p, 0, n);
- return p;
- }
- void
- fatal(char *fmt, ...)
- {
- char buf[1024];
- va_list arg;
- if(fmt){
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- fprint(2, "%s: (pid %d) %s\n", argv0, getpid(), buf);
- }else
- buf[0] = '\0';
- if(mainpid){
- /* two hits are sometimes needed */
- postnote(PNGROUP, mainpid, "die1 - from srvold9p");
- postnote(PNGROUP, mainpid, "die2 - from srvold9p");
- }
- exits(buf);
- }
|