19a747e4fSDavid du Colombier #include <u.h> 29a747e4fSDavid du Colombier #include <libc.h> 39a747e4fSDavid du Colombier #include <auth.h> 49a747e4fSDavid du Colombier #include <fcall.h> 5*6b6b9ac8SDavid 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 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 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 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 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 * 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 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; 3739a747e4fSDavid du Colombier rendezvous(r.tag, (ulong)msg); 3749a747e4fSDavid du Colombier } 3759a747e4fSDavid du Colombier } 3769a747e4fSDavid du Colombier 3779a747e4fSDavid du Colombier 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 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 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 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 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 5189a747e4fSDavid du Colombier msg = (Message*)rendezvous(tag, 0); 5199a747e4fSDavid du Colombier if((ulong)msg == ~0UL) 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* 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* 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; 5809a747e4fSDavid du Colombier rendezvous(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* 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* 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 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* 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* 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* 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* 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* 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* 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* 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* 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* 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* 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* 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 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* 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 * 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 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