19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <auth.h>
49a747e4fSDavid du Colombier #include <fcall.h>
56b6b9ac8SDavid du Colombier #include <libsec.h>
69a747e4fSDavid du Colombier #include "9p1.h"
79a747e4fSDavid du Colombier
89a747e4fSDavid du Colombier char *user;
99a747e4fSDavid du Colombier int newfd;
109a747e4fSDavid du Colombier int roldfd;
119a747e4fSDavid du Colombier int woldfd;
129a747e4fSDavid du Colombier int debug;
139a747e4fSDavid du Colombier int dofcall;
149a747e4fSDavid du Colombier QLock servelock;
159a747e4fSDavid du Colombier QLock fidlock;
169a747e4fSDavid du Colombier QLock taglock;
179a747e4fSDavid du Colombier int mainpid;
189a747e4fSDavid du Colombier int ntag;
199a747e4fSDavid du Colombier int nfork;
209a747e4fSDavid du Colombier char FLUSHED[] = "FLUSHED";
219a747e4fSDavid du Colombier
229a747e4fSDavid du Colombier enum{
239a747e4fSDavid du Colombier Maxfdata = 8192
249a747e4fSDavid du Colombier };
259a747e4fSDavid du Colombier
269a747e4fSDavid du Colombier enum{
279a747e4fSDavid du Colombier Command,
289a747e4fSDavid du Colombier Network,
299a747e4fSDavid du Colombier File,
309a747e4fSDavid du Colombier Stdio,
319a747e4fSDavid du Colombier };
329a747e4fSDavid du Colombier
339a747e4fSDavid du Colombier typedef struct Tag Tag;
349a747e4fSDavid du Colombier struct Tag
359a747e4fSDavid du Colombier {
369a747e4fSDavid du Colombier int tag;
379a747e4fSDavid du Colombier int flushed;
389a747e4fSDavid du Colombier int received;
399a747e4fSDavid du Colombier int ref;
409a747e4fSDavid du Colombier Tag *next;
419a747e4fSDavid du Colombier };
429a747e4fSDavid du Colombier
439a747e4fSDavid du Colombier typedef struct Message Message;
449a747e4fSDavid du Colombier struct Message
459a747e4fSDavid du Colombier {
469a747e4fSDavid du Colombier char *data;
479a747e4fSDavid du Colombier int n;
489a747e4fSDavid du Colombier };
499a747e4fSDavid du Colombier
509a747e4fSDavid du Colombier typedef struct Fid Fid;
519a747e4fSDavid du Colombier
529a747e4fSDavid du Colombier struct Fid
539a747e4fSDavid du Colombier {
549a747e4fSDavid du Colombier short busy;
559a747e4fSDavid du Colombier short allocated;
569a747e4fSDavid du Colombier int fid;
579a747e4fSDavid du Colombier Qid qid;
589a747e4fSDavid du Colombier ulong newoffset;
599a747e4fSDavid du Colombier ulong oldoffset;
609a747e4fSDavid du Colombier Fid *next;
619a747e4fSDavid du Colombier };
629a747e4fSDavid du Colombier
639a747e4fSDavid du Colombier Fid *fids;
649a747e4fSDavid du Colombier Tag *tags;
659a747e4fSDavid du Colombier
669a747e4fSDavid du Colombier char *rflush(Fcall*, Fcall*, char*),
679a747e4fSDavid du Colombier *rversion(Fcall*, Fcall*, char*),
689a747e4fSDavid du Colombier *rauth(Fcall*, Fcall*, char*),
699a747e4fSDavid du Colombier *rattach(Fcall*, Fcall*, char*),
709a747e4fSDavid du Colombier *rwalk(Fcall*, Fcall*, char*),
719a747e4fSDavid du Colombier *ropen(Fcall*, Fcall*, char*),
729a747e4fSDavid du Colombier *rcreate(Fcall*, Fcall*, char*),
739a747e4fSDavid du Colombier *rread(Fcall*, Fcall*, char*),
749a747e4fSDavid du Colombier *rwrite(Fcall*, Fcall*, char*),
759a747e4fSDavid du Colombier *rclunk(Fcall*, Fcall*, char*),
769a747e4fSDavid du Colombier *rremove(Fcall*, Fcall*, char*),
779a747e4fSDavid du Colombier *rstat(Fcall*, Fcall*, char*),
789a747e4fSDavid du Colombier *rwstat(Fcall*, Fcall*, char*);
799a747e4fSDavid du Colombier
809a747e4fSDavid du Colombier char *(*fcalls[])(Fcall*, Fcall*, char*) = {
819a747e4fSDavid du Colombier [Tversion] rversion,
829a747e4fSDavid du Colombier [Tflush] rflush,
839a747e4fSDavid du Colombier [Tauth] rauth,
849a747e4fSDavid du Colombier [Tattach] rattach,
859a747e4fSDavid du Colombier [Twalk] rwalk,
869a747e4fSDavid du Colombier [Topen] ropen,
879a747e4fSDavid du Colombier [Tcreate] rcreate,
889a747e4fSDavid du Colombier [Tread] rread,
899a747e4fSDavid du Colombier [Twrite] rwrite,
909a747e4fSDavid du Colombier [Tclunk] rclunk,
919a747e4fSDavid du Colombier [Tremove] rremove,
929a747e4fSDavid du Colombier [Tstat] rstat,
939a747e4fSDavid du Colombier [Twstat] rwstat,
949a747e4fSDavid du Colombier };
959a747e4fSDavid du Colombier
969a747e4fSDavid du Colombier char Etoolong[] = "name too long";
979a747e4fSDavid du Colombier
989a747e4fSDavid du Colombier void connect(int, char*);
999a747e4fSDavid du Colombier void post(int, char*);
1009a747e4fSDavid du Colombier void serve(void);
1019a747e4fSDavid du Colombier void demux(void);
1029a747e4fSDavid du Colombier void* emalloc(ulong);
1039a747e4fSDavid du Colombier char* transact9p1(Fcall9p1*, Fcall9p1*, char*);
1049a747e4fSDavid du Colombier Fid* newfid(int);
1059a747e4fSDavid du Colombier
1069a747e4fSDavid du Colombier struct
1079a747e4fSDavid du Colombier {
1089a747e4fSDavid du Colombier char chal[CHALLEN]; /* my challenge */
1099a747e4fSDavid du Colombier char rchal[CHALLEN]; /* his challenge */
1109a747e4fSDavid du Colombier char authid[NAMEREC];
1119a747e4fSDavid du Colombier char authdom[DOMLEN];
1129a747e4fSDavid du Colombier int id;
1139a747e4fSDavid du Colombier } ai;
1149a747e4fSDavid du Colombier
1159a747e4fSDavid du Colombier void
usage(void)1169a747e4fSDavid du Colombier usage(void)
1179a747e4fSDavid du Colombier {
1189a747e4fSDavid du Colombier fprint(2, "usage: srvold9p [-abcCd] [-u user] [-s | [-m mountpoint]] [-x 'command' | -n network-addr | -f file] [-F] [-p servicename]\n");
1199a747e4fSDavid du Colombier exits("usage");
1209a747e4fSDavid du Colombier }
1219a747e4fSDavid du Colombier
1229a747e4fSDavid du Colombier void
main(int argc,char * argv[])1239a747e4fSDavid du Colombier main(int argc, char *argv[])
1249a747e4fSDavid du Colombier {
1259a747e4fSDavid du Colombier int method;
1269a747e4fSDavid du Colombier char *oldstring;
1279a747e4fSDavid du Colombier char *mountpoint, *postname;
1289a747e4fSDavid du Colombier int mountflag, mountfd;
1299a747e4fSDavid du Colombier int p[2];
1309a747e4fSDavid du Colombier int i;
1319a747e4fSDavid du Colombier
1329a747e4fSDavid du Colombier fmtinstall('F', fcallfmt);
1339a747e4fSDavid du Colombier fmtinstall('G', fcallfmt9p1);
1349a747e4fSDavid du Colombier fmtinstall('D', dirfmt);
1359a747e4fSDavid du Colombier
1369a747e4fSDavid du Colombier user = getuser();
1379a747e4fSDavid du Colombier mountpoint = nil;
1389a747e4fSDavid du Colombier mountflag = 0;
1399a747e4fSDavid du Colombier postname = nil;
1409a747e4fSDavid du Colombier oldstring = nil;
1419a747e4fSDavid du Colombier method = -1;
1429a747e4fSDavid du Colombier mountfd = -1;
1439a747e4fSDavid du Colombier
1449a747e4fSDavid du Colombier ARGBEGIN{
1459a747e4fSDavid du Colombier case 'a':
1469a747e4fSDavid du Colombier mountflag |= MAFTER;
1479a747e4fSDavid du Colombier break;
1489a747e4fSDavid du Colombier case 'b':
1499a747e4fSDavid du Colombier mountflag |= MBEFORE;
1509a747e4fSDavid du Colombier break;
1519a747e4fSDavid du Colombier case 'c':
1529a747e4fSDavid du Colombier mountflag |= MCREATE;
1539a747e4fSDavid du Colombier break;
1549a747e4fSDavid du Colombier case 'C':
1559a747e4fSDavid du Colombier mountflag |= MCACHE;
1569a747e4fSDavid du Colombier break;
1579a747e4fSDavid du Colombier case 'd':
1589a747e4fSDavid du Colombier debug++;
1599a747e4fSDavid du Colombier break;
1609a747e4fSDavid du Colombier case 'f':
1619a747e4fSDavid du Colombier method = File;
1629a747e4fSDavid du Colombier oldstring = ARGF();
1639a747e4fSDavid du Colombier break;
1649a747e4fSDavid du Colombier case 'F':
1659a747e4fSDavid du Colombier dofcall++;
1669a747e4fSDavid du Colombier break;
1679a747e4fSDavid du Colombier case 'm':
1689a747e4fSDavid du Colombier mountpoint = EARGF(usage());
1699a747e4fSDavid du Colombier break;
1709a747e4fSDavid du Colombier case 'n':
1719a747e4fSDavid du Colombier method = Network;
1729a747e4fSDavid du Colombier oldstring = ARGF();
1739a747e4fSDavid du Colombier break;
1749a747e4fSDavid du Colombier case 'p':
1759a747e4fSDavid du Colombier postname = ARGF();
1769a747e4fSDavid du Colombier if(postname == nil)
1779a747e4fSDavid du Colombier usage();
1789a747e4fSDavid du Colombier break;
1799a747e4fSDavid du Colombier case 's':
1809a747e4fSDavid du Colombier method = Stdio;
1819a747e4fSDavid du Colombier break;
1829a747e4fSDavid du Colombier case 'u':
1839a747e4fSDavid du Colombier user = EARGF(usage());
1849a747e4fSDavid du Colombier break;
1859a747e4fSDavid du Colombier case 'x':
1869a747e4fSDavid du Colombier method = Command;
1879a747e4fSDavid du Colombier oldstring = ARGF();
1889a747e4fSDavid du Colombier break;
1899a747e4fSDavid du Colombier default:
1909a747e4fSDavid du Colombier usage();
1919a747e4fSDavid du Colombier }ARGEND;
1929a747e4fSDavid du Colombier
1939a747e4fSDavid du Colombier if(method == Stdio){
1949a747e4fSDavid du Colombier if(mountpoint!=nil || argc!=0)
1959a747e4fSDavid du Colombier usage();
1969a747e4fSDavid du Colombier }else{
1979a747e4fSDavid du Colombier if(oldstring == nil || argc != 0 || (mountflag!=0 && mountpoint==nil))
1989a747e4fSDavid du Colombier usage();
1999a747e4fSDavid du Colombier }
2009a747e4fSDavid du Colombier
2019a747e4fSDavid du Colombier rfork(RFNOTEG|RFREND);
2029a747e4fSDavid du Colombier
2039a747e4fSDavid du Colombier connect(method, oldstring);
2049a747e4fSDavid du Colombier
2059a747e4fSDavid du Colombier if(method == Stdio)
2069a747e4fSDavid du Colombier newfd = 0;
2079a747e4fSDavid du Colombier else{
2089a747e4fSDavid du Colombier if(pipe(p) < 0)
2099a747e4fSDavid du Colombier fatal("pipe: %r");
2109a747e4fSDavid du Colombier if(postname != nil)
2119a747e4fSDavid du Colombier post(p[0], postname);
2129a747e4fSDavid du Colombier mountfd = p[0];
2139a747e4fSDavid du Colombier newfd = p[1];
2149a747e4fSDavid du Colombier }
2159a747e4fSDavid du Colombier if(debug)
2169a747e4fSDavid du Colombier fprint(2, "connected and posted\n");
2179a747e4fSDavid du Colombier
2189a747e4fSDavid du Colombier switch(rfork(RFPROC|RFMEM|RFNAMEG|RFFDG)){
2199a747e4fSDavid du Colombier case 0:
2209a747e4fSDavid du Colombier mainpid = getpid();
2219a747e4fSDavid du Colombier /* child does all the work */
2229a747e4fSDavid du Colombier if(mountfd >= 0)
2239a747e4fSDavid du Colombier close(mountfd);
2249a747e4fSDavid du Colombier switch(rfork(RFPROC|RFMEM|RFFDG)){
2259a747e4fSDavid du Colombier case 0:
2269a747e4fSDavid du Colombier for(i = 0; i < 20; i++)
2279a747e4fSDavid du Colombier if (i != roldfd) close(i);
2289a747e4fSDavid du Colombier demux();
2299a747e4fSDavid du Colombier return;
2309a747e4fSDavid du Colombier case -1:
2319a747e4fSDavid du Colombier fatal("fork error: %r");
2329a747e4fSDavid du Colombier break;
2339a747e4fSDavid du Colombier }
2349a747e4fSDavid du Colombier for(i = 0; i < 20; i++)
2359a747e4fSDavid du Colombier if (i != newfd && i != woldfd && (debug == 0 || i != 2)) close(i);
2369a747e4fSDavid du Colombier serve();
2379a747e4fSDavid du Colombier break;
2389a747e4fSDavid du Colombier case -1:
2399a747e4fSDavid du Colombier fatal("fork error: %r");
2409a747e4fSDavid du Colombier break;
2419a747e4fSDavid du Colombier default:
2429a747e4fSDavid du Colombier /* parent mounts if required, then exits */
2439a747e4fSDavid du Colombier if(mountpoint){
2449a747e4fSDavid du Colombier if(mount(mountfd, -1, mountpoint, mountflag, "") < 0)
2459a747e4fSDavid du Colombier fatal("can't mount: %r");
2469a747e4fSDavid du Colombier }
2479a747e4fSDavid du Colombier break;
2489a747e4fSDavid du Colombier }
2499a747e4fSDavid du Colombier exits(nil);
2509a747e4fSDavid du Colombier }
2519a747e4fSDavid du Colombier
2529a747e4fSDavid du Colombier void
connect(int method,char * oldstring)2539a747e4fSDavid du Colombier connect(int method, char *oldstring)
2549a747e4fSDavid du Colombier {
2559a747e4fSDavid du Colombier char *s;
2569a747e4fSDavid du Colombier char dir[256];
2579a747e4fSDavid du Colombier
2589a747e4fSDavid du Colombier switch(method){
2599a747e4fSDavid du Colombier default:
2609a747e4fSDavid du Colombier roldfd = -1;
2619a747e4fSDavid du Colombier woldfd = -1;
2629a747e4fSDavid du Colombier fatal("can't handle method type %d", method);
2639a747e4fSDavid du Colombier break;
2649a747e4fSDavid du Colombier case Network:
2659a747e4fSDavid du Colombier s = netmkaddr(oldstring, 0, "9fs");
2669a747e4fSDavid du Colombier roldfd = dial(s, 0, dir, 0);
2679a747e4fSDavid du Colombier if(roldfd < 0)
2689a747e4fSDavid du Colombier fatal("dial %s: %r", s);
2699a747e4fSDavid du Colombier woldfd = roldfd;
2709a747e4fSDavid du Colombier if(dofcall)
2719a747e4fSDavid du Colombier roldfd = fcall(woldfd);
2729a747e4fSDavid du Colombier break;
2739a747e4fSDavid du Colombier case File:
2749a747e4fSDavid du Colombier roldfd = open(oldstring, ORDWR);
2759a747e4fSDavid du Colombier if(roldfd < 0)
2769a747e4fSDavid du Colombier fatal("can't open %s: %r", oldstring);
2779a747e4fSDavid du Colombier woldfd = roldfd;
2789a747e4fSDavid du Colombier if(dofcall)
2799a747e4fSDavid du Colombier roldfd = fcall(woldfd);
2809a747e4fSDavid du Colombier break;
2819a747e4fSDavid du Colombier case Stdio:
2829a747e4fSDavid du Colombier roldfd = fcall(1);
2839a747e4fSDavid du Colombier woldfd = 1;
2849a747e4fSDavid du Colombier break;
2859a747e4fSDavid du Colombier }
2869a747e4fSDavid du Colombier }
2879a747e4fSDavid du Colombier
2889a747e4fSDavid du Colombier void
post(int fd,char * srv)2899a747e4fSDavid du Colombier post(int fd, char *srv)
2909a747e4fSDavid du Colombier {
2919a747e4fSDavid du Colombier int f;
2929a747e4fSDavid du Colombier char buf[128];
2939a747e4fSDavid du Colombier
2949a747e4fSDavid du Colombier snprint(buf, sizeof buf, "/srv/%s", srv);
2959a747e4fSDavid du Colombier f = create(buf, OWRITE, 0666);
2969a747e4fSDavid du Colombier if(f < 0)
2979a747e4fSDavid du Colombier fatal("can't create %s: %r", buf);
2989a747e4fSDavid du Colombier sprint(buf, "%d", fd);
2999a747e4fSDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf))
3009a747e4fSDavid du Colombier fatal("post write: %r");
3019a747e4fSDavid du Colombier close(f);
3029a747e4fSDavid du Colombier }
3039a747e4fSDavid du Colombier
3049a747e4fSDavid du Colombier Fid *
newfid(int fid)3059a747e4fSDavid du Colombier newfid(int fid)
3069a747e4fSDavid du Colombier {
3079a747e4fSDavid du Colombier Fid *f, *ff;
3089a747e4fSDavid du Colombier
3099a747e4fSDavid du Colombier ff = 0;
3109a747e4fSDavid du Colombier qlock(&fidlock);
3119a747e4fSDavid du Colombier for(f = fids; f; f = f->next)
3129a747e4fSDavid du Colombier if(f->fid == fid){
3139a747e4fSDavid du Colombier f->allocated = 1;
3149a747e4fSDavid du Colombier qunlock(&fidlock);
3159a747e4fSDavid du Colombier return f;
3169a747e4fSDavid du Colombier }
3179a747e4fSDavid du Colombier else if(!ff && !f->allocated)
3189a747e4fSDavid du Colombier ff = f;
3199a747e4fSDavid du Colombier if(ff){
3209a747e4fSDavid du Colombier ff->fid = fid;
3219a747e4fSDavid du Colombier ff->allocated = 1;
3229a747e4fSDavid du Colombier qunlock(&fidlock);
3239a747e4fSDavid du Colombier return ff;
3249a747e4fSDavid du Colombier }
3259a747e4fSDavid du Colombier f = emalloc(sizeof *f);
3269a747e4fSDavid du Colombier f->fid = fid;
3279a747e4fSDavid du Colombier f->next = fids;
3289a747e4fSDavid du Colombier f->allocated = 1;
3299a747e4fSDavid du Colombier fids = f;
3309a747e4fSDavid du Colombier qunlock(&fidlock);
3319a747e4fSDavid du Colombier return f;
3329a747e4fSDavid du Colombier }
3339a747e4fSDavid du Colombier
3349a747e4fSDavid du Colombier /*
3359a747e4fSDavid du Colombier * Reads returning 9P1 messages and demultiplexes them.
3369a747e4fSDavid du Colombier * BUG: assumes one read per message.
3379a747e4fSDavid du Colombier */
3389a747e4fSDavid du Colombier void
demux(void)3399a747e4fSDavid du Colombier demux(void)
3409a747e4fSDavid du Colombier {
3419a747e4fSDavid du Colombier int m, n;
3429a747e4fSDavid du Colombier char *data;
3439a747e4fSDavid du Colombier Fcall9p1 r;
3449a747e4fSDavid du Colombier Message *msg;
3459a747e4fSDavid du Colombier Tag *t;
3469a747e4fSDavid du Colombier
3479a747e4fSDavid du Colombier for(;;){
3489a747e4fSDavid du Colombier data = malloc(IOHDRSZ+Maxfdata); /* no need to clear memory */
3499a747e4fSDavid du Colombier if(data == nil)
3509a747e4fSDavid du Colombier fatal("demux malloc: %r");
3519a747e4fSDavid du Colombier m = read(roldfd, data, IOHDRSZ+Maxfdata);
3529a747e4fSDavid du Colombier if(m <= 0)
3539a747e4fSDavid du Colombier fatal("read error talking to old system: %r");
3549a747e4fSDavid du Colombier n = convM2S9p1(data, &r, m);
3559a747e4fSDavid du Colombier if(n == 0)
3569a747e4fSDavid du Colombier fatal("bad conversion receiving from old system");
3579a747e4fSDavid du Colombier if(debug)
3589a747e4fSDavid du Colombier fprint(2, "srvold9p:<=%G\n", &r);
3599a747e4fSDavid du Colombier qlock(&taglock);
3609a747e4fSDavid du Colombier for(t=tags; t!=nil; t=t->next)
3619a747e4fSDavid du Colombier if(t->tag == r.tag){
3629a747e4fSDavid du Colombier t->received = 1;
3639a747e4fSDavid du Colombier break;
3649a747e4fSDavid du Colombier }
3659a747e4fSDavid du Colombier qunlock(&taglock);
3669a747e4fSDavid du Colombier /*
3679a747e4fSDavid du Colombier * Fcall9p1 tag is used to rendezvous.
3689a747e4fSDavid du Colombier * Recipient converts message a second time, but that's OK.
3699a747e4fSDavid du Colombier */
3709a747e4fSDavid du Colombier msg = emalloc(sizeof(Message));
3719a747e4fSDavid du Colombier msg->data = data;
3729a747e4fSDavid du Colombier msg->n = n;
373*74f16c81SDavid du Colombier rendezvous((void*)r.tag, msg);
3749a747e4fSDavid du Colombier }
3759a747e4fSDavid du Colombier }
3769a747e4fSDavid du Colombier
3779a747e4fSDavid du Colombier Tag*
newtag(int tag)3789a747e4fSDavid du Colombier newtag(int tag)
3799a747e4fSDavid du Colombier {
3809a747e4fSDavid du Colombier Tag *t;
3819a747e4fSDavid du Colombier
3829a747e4fSDavid du Colombier t = emalloc(sizeof(Tag));
3839a747e4fSDavid du Colombier t->tag = tag;
3849a747e4fSDavid du Colombier t->flushed = 0;
3859a747e4fSDavid du Colombier t->received = 0;
3869a747e4fSDavid du Colombier t->ref = 1;
3879a747e4fSDavid du Colombier qlock(&taglock);
3889a747e4fSDavid du Colombier t->next = tags;
3899a747e4fSDavid du Colombier tags = t;
3909a747e4fSDavid du Colombier qunlock(&taglock);
3919a747e4fSDavid du Colombier return t;
3929a747e4fSDavid du Colombier }
3939a747e4fSDavid du Colombier
3949a747e4fSDavid du Colombier void
freetag(Tag * tag)3959a747e4fSDavid du Colombier freetag(Tag *tag) /* called with taglock set */
3969a747e4fSDavid du Colombier {
3979a747e4fSDavid du Colombier Tag *t, *prev;
3989a747e4fSDavid du Colombier
3999a747e4fSDavid du Colombier if(tag->ref-- == 1){
4009a747e4fSDavid du Colombier prev = nil;
4019a747e4fSDavid du Colombier for(t=tags; t!=nil; t=t->next){
4029a747e4fSDavid du Colombier if(t == tag){
4039a747e4fSDavid du Colombier if(prev == nil)
4049a747e4fSDavid du Colombier tags = t->next;
4059a747e4fSDavid du Colombier else
4069a747e4fSDavid du Colombier prev->next = t->next;
4079a747e4fSDavid du Colombier break;
4089a747e4fSDavid du Colombier }
4099a747e4fSDavid du Colombier prev = t;
4109a747e4fSDavid du Colombier }
4119a747e4fSDavid du Colombier if(t == nil)
4129a747e4fSDavid du Colombier sysfatal("freetag");
4139a747e4fSDavid du Colombier free(tag);
4149a747e4fSDavid du Colombier }
4159a747e4fSDavid du Colombier }
4169a747e4fSDavid du Colombier
4179a747e4fSDavid du Colombier void
serve(void)4189a747e4fSDavid du Colombier serve(void)
4199a747e4fSDavid du Colombier {
4209a747e4fSDavid du Colombier char *err;
4219a747e4fSDavid du Colombier int n;
4229a747e4fSDavid du Colombier Fcall thdr;
4239a747e4fSDavid du Colombier Fcall rhdr;
4249a747e4fSDavid du Colombier uchar mdata[IOHDRSZ+Maxfdata];
4259a747e4fSDavid du Colombier char mdata9p1[IOHDRSZ+Maxfdata];
4269a747e4fSDavid du Colombier Tag *tag;
4279a747e4fSDavid du Colombier
4289a747e4fSDavid du Colombier for(;;){
4299a747e4fSDavid du Colombier qlock(&servelock);
4309a747e4fSDavid du Colombier for(;;){
4319a747e4fSDavid du Colombier n = read9pmsg(newfd, mdata, sizeof mdata);
4329a747e4fSDavid du Colombier
4339a747e4fSDavid du Colombier if(n == 0)
4349a747e4fSDavid du Colombier continue;
4359a747e4fSDavid du Colombier if(n < 0)
4369a747e4fSDavid du Colombier break;
4379a747e4fSDavid du Colombier if(n > 0 && convM2S(mdata, n, &thdr) > 0)
4389a747e4fSDavid du Colombier break;
4399a747e4fSDavid du Colombier }
4409a747e4fSDavid du Colombier if(n>0 && servelock.head==nil) /* no other processes waiting to read */
4419a747e4fSDavid du Colombier switch(rfork(RFPROC|RFMEM)){
4429a747e4fSDavid du Colombier case 0:
4439a747e4fSDavid du Colombier /* child starts serving */
4449a747e4fSDavid du Colombier continue;
4459a747e4fSDavid du Colombier break;
4469a747e4fSDavid du Colombier case -1:
4479a747e4fSDavid du Colombier fatal("fork error: %r");
4489a747e4fSDavid du Colombier break;
4499a747e4fSDavid du Colombier default:
4509a747e4fSDavid du Colombier break;
4519a747e4fSDavid du Colombier }
4529a747e4fSDavid du Colombier qunlock(&servelock);
4539a747e4fSDavid du Colombier
4549a747e4fSDavid du Colombier if(n < 0)
4559a747e4fSDavid du Colombier fatal(nil); /* exit quietly; remote end has just hung up */
4569a747e4fSDavid du Colombier
4579a747e4fSDavid du Colombier if(debug)
4589a747e4fSDavid du Colombier fprint(2, "srvold9p:<-%F\n", &thdr);
4599a747e4fSDavid du Colombier
4609a747e4fSDavid du Colombier tag = newtag(thdr.tag);
4619a747e4fSDavid du Colombier
4629a747e4fSDavid du Colombier if(!fcalls[thdr.type])
4639a747e4fSDavid du Colombier err = "bad fcall type";
4649a747e4fSDavid du Colombier else
4659a747e4fSDavid du Colombier err = (*fcalls[thdr.type])(&thdr, &rhdr, mdata9p1);
4669a747e4fSDavid du Colombier
4679a747e4fSDavid du Colombier qlock(&taglock);
4689a747e4fSDavid du Colombier if(tag->flushed){
4699a747e4fSDavid du Colombier freetag(tag);
4709a747e4fSDavid du Colombier qunlock(&taglock);
4719a747e4fSDavid du Colombier continue;
4729a747e4fSDavid du Colombier }
4739a747e4fSDavid du Colombier qunlock(&taglock);
4749a747e4fSDavid du Colombier
4759a747e4fSDavid du Colombier if(err){
4769a747e4fSDavid du Colombier rhdr.type = Rerror;
4779a747e4fSDavid du Colombier rhdr.ename = err;
4789a747e4fSDavid du Colombier }else{
4799a747e4fSDavid du Colombier rhdr.type = thdr.type + 1;
4809a747e4fSDavid du Colombier rhdr.fid = thdr.fid;
4819a747e4fSDavid du Colombier }
4829a747e4fSDavid du Colombier rhdr.tag = thdr.tag;
4839a747e4fSDavid du Colombier if(debug)
4849a747e4fSDavid du Colombier fprint(2, "srvold9p:->%F\n", &rhdr);/**/
4859a747e4fSDavid du Colombier n = convS2M(&rhdr, mdata, sizeof mdata);
4869a747e4fSDavid du Colombier if(n == 0)
4879a747e4fSDavid du Colombier fatal("convS2M error on write");
4889a747e4fSDavid du Colombier if(write(newfd, mdata, n) != n)
4899a747e4fSDavid du Colombier fatal("mount write");
4909a747e4fSDavid du Colombier
4919a747e4fSDavid du Colombier qlock(&taglock);
4929a747e4fSDavid du Colombier freetag(tag);
4939a747e4fSDavid du Colombier qunlock(&taglock);
4949a747e4fSDavid du Colombier }
4959a747e4fSDavid du Colombier }
4969a747e4fSDavid du Colombier
4979a747e4fSDavid du Colombier void
send9p1(Fcall9p1 * t,char * data)4989a747e4fSDavid du Colombier send9p1(Fcall9p1 *t, char *data)
4999a747e4fSDavid du Colombier {
5009a747e4fSDavid du Colombier int m, n;
5019a747e4fSDavid du Colombier
5029a747e4fSDavid du Colombier if(debug)
5039a747e4fSDavid du Colombier fprint(2, "srvold9p:=>%G\n", t);
5049a747e4fSDavid du Colombier n = convS2M9p1(t, data);
5059a747e4fSDavid du Colombier if(n == 0)
5069a747e4fSDavid du Colombier fatal("bad conversion sending to old system");
5079a747e4fSDavid du Colombier m = write(woldfd, data, n);
5089a747e4fSDavid du Colombier if(m != n)
5099a747e4fSDavid du Colombier fatal("wrote %d to old system; should be %d", m, n);
5109a747e4fSDavid du Colombier }
5119a747e4fSDavid du Colombier
5129a747e4fSDavid du Colombier int
recv9p1(Fcall9p1 * r,int tag,char * data)5139a747e4fSDavid du Colombier recv9p1(Fcall9p1 *r, int tag, char *data)
5149a747e4fSDavid du Colombier {
5159a747e4fSDavid du Colombier int n;
5169a747e4fSDavid du Colombier Message *msg;
5179a747e4fSDavid du Colombier
518*74f16c81SDavid du Colombier msg = rendezvous((void*)tag, 0);
519*74f16c81SDavid du Colombier if(msg == (void*)~0)
5209a747e4fSDavid du Colombier fatal("rendezvous: %r");
5219a747e4fSDavid du Colombier if(msg == nil){
5229a747e4fSDavid du Colombier if(debug)
5239a747e4fSDavid du Colombier fprint(2, "recv flushed\n");
5249a747e4fSDavid du Colombier return -1;
5259a747e4fSDavid du Colombier }
5269a747e4fSDavid du Colombier /* copy data to local buffer */
5279a747e4fSDavid du Colombier memmove(data, msg->data, msg->n);
5289a747e4fSDavid du Colombier n = convM2S9p1(data, r, msg->n);
5299a747e4fSDavid du Colombier if(n == 0)
5309a747e4fSDavid du Colombier fatal("bad conversion receiving from old system");
5319a747e4fSDavid du Colombier free(msg->data);
5329a747e4fSDavid du Colombier free(msg);
5339a747e4fSDavid du Colombier return 1;
5349a747e4fSDavid du Colombier }
5359a747e4fSDavid du Colombier
5369a747e4fSDavid du Colombier char*
transact9p1(Fcall9p1 * t,Fcall9p1 * r,char * mdata9p1)5379a747e4fSDavid du Colombier transact9p1(Fcall9p1 *t, Fcall9p1 *r, char *mdata9p1)
5389a747e4fSDavid du Colombier {
5399a747e4fSDavid du Colombier send9p1(t, mdata9p1);
5409a747e4fSDavid du Colombier if(recv9p1(r, t->tag, mdata9p1) < 0)
5419a747e4fSDavid du Colombier return FLUSHED;
5429a747e4fSDavid du Colombier if(r->type == Rerror9p1)
5439a747e4fSDavid du Colombier return r->ename;
5449a747e4fSDavid du Colombier if(r->type != t->type+1)
5459a747e4fSDavid du Colombier fatal("bad message type; expected %d got %d", t->type+1, r->type);
5469a747e4fSDavid du Colombier return nil;
5479a747e4fSDavid du Colombier }
5489a747e4fSDavid du Colombier
5499a747e4fSDavid du Colombier char*
rflush(Fcall * t,Fcall *,char * mdata9p1)5509a747e4fSDavid du Colombier rflush(Fcall *t, Fcall *, char *mdata9p1)
5519a747e4fSDavid du Colombier {
5529a747e4fSDavid du Colombier Fcall9p1 t9, r9;
5539a747e4fSDavid du Colombier Tag *oldt;
5549a747e4fSDavid du Colombier
5559a747e4fSDavid du Colombier t9.type = Tflush9p1;
5569a747e4fSDavid du Colombier t9.tag = t->tag;
5579a747e4fSDavid du Colombier t9.oldtag = t->oldtag;
5589a747e4fSDavid du Colombier qlock(&taglock);
5599a747e4fSDavid du Colombier for(oldt=tags; oldt!=nil; oldt=oldt->next)
5609a747e4fSDavid du Colombier if(oldt->tag == t->oldtag){
5619a747e4fSDavid du Colombier oldt->flushed = 1;
5629a747e4fSDavid du Colombier oldt->ref++;
5639a747e4fSDavid du Colombier break;
5649a747e4fSDavid du Colombier }
5659a747e4fSDavid du Colombier qunlock(&taglock);
5669a747e4fSDavid du Colombier
5679a747e4fSDavid du Colombier if(oldt == nil){ /* nothing to flush */
5689a747e4fSDavid du Colombier if(debug)
5699a747e4fSDavid du Colombier fprint(2, "no such tag to flush\n");
5709a747e4fSDavid du Colombier return 0;
5719a747e4fSDavid du Colombier }
5729a747e4fSDavid du Colombier
5739a747e4fSDavid du Colombier transact9p1(&t9, &r9, mdata9p1); /* can't error */
5749a747e4fSDavid du Colombier
5759a747e4fSDavid du Colombier qlock(&taglock);
5769a747e4fSDavid du Colombier if(oldt->received == 0){ /* wake up receiver */
5779a747e4fSDavid du Colombier if(debug)
5789a747e4fSDavid du Colombier fprint(2, "wake up receiver\n");
5799a747e4fSDavid du Colombier oldt->received = 1;
580*74f16c81SDavid du Colombier rendezvous((void*)t->oldtag, 0);
5819a747e4fSDavid du Colombier }
5829a747e4fSDavid du Colombier freetag(oldt);
5839a747e4fSDavid du Colombier qunlock(&taglock);
5849a747e4fSDavid du Colombier return 0;
5859a747e4fSDavid du Colombier }
5869a747e4fSDavid du Colombier
5879a747e4fSDavid du Colombier char*
rversion(Fcall * t,Fcall * r,char *)5889a747e4fSDavid du Colombier rversion(Fcall *t, Fcall *r, char*)
5899a747e4fSDavid du Colombier {
5909a747e4fSDavid du Colombier Fid *f;
5919a747e4fSDavid du Colombier
5929a747e4fSDavid du Colombier /* just ack; this one doesn't go to old service */
5939a747e4fSDavid du Colombier if(t->msize > IOHDRSZ+Maxfdata)
5949a747e4fSDavid du Colombier r->msize = IOHDRSZ+Maxfdata;
5959a747e4fSDavid du Colombier else
5969a747e4fSDavid du Colombier r->msize = t->msize;
5979a747e4fSDavid du Colombier if(strncmp(t->version, "9P2000", 6) != 0)
5989a747e4fSDavid du Colombier return "unknown 9P version";
5999a747e4fSDavid du Colombier r->version = "9P2000";
6009a747e4fSDavid du Colombier
6019a747e4fSDavid du Colombier qlock(&fidlock);
6029a747e4fSDavid du Colombier for(f = fids; f; f = f->next){
6039a747e4fSDavid du Colombier f->busy = 0;
6049a747e4fSDavid du Colombier f->allocated = 0;
6059a747e4fSDavid du Colombier }
6069a747e4fSDavid du Colombier qunlock(&fidlock);
6079a747e4fSDavid du Colombier
6089a747e4fSDavid du Colombier return 0;
6099a747e4fSDavid du Colombier }
6109a747e4fSDavid du Colombier
6119a747e4fSDavid du Colombier char*
rauth(Fcall *,Fcall *,char *)6129a747e4fSDavid du Colombier rauth(Fcall *, Fcall *, char *)
6139a747e4fSDavid du Colombier {
6149a747e4fSDavid du Colombier return "srvold9p: authentication not supported";
6159a747e4fSDavid du Colombier }
6169a747e4fSDavid du Colombier
6179a747e4fSDavid du Colombier #ifdef asdf
6189a747e4fSDavid du Colombier
6199a747e4fSDavid du Colombier void
memrandom(void * p,int n)6209a747e4fSDavid du Colombier memrandom(void *p, int n)
6219a747e4fSDavid du Colombier {
6229a747e4fSDavid du Colombier ulong *lp;
6239a747e4fSDavid du Colombier uchar *cp;
6249a747e4fSDavid du Colombier
6259a747e4fSDavid du Colombier for(lp = p; n >= sizeof(ulong); n -= sizeof(ulong))
6269a747e4fSDavid du Colombier *lp++ = fastrand();
6279a747e4fSDavid du Colombier for(cp = (uchar*)lp; n > 0; n--)
6289a747e4fSDavid du Colombier *cp++ = fastrand();
6299a747e4fSDavid du Colombier }
6309a747e4fSDavid du Colombier
6319a747e4fSDavid du Colombier char*
rsession(Fcall * t,Fcall * r,char * mdata9p1)6329a747e4fSDavid du Colombier rsession(Fcall *t, Fcall *r, char *mdata9p1)
6339a747e4fSDavid du Colombier {
6349a747e4fSDavid du Colombier char *err;
6359a747e4fSDavid du Colombier Fcall9p1 t9, r9;
6369a747e4fSDavid du Colombier Fid *f;
6379a747e4fSDavid du Colombier
6389a747e4fSDavid du Colombier t9.type = Tsession9p1;
6399a747e4fSDavid du Colombier t9.tag = t->tag;
6409a747e4fSDavid du Colombier if(doauth)
6419a747e4fSDavid du Colombier memrandom(t9.chal, sizeof t9.chal);
6429a747e4fSDavid du Colombier else
6439a747e4fSDavid du Colombier memset(t9.chal, 0, sizeof t9.chal);
6449a747e4fSDavid du Colombier err = transact9p1(&t9, &r9, mdata9p1);
6459a747e4fSDavid du Colombier if(err)
6469a747e4fSDavid du Colombier return err;
6479a747e4fSDavid du Colombier
6489a747e4fSDavid du Colombier qlock(&fidlock);
6499a747e4fSDavid du Colombier for(f = fids; f; f = f->next){
6509a747e4fSDavid du Colombier f->busy = 0;
6519a747e4fSDavid du Colombier f->allocated = 0;
6529a747e4fSDavid du Colombier }
6539a747e4fSDavid du Colombier qunlock(&fidlock);
6549a747e4fSDavid du Colombier
6559a747e4fSDavid du Colombier if(doauth){
6569a747e4fSDavid du Colombier memmove(ai.authid, r9.authid, sizeof ai.authid);
6579a747e4fSDavid du Colombier memmove(ai.authdom, r9.authdom, sizeof ai.authid);
6589a747e4fSDavid du Colombier memmove(ai.rchal, r9.chal, sizeof ai.rchal);
6599a747e4fSDavid du Colombier memmove(ai.chal, t9.chal, sizeof ai.chal);
6609a747e4fSDavid du Colombier r->authid = ai.authid;
6619a747e4fSDavid du Colombier r->authdom = ai.authdom;
6629a747e4fSDavid du Colombier r->chal = (uchar*)ai.rchal;
6639a747e4fSDavid du Colombier r->nchal = CHALLEN;
6649a747e4fSDavid du Colombier } else {
6659a747e4fSDavid du Colombier r->authid = "";
6669a747e4fSDavid du Colombier r->authdom = "";
6679a747e4fSDavid du Colombier r->nchal = 0;
6689a747e4fSDavid du Colombier r->chal = nil;
6699a747e4fSDavid du Colombier }
6709a747e4fSDavid du Colombier return 0;
6719a747e4fSDavid du Colombier }
6729a747e4fSDavid du Colombier #endif
6739a747e4fSDavid du Colombier
6749a747e4fSDavid du Colombier char*
rattach(Fcall * t,Fcall * r,char * mdata9p1)6759a747e4fSDavid du Colombier rattach(Fcall *t, Fcall *r, char *mdata9p1)
6769a747e4fSDavid du Colombier {
6779a747e4fSDavid du Colombier char *err;
6789a747e4fSDavid du Colombier Fcall9p1 t9, r9;
6799a747e4fSDavid du Colombier Fid *f;
6809a747e4fSDavid du Colombier
6819a747e4fSDavid du Colombier f = newfid(t->fid);
6829a747e4fSDavid du Colombier if(f->busy)
6839a747e4fSDavid du Colombier return "attach: fid in use";
6849a747e4fSDavid du Colombier /* no authentication! */
6859a747e4fSDavid du Colombier t9.type = Tattach9p1;
6869a747e4fSDavid du Colombier t9.tag = t->tag;
6879a747e4fSDavid du Colombier t9.fid = t->fid;
6889a747e4fSDavid du Colombier strncpy(t9.uname, t->uname, NAMEREC);
6899a747e4fSDavid du Colombier if(strcmp(user, "none") == 0)
6909a747e4fSDavid du Colombier strncpy(t9.uname, user, NAMEREC);
6919a747e4fSDavid du Colombier strncpy(t9.aname, t->aname, NAMEREC);
6929a747e4fSDavid du Colombier memset(t9.ticket, 0, sizeof t9.ticket);
6939a747e4fSDavid du Colombier memset(t9.auth, 0, sizeof t9.auth);
6949a747e4fSDavid du Colombier err = transact9p1(&t9, &r9, mdata9p1);
6959a747e4fSDavid du Colombier if(err)
6969a747e4fSDavid du Colombier return err;
6979a747e4fSDavid du Colombier
6989a747e4fSDavid du Colombier r->qid.path = r9.qid.path & ~0x80000000;
6999a747e4fSDavid du Colombier r->qid.vers = r9.qid.version;
7009a747e4fSDavid du Colombier r->qid.type = QTDIR;
7019a747e4fSDavid du Colombier f->busy = 1;
7029a747e4fSDavid du Colombier f->qid = r->qid;
7039a747e4fSDavid du Colombier return 0;
7049a747e4fSDavid du Colombier }
7059a747e4fSDavid du Colombier
7069a747e4fSDavid du Colombier char*
rwalk(Fcall * t,Fcall * r,char * mdata9p1)7079a747e4fSDavid du Colombier rwalk(Fcall *t, Fcall *r, char *mdata9p1)
7089a747e4fSDavid du Colombier {
7099a747e4fSDavid du Colombier char *err;
7109a747e4fSDavid du Colombier Fcall9p1 t9, r9;
7119a747e4fSDavid du Colombier int i, fid;
7129a747e4fSDavid du Colombier Qid *q;
7139a747e4fSDavid du Colombier Fid *f, *nf;
7149a747e4fSDavid du Colombier
7159a747e4fSDavid du Colombier f = newfid(t->fid);
7169a747e4fSDavid du Colombier if(!f->busy)
7179a747e4fSDavid du Colombier return "walk: bad fid";
7189a747e4fSDavid du Colombier
7199a747e4fSDavid du Colombier fid = t->fid;
7209a747e4fSDavid du Colombier nf = nil;
7219a747e4fSDavid du Colombier if(t->fid != t->newfid){
7229a747e4fSDavid du Colombier nf = newfid(t->newfid);
7239a747e4fSDavid du Colombier if(nf->busy)
7249a747e4fSDavid du Colombier return "walk: newfid in use";
7259a747e4fSDavid du Colombier t9.type = Tclone9p1;
7269a747e4fSDavid du Colombier t9.tag = t->tag;
7279a747e4fSDavid du Colombier t9.fid = t->fid;
7289a747e4fSDavid du Colombier t9.newfid = t->newfid;
7299a747e4fSDavid du Colombier err = transact9p1(&t9, &r9, mdata9p1);
7309a747e4fSDavid du Colombier if(err){
7319a747e4fSDavid du Colombier nf->busy = 0;
7329a747e4fSDavid du Colombier nf->allocated = 0;
7339a747e4fSDavid du Colombier return err;
7349a747e4fSDavid du Colombier }
7359a747e4fSDavid du Colombier fid = t->newfid;
7369a747e4fSDavid du Colombier nf->busy = 1;
7379a747e4fSDavid du Colombier }
7389a747e4fSDavid du Colombier
7399a747e4fSDavid du Colombier err = nil;
7409a747e4fSDavid du Colombier r->nwqid = 0;
7419a747e4fSDavid du Colombier for(i=0; i<t->nwname && err==nil; i++){
7429a747e4fSDavid du Colombier if(i > MAXWELEM)
7439a747e4fSDavid du Colombier break;
7449a747e4fSDavid du Colombier t9.type = Twalk9p1;
7459a747e4fSDavid du Colombier t9.tag = t->tag;
7469a747e4fSDavid du Colombier t9.fid = fid;
7479a747e4fSDavid du Colombier strncpy(t9.name, t->wname[i], NAMEREC);
7489a747e4fSDavid du Colombier err = transact9p1(&t9, &r9, mdata9p1);
7499a747e4fSDavid du Colombier if(err == FLUSHED){
7509a747e4fSDavid du Colombier i = -1; /* guarantee cleanup */
7519a747e4fSDavid du Colombier break;
7529a747e4fSDavid du Colombier }
7539a747e4fSDavid du Colombier if(err == nil){
7549a747e4fSDavid du Colombier q = &r->wqid[r->nwqid++];
7559a747e4fSDavid du Colombier q->type = QTFILE;
7569a747e4fSDavid du Colombier if(r9.qid.path & 0x80000000)
7579a747e4fSDavid du Colombier q->type = QTDIR;
7589a747e4fSDavid du Colombier q->vers = r9.qid.version;
7599a747e4fSDavid du Colombier q->path = r9.qid.path & ~0x80000000;
7609a747e4fSDavid du Colombier }
7619a747e4fSDavid du Colombier }
7629a747e4fSDavid du Colombier
7639a747e4fSDavid du Colombier if(nf!=nil && (err!=nil || i<t->nwname)){
7649a747e4fSDavid du Colombier /* clunk the new fid */
7659a747e4fSDavid du Colombier t9.type = Tclunk9p1;
7669a747e4fSDavid du Colombier t9.tag = t->tag;
7679a747e4fSDavid du Colombier t9.fid = t->newfid;
7689a747e4fSDavid du Colombier transact9p1(&t9, &r9, mdata9p1);
7699a747e4fSDavid du Colombier /* ignore more errors */
7709a747e4fSDavid du Colombier nf->busy = 0;
7719a747e4fSDavid du Colombier nf->allocated = 0;
7729a747e4fSDavid du Colombier }
7739a747e4fSDavid du Colombier
7749a747e4fSDavid du Colombier if(i>0 && i==t->nwname && err==nil)
7759a747e4fSDavid du Colombier f->qid = r->wqid[r->nwqid-1];
7769a747e4fSDavid du Colombier if(i > 0)
7779a747e4fSDavid du Colombier return 0;
7789a747e4fSDavid du Colombier return err;
7799a747e4fSDavid du Colombier }
7809a747e4fSDavid du Colombier
7819a747e4fSDavid du Colombier char*
ropen(Fcall * t,Fcall * r,char * mdata9p1)7829a747e4fSDavid du Colombier ropen(Fcall *t, Fcall *r, char *mdata9p1)
7839a747e4fSDavid du Colombier {
7849a747e4fSDavid du Colombier char *err;
7859a747e4fSDavid du Colombier Fcall9p1 t9, r9;
7869a747e4fSDavid du Colombier Fid *f;
7879a747e4fSDavid du Colombier
7889a747e4fSDavid du Colombier f = newfid(t->fid);
7899a747e4fSDavid du Colombier if(!f->busy)
7909a747e4fSDavid du Colombier return "open: bad fid";
7919a747e4fSDavid du Colombier
7929a747e4fSDavid du Colombier t9.type = Topen9p1;
7939a747e4fSDavid du Colombier t9.tag = t->tag;
7949a747e4fSDavid du Colombier t9.fid = t->fid;
7959a747e4fSDavid du Colombier t9.mode = t->mode;
7969a747e4fSDavid du Colombier err = transact9p1(&t9, &r9, mdata9p1);
7979a747e4fSDavid du Colombier if(err)
7989a747e4fSDavid du Colombier return err;
7999a747e4fSDavid du Colombier
8009a747e4fSDavid du Colombier r->qid.path = r9.qid.path & ~0x80000000;
8019a747e4fSDavid du Colombier r->qid.vers = r9.qid.version;
8029a747e4fSDavid du Colombier r->qid.type = QTFILE;
8039a747e4fSDavid du Colombier if(r9.qid.path & 0x80000000)
8049a747e4fSDavid du Colombier r->qid.type = QTDIR;
8059a747e4fSDavid du Colombier f->qid = r->qid;
8069a747e4fSDavid du Colombier f->newoffset = 0;
8079a747e4fSDavid du Colombier f->oldoffset = 0;
8089a747e4fSDavid du Colombier r->iounit = 0;
8099a747e4fSDavid du Colombier return 0;
8109a747e4fSDavid du Colombier }
8119a747e4fSDavid du Colombier
8129a747e4fSDavid du Colombier char*
rcreate(Fcall * t,Fcall * r,char * mdata9p1)8139a747e4fSDavid du Colombier rcreate(Fcall *t, Fcall *r, char *mdata9p1)
8149a747e4fSDavid du Colombier {
8159a747e4fSDavid du Colombier char *err;
8169a747e4fSDavid du Colombier Fcall9p1 t9, r9;
8179a747e4fSDavid du Colombier Fid *f;
8189a747e4fSDavid du Colombier
8199a747e4fSDavid du Colombier f = newfid(t->fid);
8209a747e4fSDavid du Colombier if(!f->busy)
8219a747e4fSDavid du Colombier return "create: bad fid";
8229a747e4fSDavid du Colombier
8239a747e4fSDavid du Colombier t9.type = Tcreate9p1;
8249a747e4fSDavid du Colombier t9.tag = t->tag;
8259a747e4fSDavid du Colombier t9.fid = t->fid;
8269a747e4fSDavid du Colombier if(strlen(t->name)+1 >= NAMEREC)
8279a747e4fSDavid du Colombier return "file name element too long";
8289a747e4fSDavid du Colombier strncpy(t9.name, t->name, NAMEREC);
8299a747e4fSDavid du Colombier t9.perm = t->perm;
8309a747e4fSDavid du Colombier t9.mode = t->mode;
8319a747e4fSDavid du Colombier err = transact9p1(&t9, &r9, mdata9p1);
8329a747e4fSDavid du Colombier if(err)
8339a747e4fSDavid du Colombier return err;
8349a747e4fSDavid du Colombier
8359a747e4fSDavid du Colombier r->qid.path = r9.qid.path & ~0x80000000;
8369a747e4fSDavid du Colombier r->qid.vers = r9.qid.version;
8379a747e4fSDavid du Colombier r->qid.type = QTFILE;
8389a747e4fSDavid du Colombier if(r9.qid.path & 0x80000000)
8399a747e4fSDavid du Colombier r->qid.type = QTDIR;
8409a747e4fSDavid du Colombier if(r9.qid.path & 0x40000000)
8419a747e4fSDavid du Colombier r->qid.type |= QTAPPEND;
8429a747e4fSDavid du Colombier if(r9.qid.path & 0x20000000)
8439a747e4fSDavid du Colombier r->qid.type |= QTEXCL;
8449a747e4fSDavid du Colombier f->qid = r->qid;
8459a747e4fSDavid du Colombier r->iounit = 0;
8469a747e4fSDavid du Colombier return 0;
8479a747e4fSDavid du Colombier }
8489a747e4fSDavid du Colombier
8499a747e4fSDavid du Colombier char*
dirrread(Fcall * t,Fcall * r,char * mdata9p1)8509a747e4fSDavid du Colombier dirrread(Fcall *t, Fcall *r, char *mdata9p1)
8519a747e4fSDavid du Colombier {
8529a747e4fSDavid du Colombier char *err;
8539a747e4fSDavid du Colombier Fcall9p1 t9, r9;
8549a747e4fSDavid du Colombier Fid *f;
8559a747e4fSDavid du Colombier int i, ndir, n, count;
8569a747e4fSDavid du Colombier Dir d;
8579a747e4fSDavid du Colombier uchar buf[Maxfdata];
8589a747e4fSDavid du Colombier char *old;
8599a747e4fSDavid du Colombier
8609a747e4fSDavid du Colombier f = newfid(t->fid);
8619a747e4fSDavid du Colombier if(!f->busy)
8629a747e4fSDavid du Colombier return "dirread: bad fid";
8639a747e4fSDavid du Colombier
8649a747e4fSDavid du Colombier if(f->newoffset != t->offset)
8659a747e4fSDavid du Colombier return "seek in directory disallowed";
8669a747e4fSDavid du Colombier
8679a747e4fSDavid du Colombier t9.type = Tread9p1;
8689a747e4fSDavid du Colombier t9.tag = t->tag;
8699a747e4fSDavid du Colombier t9.fid = t->fid;
8709a747e4fSDavid du Colombier t9.offset = f->oldoffset;
8719a747e4fSDavid du Colombier t9.count = t->count; /* new directories tend to be smaller, so this may overshoot */
8729a747e4fSDavid du Colombier err = transact9p1(&t9, &r9, mdata9p1);
8739a747e4fSDavid du Colombier if(err)
8749a747e4fSDavid du Colombier return err;
8759a747e4fSDavid du Colombier
8769a747e4fSDavid du Colombier ndir = r9.count/DIRREC;
8779a747e4fSDavid du Colombier old = r9.data;
8789a747e4fSDavid du Colombier count = 0;
8799a747e4fSDavid du Colombier for(i=0; i<ndir; i++){
8809a747e4fSDavid du Colombier if(convM2D9p1(old, &d) != DIRREC)
8819a747e4fSDavid du Colombier return "bad dir conversion in read";
8829a747e4fSDavid du Colombier n = convD2M(&d, buf+count, sizeof buf-count);
8839a747e4fSDavid du Colombier if(n<=BIT16SZ || count+n>t->count)
8849a747e4fSDavid du Colombier break;
8859a747e4fSDavid du Colombier old += DIRREC;
8869a747e4fSDavid du Colombier f->oldoffset += DIRREC;
8879a747e4fSDavid du Colombier f->newoffset += n;
8889a747e4fSDavid du Colombier count += n;
8899a747e4fSDavid du Colombier }
8909a747e4fSDavid du Colombier memmove(r9.data, buf, count); /* put it back in stable storage */
8919a747e4fSDavid du Colombier r->data = r9.data;
8929a747e4fSDavid du Colombier r->count = count;
8939a747e4fSDavid du Colombier return 0;
8949a747e4fSDavid du Colombier }
8959a747e4fSDavid du Colombier
8969a747e4fSDavid du Colombier char*
rread(Fcall * t,Fcall * r,char * mdata9p1)8979a747e4fSDavid du Colombier rread(Fcall *t, Fcall *r, char *mdata9p1)
8989a747e4fSDavid du Colombier {
8999a747e4fSDavid du Colombier char *err;
9009a747e4fSDavid du Colombier Fcall9p1 t9, r9;
9019a747e4fSDavid du Colombier Fid *f;
9029a747e4fSDavid du Colombier
9039a747e4fSDavid du Colombier f = newfid(t->fid);
9049a747e4fSDavid du Colombier if(!f->busy)
9059a747e4fSDavid du Colombier return "read: bad fid";
9069a747e4fSDavid du Colombier
9079a747e4fSDavid du Colombier if(f->qid.type & QTDIR)
9089a747e4fSDavid du Colombier return dirrread(t, r, mdata9p1);
9099a747e4fSDavid du Colombier
9109a747e4fSDavid du Colombier t9.type = Tread9p1;
9119a747e4fSDavid du Colombier t9.tag = t->tag;
9129a747e4fSDavid du Colombier t9.fid = t->fid;
9139a747e4fSDavid du Colombier t9.offset = t->offset;
9149a747e4fSDavid du Colombier t9.count = t->count;
9159a747e4fSDavid du Colombier err = transact9p1(&t9, &r9, mdata9p1);
9169a747e4fSDavid du Colombier if(err)
9179a747e4fSDavid du Colombier return err;
9189a747e4fSDavid du Colombier
9199a747e4fSDavid du Colombier r->count = r9.count;
9209a747e4fSDavid du Colombier r->data = r9.data; /* points to stable storage */
9219a747e4fSDavid du Colombier return 0;
9229a747e4fSDavid du Colombier }
9239a747e4fSDavid du Colombier
9249a747e4fSDavid du Colombier char*
rwrite(Fcall * t,Fcall * r,char * mdata9p1)9259a747e4fSDavid du Colombier rwrite(Fcall *t, Fcall *r, char *mdata9p1)
9269a747e4fSDavid du Colombier {
9279a747e4fSDavid du Colombier char *err;
9289a747e4fSDavid du Colombier Fcall9p1 t9, r9;
9299a747e4fSDavid du Colombier Fid *f;
9309a747e4fSDavid du Colombier
9319a747e4fSDavid du Colombier f = newfid(t->fid);
9329a747e4fSDavid du Colombier if(!f->busy)
9339a747e4fSDavid du Colombier return "write: bad fid";
9349a747e4fSDavid du Colombier
9359a747e4fSDavid du Colombier t9.type = Twrite9p1;
9369a747e4fSDavid du Colombier t9.tag = t->tag;
9379a747e4fSDavid du Colombier t9.fid = t->fid;
9389a747e4fSDavid du Colombier t9.offset = t->offset;
9399a747e4fSDavid du Colombier t9.count = t->count;
9409a747e4fSDavid du Colombier t9.data = t->data;
9419a747e4fSDavid du Colombier err = transact9p1(&t9, &r9, mdata9p1);
9429a747e4fSDavid du Colombier if(err)
9439a747e4fSDavid du Colombier return err;
9449a747e4fSDavid du Colombier
9459a747e4fSDavid du Colombier r->count = r9.count;
9469a747e4fSDavid du Colombier return 0;
9479a747e4fSDavid du Colombier }
9489a747e4fSDavid du Colombier
9499a747e4fSDavid du Colombier char*
rclunk(Fcall * t,Fcall *,char * mdata9p1)9509a747e4fSDavid du Colombier rclunk(Fcall *t, Fcall *, char *mdata9p1)
9519a747e4fSDavid du Colombier {
9529a747e4fSDavid du Colombier Fcall9p1 t9, r9;
9539a747e4fSDavid du Colombier Fid *f;
9549a747e4fSDavid du Colombier
9559a747e4fSDavid du Colombier f = newfid(t->fid);
9569a747e4fSDavid du Colombier if(!f->busy)
9579a747e4fSDavid du Colombier return "clunk: bad fid";
9589a747e4fSDavid du Colombier t9.type = Tclunk9p1;
9599a747e4fSDavid du Colombier t9.tag = t->tag;
9609a747e4fSDavid du Colombier t9.fid = t->fid;
9619a747e4fSDavid du Colombier transact9p1(&t9, &r9, mdata9p1);
9629a747e4fSDavid du Colombier f->busy = 0;
9639a747e4fSDavid du Colombier f->allocated = 0;
9649a747e4fSDavid du Colombier /* disregard error */
9659a747e4fSDavid du Colombier return 0;
9669a747e4fSDavid du Colombier }
9679a747e4fSDavid du Colombier
9689a747e4fSDavid du Colombier char*
rremove(Fcall * t,Fcall *,char * mdata9p1)9699a747e4fSDavid du Colombier rremove(Fcall *t, Fcall*, char *mdata9p1)
9709a747e4fSDavid du Colombier {
9719a747e4fSDavid du Colombier char *err;
9729a747e4fSDavid du Colombier Fcall9p1 t9, r9;
9739a747e4fSDavid du Colombier Fid *f;
9749a747e4fSDavid du Colombier
9759a747e4fSDavid du Colombier f = newfid(t->fid);
9769a747e4fSDavid du Colombier if(!f->busy)
9779a747e4fSDavid du Colombier return "remove: bad fid";
9789a747e4fSDavid du Colombier t9.type = Tremove9p1;
9799a747e4fSDavid du Colombier t9.tag = t->tag;
9809a747e4fSDavid du Colombier t9.fid = t->fid;
9819a747e4fSDavid du Colombier err = transact9p1(&t9, &r9, mdata9p1);
9829a747e4fSDavid du Colombier f->busy = 0;
9839a747e4fSDavid du Colombier f->allocated = 0;
9849a747e4fSDavid du Colombier return err;
9859a747e4fSDavid du Colombier }
9869a747e4fSDavid du Colombier
9879a747e4fSDavid du Colombier char*
rstat(Fcall * t,Fcall * r,char * mdata9p1)9889a747e4fSDavid du Colombier rstat(Fcall *t, Fcall *r, char *mdata9p1)
9899a747e4fSDavid du Colombier {
9909a747e4fSDavid du Colombier Fcall9p1 t9, r9;
9919a747e4fSDavid du Colombier char *err;
9929a747e4fSDavid du Colombier Fid *f;
9939a747e4fSDavid du Colombier Dir d;
9949a747e4fSDavid du Colombier uchar buf[256]; /* big enough; there's no long names */
9959a747e4fSDavid du Colombier
9969a747e4fSDavid du Colombier f = newfid(t->fid);
9979a747e4fSDavid du Colombier if(!f->busy)
9989a747e4fSDavid du Colombier return "stat: bad fid";
9999a747e4fSDavid du Colombier
10009a747e4fSDavid du Colombier t9.type = Tstat9p1;
10019a747e4fSDavid du Colombier t9.tag = t->tag;
10029a747e4fSDavid du Colombier t9.fid = t->fid;
10039a747e4fSDavid du Colombier err = transact9p1(&t9, &r9, mdata9p1);
10049a747e4fSDavid du Colombier if(err)
10059a747e4fSDavid du Colombier return err;
10069a747e4fSDavid du Colombier
10079a747e4fSDavid du Colombier if(convM2D9p1(r9.stat, &d) != DIRREC)
10089a747e4fSDavid du Colombier return "bad conversion in stat";
10099a747e4fSDavid du Colombier r->stat = buf;
10109a747e4fSDavid du Colombier r->nstat = convD2M(&d, buf, sizeof buf);
10119a747e4fSDavid du Colombier return 0;
10129a747e4fSDavid du Colombier }
10139a747e4fSDavid du Colombier
10149a747e4fSDavid du Colombier int
anydefault(Dir * d)10159a747e4fSDavid du Colombier anydefault(Dir *d)
10169a747e4fSDavid du Colombier {
10179a747e4fSDavid du Colombier if(d->name[0] == '\0')
10189a747e4fSDavid du Colombier return 1;
10199a747e4fSDavid du Colombier if(d->uid[0] == '\0')
10209a747e4fSDavid du Colombier return 1;
10219a747e4fSDavid du Colombier if(d->gid[0] == '\0')
10229a747e4fSDavid du Colombier return 1;
10239a747e4fSDavid du Colombier if(d->mode == ~0)
10249a747e4fSDavid du Colombier return 1;
10259a747e4fSDavid du Colombier if(d->mtime == ~0)
10269a747e4fSDavid du Colombier return 1;
10279a747e4fSDavid du Colombier return 0;
10289a747e4fSDavid du Colombier }
10299a747e4fSDavid du Colombier
10309a747e4fSDavid du Colombier char*
rwstat(Fcall * t,Fcall *,char * mdata9p1)10319a747e4fSDavid du Colombier rwstat(Fcall *t, Fcall *, char *mdata9p1)
10329a747e4fSDavid du Colombier {
10339a747e4fSDavid du Colombier Fcall9p1 t9, r9;
10349a747e4fSDavid du Colombier char strs[DIRREC];
10359a747e4fSDavid du Colombier char *err;
10369a747e4fSDavid du Colombier Fid *f;
10379a747e4fSDavid du Colombier Dir d, cd;
10389a747e4fSDavid du Colombier
10399a747e4fSDavid du Colombier f = newfid(t->fid);
10409a747e4fSDavid du Colombier if(!f->busy)
10419a747e4fSDavid du Colombier return "wstat: bad fid";
10429a747e4fSDavid du Colombier
10439a747e4fSDavid du Colombier convM2D(t->stat, t->nstat, &d, strs);
10449a747e4fSDavid du Colombier cd = d;
10459a747e4fSDavid du Colombier if(anydefault(&d)){
10469a747e4fSDavid du Colombier /* must first stat file so we can copy current values */
10479a747e4fSDavid du Colombier t9.type = Tstat9p1;
10489a747e4fSDavid du Colombier t9.tag = t->tag;
10499a747e4fSDavid du Colombier t9.fid = t->fid;
10509a747e4fSDavid du Colombier err = transact9p1(&t9, &r9, mdata9p1);
10519a747e4fSDavid du Colombier if(err)
10529a747e4fSDavid du Colombier return err;
10539a747e4fSDavid du Colombier if(convM2D9p1(r9.stat, &cd) != DIRREC)
10549a747e4fSDavid du Colombier return "bad in conversion in wstat";
10559a747e4fSDavid du Colombier
10569a747e4fSDavid du Colombier /* fill in default values */
10579a747e4fSDavid du Colombier if(d.name[0] != '\0'){
10589a747e4fSDavid du Colombier if(strlen(d.name) >= NAMEREC)
10599a747e4fSDavid du Colombier return Etoolong;
10609a747e4fSDavid du Colombier cd.name = d.name;
10619a747e4fSDavid du Colombier }
10629a747e4fSDavid du Colombier if(d.uid[0] != '\0'){
10639a747e4fSDavid du Colombier if(strlen(d.uid) >= NAMEREC)
10649a747e4fSDavid du Colombier return Etoolong;
10659a747e4fSDavid du Colombier cd.uid = d.uid;
10669a747e4fSDavid du Colombier }
10679a747e4fSDavid du Colombier if(d.gid[0] != '\0'){
10689a747e4fSDavid du Colombier if(strlen(d.gid) >= NAMEREC)
10699a747e4fSDavid du Colombier return Etoolong;
10709a747e4fSDavid du Colombier cd.gid = d.gid;
10719a747e4fSDavid du Colombier }
10729a747e4fSDavid du Colombier if(d.mode != ~0)
10739a747e4fSDavid du Colombier cd.mode = d.mode;
10749a747e4fSDavid du Colombier if(d.mtime != ~0)
10759a747e4fSDavid du Colombier cd.mtime = d.mtime;
10769a747e4fSDavid du Colombier if(d.length != ~0LL)
10779a747e4fSDavid du Colombier cd.length = d.length;
10789a747e4fSDavid du Colombier }
10799a747e4fSDavid du Colombier
10809a747e4fSDavid du Colombier if(convD2M9p1(&cd, t9.stat) != DIRREC)
10819a747e4fSDavid du Colombier return "bad out conversion in wstat";
10829a747e4fSDavid du Colombier
10839a747e4fSDavid du Colombier t9.type = Twstat9p1;
10849a747e4fSDavid du Colombier t9.tag = t->tag;
10859a747e4fSDavid du Colombier t9.fid = t->fid;
10869a747e4fSDavid du Colombier err = transact9p1(&t9, &r9, mdata9p1);
10879a747e4fSDavid du Colombier if(err)
10889a747e4fSDavid du Colombier return err;
10899a747e4fSDavid du Colombier return 0;
10909a747e4fSDavid du Colombier }
10919a747e4fSDavid du Colombier
10929a747e4fSDavid du Colombier void *
emalloc(ulong n)10939a747e4fSDavid du Colombier emalloc(ulong n)
10949a747e4fSDavid du Colombier {
10959a747e4fSDavid du Colombier void *p;
10969a747e4fSDavid du Colombier
10979a747e4fSDavid du Colombier p = malloc(n);
10989a747e4fSDavid du Colombier if(!p)
10999a747e4fSDavid du Colombier fatal("out of memory: %r");
11009a747e4fSDavid du Colombier memset(p, 0, n);
11019a747e4fSDavid du Colombier return p;
11029a747e4fSDavid du Colombier }
11039a747e4fSDavid du Colombier
11049a747e4fSDavid du Colombier void
fatal(char * fmt,...)11059a747e4fSDavid du Colombier fatal(char *fmt, ...)
11069a747e4fSDavid du Colombier {
11079a747e4fSDavid du Colombier char buf[1024];
11089a747e4fSDavid du Colombier va_list arg;
11099a747e4fSDavid du Colombier
11109a747e4fSDavid du Colombier if(fmt){
11119a747e4fSDavid du Colombier va_start(arg, fmt);
11129a747e4fSDavid du Colombier vseprint(buf, buf+sizeof(buf), fmt, arg);
11139a747e4fSDavid du Colombier va_end(arg);
11149a747e4fSDavid du Colombier fprint(2, "%s: (pid %d) %s\n", argv0, getpid(), buf);
11159a747e4fSDavid du Colombier }else
11169a747e4fSDavid du Colombier buf[0] = '\0';
11179a747e4fSDavid du Colombier if(mainpid){
11189a747e4fSDavid du Colombier /* two hits are sometimes needed */
11199a747e4fSDavid du Colombier postnote(PNGROUP, mainpid, "die1 - from srvold9p");
11209a747e4fSDavid du Colombier postnote(PNGROUP, mainpid, "die2 - from srvold9p");
11219a747e4fSDavid du Colombier }
11229a747e4fSDavid du Colombier exits(buf);
11239a747e4fSDavid du Colombier }
1124