13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 3219b2ee8SDavid du Colombier #include <auth.h> 43e12c5d1SDavid du Colombier #include <fcall.h> 53e12c5d1SDavid du Colombier 63e12c5d1SDavid du Colombier /* 73e12c5d1SDavid du Colombier * Rather than reading /adm/users, which is a lot of work for 83e12c5d1SDavid du Colombier * a toy program, we assume all groups have the form 93e12c5d1SDavid du Colombier * NNN:user:user: 103e12c5d1SDavid du Colombier * meaning that each user is the leader of his own group. 113e12c5d1SDavid du Colombier */ 123e12c5d1SDavid du Colombier 133e12c5d1SDavid du Colombier enum 143e12c5d1SDavid du Colombier { 153e12c5d1SDavid du Colombier OPERM = 0x3, /* mask of all permission types in open mode */ 166b6b9ac8SDavid du Colombier Nram = 2048, 1746228ac7SDavid du Colombier Maxsize = 768*1024*1024, 189a747e4fSDavid du Colombier Maxfdata = 8192, 193e12c5d1SDavid du Colombier }; 203e12c5d1SDavid du Colombier 213e12c5d1SDavid du Colombier typedef struct Fid Fid; 223e12c5d1SDavid du Colombier typedef struct Ram Ram; 233e12c5d1SDavid du Colombier 243e12c5d1SDavid du Colombier struct Fid 253e12c5d1SDavid du Colombier { 263e12c5d1SDavid du Colombier short busy; 273e12c5d1SDavid du Colombier short open; 283e12c5d1SDavid du Colombier short rclose; 293e12c5d1SDavid du Colombier int fid; 303e12c5d1SDavid du Colombier Fid *next; 313e12c5d1SDavid du Colombier char *user; 323e12c5d1SDavid du Colombier Ram *ram; 333e12c5d1SDavid du Colombier }; 343e12c5d1SDavid du Colombier 353e12c5d1SDavid du Colombier struct Ram 363e12c5d1SDavid du Colombier { 373e12c5d1SDavid du Colombier short busy; 383e12c5d1SDavid du Colombier short open; 393e12c5d1SDavid du Colombier long parent; /* index in Ram array */ 403e12c5d1SDavid du Colombier Qid qid; 413e12c5d1SDavid du Colombier long perm; 429a747e4fSDavid du Colombier char *name; 433e12c5d1SDavid du Colombier ulong atime; 443e12c5d1SDavid du Colombier ulong mtime; 453e12c5d1SDavid du Colombier char *user; 463e12c5d1SDavid du Colombier char *group; 479a747e4fSDavid du Colombier char *muid; 483e12c5d1SDavid du Colombier char *data; 493e12c5d1SDavid du Colombier long ndata; 503e12c5d1SDavid du Colombier }; 513e12c5d1SDavid du Colombier 523e12c5d1SDavid du Colombier enum 533e12c5d1SDavid du Colombier { 543e12c5d1SDavid du Colombier Pexec = 1, 553e12c5d1SDavid du Colombier Pwrite = 2, 563e12c5d1SDavid du Colombier Pread = 4, 573e12c5d1SDavid du Colombier Pother = 1, 583e12c5d1SDavid du Colombier Pgroup = 8, 593e12c5d1SDavid du Colombier Powner = 64, 603e12c5d1SDavid du Colombier }; 613e12c5d1SDavid du Colombier 623e12c5d1SDavid du Colombier ulong path; /* incremented for each new file */ 633e12c5d1SDavid du Colombier Fid *fids; 643e12c5d1SDavid du Colombier Ram ram[Nram]; 653e12c5d1SDavid du Colombier int nram; 663e12c5d1SDavid du Colombier int mfd[2]; 679a747e4fSDavid du Colombier char *user; 689a747e4fSDavid du Colombier uchar mdata[IOHDRSZ+Maxfdata]; 699a747e4fSDavid du Colombier uchar rdata[Maxfdata]; /* buffer for data in reply */ 709a747e4fSDavid du Colombier uchar statbuf[STATMAX]; 713e12c5d1SDavid du Colombier Fcall thdr; 729a747e4fSDavid du Colombier Fcall rhdr; 739a747e4fSDavid du Colombier int messagesize = sizeof mdata; 743e12c5d1SDavid du Colombier 753e12c5d1SDavid du Colombier Fid * newfid(int); 769a747e4fSDavid du Colombier uint ramstat(Ram*, uchar*, uint); 773e12c5d1SDavid du Colombier void error(char*); 783e12c5d1SDavid du Colombier void io(void); 793e12c5d1SDavid du Colombier void *erealloc(void*, ulong); 803e12c5d1SDavid du Colombier void *emalloc(ulong); 819a747e4fSDavid du Colombier char *estrdup(char*); 823e12c5d1SDavid du Colombier void usage(void); 833e12c5d1SDavid du Colombier int perm(Fid*, Ram*, int); 843e12c5d1SDavid du Colombier 859a747e4fSDavid du Colombier char *rflush(Fid*), *rversion(Fid*), *rauth(Fid*), 869a747e4fSDavid du Colombier *rattach(Fid*), *rwalk(Fid*), 879a747e4fSDavid du Colombier *ropen(Fid*), *rcreate(Fid*), 883e12c5d1SDavid du Colombier *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*), 89219b2ee8SDavid du Colombier *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*); 903e12c5d1SDavid du Colombier 919fa41221SDavid du Colombier int needfid[] = { 929fa41221SDavid du Colombier [Tversion] 0, 939fa41221SDavid du Colombier [Tflush] 0, 949fa41221SDavid du Colombier [Tauth] 0, 959fa41221SDavid du Colombier [Tattach] 0, 969fa41221SDavid du Colombier [Twalk] 1, 979fa41221SDavid du Colombier [Topen] 1, 989fa41221SDavid du Colombier [Tcreate] 1, 999fa41221SDavid du Colombier [Tread] 1, 1009fa41221SDavid du Colombier [Twrite] 1, 1019fa41221SDavid du Colombier [Tclunk] 1, 1029fa41221SDavid du Colombier [Tremove] 1, 1039fa41221SDavid du Colombier [Tstat] 1, 1049fa41221SDavid du Colombier [Twstat] 1, 1059fa41221SDavid du Colombier }; 1069fa41221SDavid du Colombier 1073e12c5d1SDavid du Colombier char *(*fcalls[])(Fid*) = { 1089a747e4fSDavid du Colombier [Tversion] rversion, 1093e12c5d1SDavid du Colombier [Tflush] rflush, 1109a747e4fSDavid du Colombier [Tauth] rauth, 1113e12c5d1SDavid du Colombier [Tattach] rattach, 1123e12c5d1SDavid du Colombier [Twalk] rwalk, 1133e12c5d1SDavid du Colombier [Topen] ropen, 1143e12c5d1SDavid du Colombier [Tcreate] rcreate, 1153e12c5d1SDavid du Colombier [Tread] rread, 1163e12c5d1SDavid du Colombier [Twrite] rwrite, 1173e12c5d1SDavid du Colombier [Tclunk] rclunk, 1183e12c5d1SDavid du Colombier [Tremove] rremove, 1193e12c5d1SDavid du Colombier [Tstat] rstat, 1203e12c5d1SDavid du Colombier [Twstat] rwstat, 1213e12c5d1SDavid du Colombier }; 1223e12c5d1SDavid du Colombier 1233e12c5d1SDavid du Colombier char Eperm[] = "permission denied"; 1243e12c5d1SDavid du Colombier char Enotdir[] = "not a directory"; 1253ff48bf5SDavid du Colombier char Enoauth[] = "ramfs: authentication not required"; 1263e12c5d1SDavid du Colombier char Enotexist[] = "file does not exist"; 1273e12c5d1SDavid du Colombier char Einuse[] = "file in use"; 1283e12c5d1SDavid du Colombier char Eexist[] = "file exists"; 1299a747e4fSDavid du Colombier char Eisdir[] = "file is a directory"; 1303e12c5d1SDavid du Colombier char Enotowner[] = "not owner"; 1313e12c5d1SDavid du Colombier char Eisopen[] = "file already open for I/O"; 1323e12c5d1SDavid du Colombier char Excl[] = "exclusive use file already open"; 1333e12c5d1SDavid du Colombier char Ename[] = "illegal name"; 1349a747e4fSDavid du Colombier char Eversion[] = "unknown 9P version"; 135162174bbSDavid du Colombier char Enotempty[] = "directory not empty"; 1363e12c5d1SDavid du Colombier 137219b2ee8SDavid du Colombier int debug; 1389a747e4fSDavid du Colombier int private; 139219b2ee8SDavid du Colombier 1403e12c5d1SDavid du Colombier void 1413e12c5d1SDavid du Colombier notifyf(void *a, char *s) 1423e12c5d1SDavid du Colombier { 1433e12c5d1SDavid du Colombier USED(a); 1443e12c5d1SDavid du Colombier if(strncmp(s, "interrupt", 9) == 0) 1453e12c5d1SDavid du Colombier noted(NCONT); 1463e12c5d1SDavid du Colombier noted(NDFLT); 1473e12c5d1SDavid du Colombier } 1483e12c5d1SDavid du Colombier 1493e12c5d1SDavid du Colombier void 1503e12c5d1SDavid du Colombier main(int argc, char *argv[]) 1513e12c5d1SDavid du Colombier { 1523e12c5d1SDavid du Colombier Ram *r; 1533e12c5d1SDavid du Colombier char *defmnt; 1543e12c5d1SDavid du Colombier int p[2]; 1553e12c5d1SDavid du Colombier int fd; 1563e12c5d1SDavid du Colombier int stdio = 0; 157b7b24591SDavid du Colombier char *service; 1583e12c5d1SDavid du Colombier 159b7b24591SDavid du Colombier service = "ramfs"; 1603e12c5d1SDavid du Colombier defmnt = "/tmp"; 1613e12c5d1SDavid du Colombier ARGBEGIN{ 1629a747e4fSDavid du Colombier case 'D': 163219b2ee8SDavid du Colombier debug = 1; 164219b2ee8SDavid du Colombier break; 1653e12c5d1SDavid du Colombier case 'i': 1663e12c5d1SDavid du Colombier defmnt = 0; 1673e12c5d1SDavid du Colombier stdio = 1; 1683e12c5d1SDavid du Colombier mfd[0] = 0; 1693e12c5d1SDavid du Colombier mfd[1] = 1; 1703e12c5d1SDavid du Colombier break; 1713e12c5d1SDavid du Colombier case 's': 1723e12c5d1SDavid du Colombier defmnt = 0; 1733e12c5d1SDavid du Colombier break; 1743e12c5d1SDavid du Colombier case 'm': 175*ab3dc52fSDavid du Colombier defmnt = EARGF(usage()); 1763e12c5d1SDavid du Colombier break; 1779a747e4fSDavid du Colombier case 'p': 1789a747e4fSDavid du Colombier private++; 1799a747e4fSDavid du Colombier break; 180b7b24591SDavid du Colombier case 'S': 181b7b24591SDavid du Colombier defmnt = 0; 182b7b24591SDavid du Colombier service = EARGF(usage()); 183b7b24591SDavid du Colombier break; 1843e12c5d1SDavid du Colombier default: 1853e12c5d1SDavid du Colombier usage(); 1863e12c5d1SDavid du Colombier }ARGEND 1873e12c5d1SDavid du Colombier 1883e12c5d1SDavid du Colombier if(pipe(p) < 0) 1893e12c5d1SDavid du Colombier error("pipe failed"); 1903e12c5d1SDavid du Colombier if(!stdio){ 1913e12c5d1SDavid du Colombier mfd[0] = p[0]; 1923e12c5d1SDavid du Colombier mfd[1] = p[0]; 1933e12c5d1SDavid du Colombier if(defmnt == 0){ 194b7b24591SDavid du Colombier char buf[64]; 195b7b24591SDavid du Colombier snprint(buf, sizeof buf, "#s/%s", service); 1969fa41221SDavid du Colombier fd = create(buf, OWRITE|ORCLOSE, 0666); 1973e12c5d1SDavid du Colombier if(fd < 0) 198b7b24591SDavid du Colombier error("create failed"); 1993e12c5d1SDavid du Colombier sprint(buf, "%d", p[1]); 2003e12c5d1SDavid du Colombier if(write(fd, buf, strlen(buf)) < 0) 201b7b24591SDavid du Colombier error("writing service file"); 2023e12c5d1SDavid du Colombier } 2033e12c5d1SDavid du Colombier } 2043e12c5d1SDavid du Colombier 2059a747e4fSDavid du Colombier user = getuser(); 2063e12c5d1SDavid du Colombier notify(notifyf); 2073e12c5d1SDavid du Colombier nram = 1; 2083e12c5d1SDavid du Colombier r = &ram[0]; 2093e12c5d1SDavid du Colombier r->busy = 1; 2103e12c5d1SDavid du Colombier r->data = 0; 2113e12c5d1SDavid du Colombier r->ndata = 0; 2129a747e4fSDavid du Colombier r->perm = DMDIR | 0775; 2139a747e4fSDavid du Colombier r->qid.type = QTDIR; 2149a747e4fSDavid du Colombier r->qid.path = 0LL; 2153e12c5d1SDavid du Colombier r->qid.vers = 0; 2163e12c5d1SDavid du Colombier r->parent = 0; 2173e12c5d1SDavid du Colombier r->user = user; 2183e12c5d1SDavid du Colombier r->group = user; 2199a747e4fSDavid du Colombier r->muid = user; 2203e12c5d1SDavid du Colombier r->atime = time(0); 2213e12c5d1SDavid du Colombier r->mtime = r->atime; 2229a747e4fSDavid du Colombier r->name = estrdup("."); 2233e12c5d1SDavid du Colombier 224219b2ee8SDavid du Colombier if(debug) 2259a747e4fSDavid du Colombier fmtinstall('F', fcallfmt); 2263e12c5d1SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){ 2273e12c5d1SDavid du Colombier case -1: 2283e12c5d1SDavid du Colombier error("fork"); 2293e12c5d1SDavid du Colombier case 0: 2303e12c5d1SDavid du Colombier close(p[1]); 2313e12c5d1SDavid du Colombier io(); 2323e12c5d1SDavid du Colombier break; 2333e12c5d1SDavid du Colombier default: 2343e12c5d1SDavid du Colombier close(p[0]); /* don't deadlock if child fails */ 2359a747e4fSDavid du Colombier if(defmnt && mount(p[1], -1, defmnt, MREPL|MCREATE, "") < 0) 2363e12c5d1SDavid du Colombier error("mount failed"); 2373e12c5d1SDavid du Colombier } 2383e12c5d1SDavid du Colombier exits(0); 2393e12c5d1SDavid du Colombier } 2403e12c5d1SDavid du Colombier 2413e12c5d1SDavid du Colombier char* 2429a747e4fSDavid du Colombier rversion(Fid*) 2433e12c5d1SDavid du Colombier { 2443e12c5d1SDavid du Colombier Fid *f; 2453e12c5d1SDavid du Colombier 2463e12c5d1SDavid du Colombier for(f = fids; f; f = f->next) 2473e12c5d1SDavid du Colombier if(f->busy) 2483e12c5d1SDavid du Colombier rclunk(f); 2499a747e4fSDavid du Colombier if(thdr.msize > sizeof mdata) 2509a747e4fSDavid du Colombier rhdr.msize = sizeof mdata; 2519a747e4fSDavid du Colombier else 2529a747e4fSDavid du Colombier rhdr.msize = thdr.msize; 2539a747e4fSDavid du Colombier messagesize = rhdr.msize; 2549a747e4fSDavid du Colombier if(strncmp(thdr.version, "9P2000", 6) != 0) 2559a747e4fSDavid du Colombier return Eversion; 2569a747e4fSDavid du Colombier rhdr.version = "9P2000"; 2573e12c5d1SDavid du Colombier return 0; 2583e12c5d1SDavid du Colombier } 2593e12c5d1SDavid du Colombier 2603e12c5d1SDavid du Colombier char* 2619a747e4fSDavid du Colombier rauth(Fid*) 2629a747e4fSDavid du Colombier { 2639a747e4fSDavid du Colombier return "ramfs: no authentication required"; 2649a747e4fSDavid du Colombier } 2659a747e4fSDavid du Colombier 2669a747e4fSDavid du Colombier char* 2673e12c5d1SDavid du Colombier rflush(Fid *f) 2683e12c5d1SDavid du Colombier { 2693e12c5d1SDavid du Colombier USED(f); 2703e12c5d1SDavid du Colombier return 0; 2713e12c5d1SDavid du Colombier } 2723e12c5d1SDavid du Colombier 2733e12c5d1SDavid du Colombier char* 2743e12c5d1SDavid du Colombier rattach(Fid *f) 2753e12c5d1SDavid du Colombier { 2763e12c5d1SDavid du Colombier /* no authentication! */ 2773e12c5d1SDavid du Colombier f->busy = 1; 2783e12c5d1SDavid du Colombier f->rclose = 0; 2793e12c5d1SDavid du Colombier f->ram = &ram[0]; 2809a747e4fSDavid du Colombier rhdr.qid = f->ram->qid; 2819a747e4fSDavid du Colombier if(thdr.uname[0]) 2829a747e4fSDavid du Colombier f->user = estrdup(thdr.uname); 2833e12c5d1SDavid du Colombier else 2843e12c5d1SDavid du Colombier f->user = "none"; 2857dd7cddfSDavid du Colombier if(strcmp(user, "none") == 0) 2869a747e4fSDavid du Colombier user = f->user; 2873e12c5d1SDavid du Colombier return 0; 2883e12c5d1SDavid du Colombier } 2893e12c5d1SDavid du Colombier 2903e12c5d1SDavid du Colombier char* 2919a747e4fSDavid du Colombier clone(Fid *f, Fid **nf) 2923e12c5d1SDavid du Colombier { 2933e12c5d1SDavid du Colombier if(f->open) 2943e12c5d1SDavid du Colombier return Eisopen; 2953e12c5d1SDavid du Colombier if(f->ram->busy == 0) 2963e12c5d1SDavid du Colombier return Enotexist; 2979a747e4fSDavid du Colombier *nf = newfid(thdr.newfid); 2989a747e4fSDavid du Colombier (*nf)->busy = 1; 2999a747e4fSDavid du Colombier (*nf)->open = 0; 3009a747e4fSDavid du Colombier (*nf)->rclose = 0; 3019a747e4fSDavid du Colombier (*nf)->ram = f->ram; 3029a747e4fSDavid du Colombier (*nf)->user = f->user; /* no ref count; the leakage is minor */ 3033e12c5d1SDavid du Colombier return 0; 3043e12c5d1SDavid du Colombier } 3053e12c5d1SDavid du Colombier 3063e12c5d1SDavid du Colombier char* 3073e12c5d1SDavid du Colombier rwalk(Fid *f) 3083e12c5d1SDavid du Colombier { 3099a747e4fSDavid du Colombier Ram *r, *fram; 3103e12c5d1SDavid du Colombier char *name; 3113e12c5d1SDavid du Colombier Ram *parent; 3123e12c5d1SDavid du Colombier Fid *nf; 3133e12c5d1SDavid du Colombier char *err; 3149a747e4fSDavid du Colombier ulong t; 3159a747e4fSDavid du Colombier int i; 3163e12c5d1SDavid du Colombier 3179a747e4fSDavid du Colombier err = nil; 3189a747e4fSDavid du Colombier nf = nil; 3199a747e4fSDavid du Colombier rhdr.nwqid = 0; 32059c21d95SDavid du Colombier if(thdr.newfid != thdr.fid){ 3219a747e4fSDavid du Colombier err = clone(f, &nf); 3229a747e4fSDavid du Colombier if(err) 3239a747e4fSDavid du Colombier return err; 3249a747e4fSDavid du Colombier f = nf; /* walk the new fid */ 3259a747e4fSDavid du Colombier } 3269a747e4fSDavid du Colombier fram = f->ram; 3279a747e4fSDavid du Colombier if(thdr.nwname > 0){ 3289a747e4fSDavid du Colombier t = time(0); 3299a747e4fSDavid du Colombier for(i=0; i<thdr.nwname && i<MAXWELEM; i++){ 3309a747e4fSDavid du Colombier if((fram->qid.type & QTDIR) == 0){ 3319a747e4fSDavid du Colombier err = Enotdir; 3329a747e4fSDavid du Colombier break; 3339a747e4fSDavid du Colombier } 3349a747e4fSDavid du Colombier if(fram->busy == 0){ 3359a747e4fSDavid du Colombier err = Enotexist; 3369a747e4fSDavid du Colombier break; 3379a747e4fSDavid du Colombier } 3389a747e4fSDavid du Colombier fram->atime = t; 3399a747e4fSDavid du Colombier name = thdr.wname[i]; 3409a747e4fSDavid du Colombier if(strcmp(name, ".") == 0){ 3419a747e4fSDavid du Colombier Found: 3429a747e4fSDavid du Colombier rhdr.nwqid++; 3439a747e4fSDavid du Colombier rhdr.wqid[i] = fram->qid; 3449a747e4fSDavid du Colombier continue; 3459a747e4fSDavid du Colombier } 3469a747e4fSDavid du Colombier parent = &ram[fram->parent]; 3479a747e4fSDavid du Colombier if(!perm(f, parent, Pexec)){ 3489a747e4fSDavid du Colombier err = Eperm; 3499a747e4fSDavid du Colombier break; 3509a747e4fSDavid du Colombier } 3519a747e4fSDavid du Colombier if(strcmp(name, "..") == 0){ 3529a747e4fSDavid du Colombier fram = parent; 3539a747e4fSDavid du Colombier goto Found; 3549a747e4fSDavid du Colombier } 3559a747e4fSDavid du Colombier for(r=ram; r < &ram[nram]; r++) 3569a747e4fSDavid du Colombier if(r->busy && r->parent==fram-ram && strcmp(name, r->name)==0){ 3579a747e4fSDavid du Colombier fram = r; 3589a747e4fSDavid du Colombier goto Found; 3599a747e4fSDavid du Colombier } 3609a747e4fSDavid du Colombier break; 3619a747e4fSDavid du Colombier } 3629a747e4fSDavid du Colombier if(i==0 && err == nil) 3639a747e4fSDavid du Colombier err = Enotexist; 3649a747e4fSDavid du Colombier } 3659a747e4fSDavid du Colombier if(nf != nil && (err!=nil || rhdr.nwqid<thdr.nwname)){ 3669a747e4fSDavid du Colombier /* clunk the new fid, which is the one we walked */ 3679a747e4fSDavid du Colombier f->busy = 0; 3689a747e4fSDavid du Colombier f->ram = nil; 3699a747e4fSDavid du Colombier } 3709fa41221SDavid du Colombier if(rhdr.nwqid > 0) 3719fa41221SDavid du Colombier err = nil; /* didn't get everything in 9P2000 right! */ 3729a747e4fSDavid du Colombier if(rhdr.nwqid == thdr.nwname) /* update the fid after a successful walk */ 3739a747e4fSDavid du Colombier f->ram = fram; 3743e12c5d1SDavid du Colombier return err; 3753e12c5d1SDavid du Colombier } 3763e12c5d1SDavid du Colombier 3773e12c5d1SDavid du Colombier char * 3783e12c5d1SDavid du Colombier ropen(Fid *f) 3793e12c5d1SDavid du Colombier { 3803e12c5d1SDavid du Colombier Ram *r; 3813e12c5d1SDavid du Colombier int mode, trunc; 3823e12c5d1SDavid du Colombier 3833e12c5d1SDavid du Colombier if(f->open) 3843e12c5d1SDavid du Colombier return Eisopen; 3853e12c5d1SDavid du Colombier r = f->ram; 3863e12c5d1SDavid du Colombier if(r->busy == 0) 3873e12c5d1SDavid du Colombier return Enotexist; 3889a747e4fSDavid du Colombier if(r->perm & DMEXCL) 3893e12c5d1SDavid du Colombier if(r->open) 3903e12c5d1SDavid du Colombier return Excl; 3919a747e4fSDavid du Colombier mode = thdr.mode; 3929a747e4fSDavid du Colombier if(r->qid.type & QTDIR){ 3933e12c5d1SDavid du Colombier if(mode != OREAD) 3943e12c5d1SDavid du Colombier return Eperm; 3959a747e4fSDavid du Colombier rhdr.qid = r->qid; 3963e12c5d1SDavid du Colombier return 0; 3973e12c5d1SDavid du Colombier } 3983e12c5d1SDavid du Colombier if(mode & ORCLOSE){ 3999a747e4fSDavid du Colombier /* can't remove root; must be able to write parent */ 4009a747e4fSDavid du Colombier if(r->qid.path==0 || !perm(f, &ram[r->parent], Pwrite)) 4013e12c5d1SDavid du Colombier return Eperm; 4023e12c5d1SDavid du Colombier f->rclose = 1; 4033e12c5d1SDavid du Colombier } 4043e12c5d1SDavid du Colombier trunc = mode & OTRUNC; 4053e12c5d1SDavid du Colombier mode &= OPERM; 4063e12c5d1SDavid du Colombier if(mode==OWRITE || mode==ORDWR || trunc) 4073e12c5d1SDavid du Colombier if(!perm(f, r, Pwrite)) 4083e12c5d1SDavid du Colombier return Eperm; 4093e12c5d1SDavid du Colombier if(mode==OREAD || mode==ORDWR) 4103e12c5d1SDavid du Colombier if(!perm(f, r, Pread)) 4113e12c5d1SDavid du Colombier return Eperm; 4123e12c5d1SDavid du Colombier if(mode==OEXEC) 4133e12c5d1SDavid du Colombier if(!perm(f, r, Pexec)) 4143e12c5d1SDavid du Colombier return Eperm; 4159a747e4fSDavid du Colombier if(trunc && (r->perm&DMAPPEND)==0){ 4163e12c5d1SDavid du Colombier r->ndata = 0; 4173e12c5d1SDavid du Colombier if(r->data) 4183e12c5d1SDavid du Colombier free(r->data); 4193e12c5d1SDavid du Colombier r->data = 0; 4203e12c5d1SDavid du Colombier r->qid.vers++; 4213e12c5d1SDavid du Colombier } 4229a747e4fSDavid du Colombier rhdr.qid = r->qid; 4239a747e4fSDavid du Colombier rhdr.iounit = messagesize-IOHDRSZ; 4243e12c5d1SDavid du Colombier f->open = 1; 4253e12c5d1SDavid du Colombier r->open++; 4263e12c5d1SDavid du Colombier return 0; 4273e12c5d1SDavid du Colombier } 4283e12c5d1SDavid du Colombier 4293e12c5d1SDavid du Colombier char * 4303e12c5d1SDavid du Colombier rcreate(Fid *f) 4313e12c5d1SDavid du Colombier { 4323e12c5d1SDavid du Colombier Ram *r; 4333e12c5d1SDavid du Colombier char *name; 4343e12c5d1SDavid du Colombier long parent, prm; 4353e12c5d1SDavid du Colombier 4363e12c5d1SDavid du Colombier if(f->open) 4373e12c5d1SDavid du Colombier return Eisopen; 4383e12c5d1SDavid du Colombier if(f->ram->busy == 0) 4393e12c5d1SDavid du Colombier return Enotexist; 4403e12c5d1SDavid du Colombier parent = f->ram - ram; 4419a747e4fSDavid du Colombier if((f->ram->qid.type&QTDIR) == 0) 4423e12c5d1SDavid du Colombier return Enotdir; 4433e12c5d1SDavid du Colombier /* must be able to write parent */ 4443e12c5d1SDavid du Colombier if(!perm(f, f->ram, Pwrite)) 4453e12c5d1SDavid du Colombier return Eperm; 4469a747e4fSDavid du Colombier prm = thdr.perm; 4479a747e4fSDavid du Colombier name = thdr.name; 4483e12c5d1SDavid du Colombier if(strcmp(name, ".")==0 || strcmp(name, "..")==0) 4493e12c5d1SDavid du Colombier return Ename; 4503e12c5d1SDavid du Colombier for(r=ram; r<&ram[nram]; r++) 4513e12c5d1SDavid du Colombier if(r->busy && parent==r->parent) 4523e12c5d1SDavid du Colombier if(strcmp((char*)name, r->name)==0) 4533e12c5d1SDavid du Colombier return Einuse; 4543e12c5d1SDavid du Colombier for(r=ram; r->busy; r++) 4553e12c5d1SDavid du Colombier if(r == &ram[Nram-1]) 4563e12c5d1SDavid du Colombier return "no free ram resources"; 4573e12c5d1SDavid du Colombier r->busy = 1; 4583e12c5d1SDavid du Colombier r->qid.path = ++path; 4593e12c5d1SDavid du Colombier r->qid.vers = 0; 4609a747e4fSDavid du Colombier if(prm & DMDIR) 4619a747e4fSDavid du Colombier r->qid.type |= QTDIR; 4623e12c5d1SDavid du Colombier r->parent = parent; 4639a747e4fSDavid du Colombier free(r->name); 4649a747e4fSDavid du Colombier r->name = estrdup(name); 4653e12c5d1SDavid du Colombier r->user = f->user; 4663e12c5d1SDavid du Colombier r->group = f->ram->group; 4679a747e4fSDavid du Colombier r->muid = f->ram->muid; 4689a747e4fSDavid du Colombier if(prm & DMDIR) 4693e12c5d1SDavid du Colombier prm = (prm&~0777) | (f->ram->perm&prm&0777); 4703e12c5d1SDavid du Colombier else 4713e12c5d1SDavid du Colombier prm = (prm&(~0777|0111)) | (f->ram->perm&prm&0666); 4723e12c5d1SDavid du Colombier r->perm = prm; 4733e12c5d1SDavid du Colombier r->ndata = 0; 4743e12c5d1SDavid du Colombier if(r-ram >= nram) 4753e12c5d1SDavid du Colombier nram = r - ram + 1; 4763e12c5d1SDavid du Colombier r->atime = time(0); 4773e12c5d1SDavid du Colombier r->mtime = r->atime; 4783e12c5d1SDavid du Colombier f->ram->mtime = r->atime; 4793e12c5d1SDavid du Colombier f->ram = r; 4809a747e4fSDavid du Colombier rhdr.qid = r->qid; 4819a747e4fSDavid du Colombier rhdr.iounit = messagesize-IOHDRSZ; 4823e12c5d1SDavid du Colombier f->open = 1; 4839a747e4fSDavid du Colombier if(thdr.mode & ORCLOSE) 4847dd7cddfSDavid du Colombier f->rclose = 1; 4853e12c5d1SDavid du Colombier r->open++; 4863e12c5d1SDavid du Colombier return 0; 4873e12c5d1SDavid du Colombier } 4883e12c5d1SDavid du Colombier 4893e12c5d1SDavid du Colombier char* 4903e12c5d1SDavid du Colombier rread(Fid *f) 4913e12c5d1SDavid du Colombier { 4923e12c5d1SDavid du Colombier Ram *r; 4939a747e4fSDavid du Colombier uchar *buf; 4943e12c5d1SDavid du Colombier long off; 4959a747e4fSDavid du Colombier int n, m, cnt; 4963e12c5d1SDavid du Colombier 4973e12c5d1SDavid du Colombier if(f->ram->busy == 0) 4983e12c5d1SDavid du Colombier return Enotexist; 4993e12c5d1SDavid du Colombier n = 0; 5009a747e4fSDavid du Colombier rhdr.count = 0; 5019a747e4fSDavid du Colombier off = thdr.offset; 5029a747e4fSDavid du Colombier buf = rdata; 5039a747e4fSDavid du Colombier cnt = thdr.count; 5049a747e4fSDavid du Colombier if(cnt > messagesize) /* shouldn't happen, anyway */ 5059a747e4fSDavid du Colombier cnt = messagesize; 5069a747e4fSDavid du Colombier if(f->ram->qid.type & QTDIR){ 5079a747e4fSDavid du Colombier for(r=ram+1; off > 0; r++){ 5083e12c5d1SDavid du Colombier if(r->busy && r->parent==f->ram-ram) 5099a747e4fSDavid du Colombier off -= ramstat(r, statbuf, sizeof statbuf); 5103e12c5d1SDavid du Colombier if(r == &ram[nram-1]) 5113e12c5d1SDavid du Colombier return 0; 5123e12c5d1SDavid du Colombier } 5133e12c5d1SDavid du Colombier for(; r<&ram[nram] && n < cnt; r++){ 5143e12c5d1SDavid du Colombier if(!r->busy || r->parent!=f->ram-ram) 5153e12c5d1SDavid du Colombier continue; 5169a747e4fSDavid du Colombier m = ramstat(r, buf+n, cnt-n); 5179a747e4fSDavid du Colombier if(m == 0) 5189a747e4fSDavid du Colombier break; 5199a747e4fSDavid du Colombier n += m; 5203e12c5d1SDavid du Colombier } 5219a747e4fSDavid du Colombier rhdr.data = (char*)rdata; 5229a747e4fSDavid du Colombier rhdr.count = n; 5233e12c5d1SDavid du Colombier return 0; 5243e12c5d1SDavid du Colombier } 5253e12c5d1SDavid du Colombier r = f->ram; 5263e12c5d1SDavid du Colombier if(off >= r->ndata) 5273e12c5d1SDavid du Colombier return 0; 5283e12c5d1SDavid du Colombier r->atime = time(0); 5293e12c5d1SDavid du Colombier n = cnt; 5303e12c5d1SDavid du Colombier if(off+n > r->ndata) 5313e12c5d1SDavid du Colombier n = r->ndata - off; 5329a747e4fSDavid du Colombier rhdr.data = r->data+off; 5339a747e4fSDavid du Colombier rhdr.count = n; 5343e12c5d1SDavid du Colombier return 0; 5353e12c5d1SDavid du Colombier } 5363e12c5d1SDavid du Colombier 5373e12c5d1SDavid du Colombier char* 5383e12c5d1SDavid du Colombier rwrite(Fid *f) 5393e12c5d1SDavid du Colombier { 5403e12c5d1SDavid du Colombier Ram *r; 5413e12c5d1SDavid du Colombier ulong off; 5423e12c5d1SDavid du Colombier int cnt; 5433e12c5d1SDavid du Colombier 5443e12c5d1SDavid du Colombier r = f->ram; 5453e12c5d1SDavid du Colombier if(r->busy == 0) 5463e12c5d1SDavid du Colombier return Enotexist; 5479a747e4fSDavid du Colombier off = thdr.offset; 5489a747e4fSDavid du Colombier if(r->perm & DMAPPEND) 5493e12c5d1SDavid du Colombier off = r->ndata; 5509a747e4fSDavid du Colombier cnt = thdr.count; 5519a747e4fSDavid du Colombier if(r->qid.type & QTDIR) 5529a747e4fSDavid du Colombier return Eisdir; 5537dd7cddfSDavid du Colombier if(off+cnt >= Maxsize) /* sanity check */ 5543e12c5d1SDavid du Colombier return "write too big"; 5553e12c5d1SDavid du Colombier if(off+cnt > r->ndata) 5563e12c5d1SDavid du Colombier r->data = erealloc(r->data, off+cnt); 5573e12c5d1SDavid du Colombier if(off > r->ndata) 5583e12c5d1SDavid du Colombier memset(r->data+r->ndata, 0, off-r->ndata); 5593e12c5d1SDavid du Colombier if(off+cnt > r->ndata) 5603e12c5d1SDavid du Colombier r->ndata = off+cnt; 5619a747e4fSDavid du Colombier memmove(r->data+off, thdr.data, cnt); 5623e12c5d1SDavid du Colombier r->qid.vers++; 5633e12c5d1SDavid du Colombier r->mtime = time(0); 5649a747e4fSDavid du Colombier rhdr.count = cnt; 5653e12c5d1SDavid du Colombier return 0; 5663e12c5d1SDavid du Colombier } 5673e12c5d1SDavid du Colombier 568162174bbSDavid du Colombier static int 569162174bbSDavid du Colombier emptydir(Ram *dr) 570162174bbSDavid du Colombier { 571162174bbSDavid du Colombier long didx = dr - ram; 572162174bbSDavid du Colombier Ram *r; 573162174bbSDavid du Colombier 574162174bbSDavid du Colombier for(r=ram; r<&ram[nram]; r++) 575162174bbSDavid du Colombier if(r->busy && didx==r->parent) 576162174bbSDavid du Colombier return 0; 577162174bbSDavid du Colombier return 1; 578162174bbSDavid du Colombier } 579162174bbSDavid du Colombier 580162174bbSDavid du Colombier char * 5813e12c5d1SDavid du Colombier realremove(Ram *r) 5823e12c5d1SDavid du Colombier { 583162174bbSDavid du Colombier if(r->qid.type & QTDIR && !emptydir(r)) 584162174bbSDavid du Colombier return Enotempty; 5853e12c5d1SDavid du Colombier r->ndata = 0; 5863e12c5d1SDavid du Colombier if(r->data) 5873e12c5d1SDavid du Colombier free(r->data); 5883e12c5d1SDavid du Colombier r->data = 0; 5893e12c5d1SDavid du Colombier r->parent = 0; 5909a747e4fSDavid du Colombier memset(&r->qid, 0, sizeof r->qid); 5919a747e4fSDavid du Colombier free(r->name); 5929a747e4fSDavid du Colombier r->name = nil; 5933e12c5d1SDavid du Colombier r->busy = 0; 594162174bbSDavid du Colombier return nil; 5953e12c5d1SDavid du Colombier } 5963e12c5d1SDavid du Colombier 5973e12c5d1SDavid du Colombier char * 5983e12c5d1SDavid du Colombier rclunk(Fid *f) 5993e12c5d1SDavid du Colombier { 600162174bbSDavid du Colombier char *e = nil; 601162174bbSDavid du Colombier 6023e12c5d1SDavid du Colombier if(f->open) 6033e12c5d1SDavid du Colombier f->ram->open--; 6043e12c5d1SDavid du Colombier if(f->rclose) 605162174bbSDavid du Colombier e = realremove(f->ram); 6063e12c5d1SDavid du Colombier f->busy = 0; 6073e12c5d1SDavid du Colombier f->open = 0; 6083e12c5d1SDavid du Colombier f->ram = 0; 609162174bbSDavid du Colombier return e; 6103e12c5d1SDavid du Colombier } 6113e12c5d1SDavid du Colombier 6123e12c5d1SDavid du Colombier char * 6133e12c5d1SDavid du Colombier rremove(Fid *f) 6143e12c5d1SDavid du Colombier { 6153e12c5d1SDavid du Colombier Ram *r; 6163e12c5d1SDavid du Colombier 6173e12c5d1SDavid du Colombier if(f->open) 6183e12c5d1SDavid du Colombier f->ram->open--; 6193e12c5d1SDavid du Colombier f->busy = 0; 6203e12c5d1SDavid du Colombier f->open = 0; 6213e12c5d1SDavid du Colombier r = f->ram; 6223e12c5d1SDavid du Colombier f->ram = 0; 6239a747e4fSDavid du Colombier if(r->qid.path == 0 || !perm(f, &ram[r->parent], Pwrite)) 6243e12c5d1SDavid du Colombier return Eperm; 6253e12c5d1SDavid du Colombier ram[r->parent].mtime = time(0); 626162174bbSDavid du Colombier return realremove(r); 6273e12c5d1SDavid du Colombier } 6283e12c5d1SDavid du Colombier 6293e12c5d1SDavid du Colombier char * 6303e12c5d1SDavid du Colombier rstat(Fid *f) 6313e12c5d1SDavid du Colombier { 6323e12c5d1SDavid du Colombier if(f->ram->busy == 0) 6333e12c5d1SDavid du Colombier return Enotexist; 6349a747e4fSDavid du Colombier rhdr.nstat = ramstat(f->ram, statbuf, sizeof statbuf); 6359a747e4fSDavid du Colombier rhdr.stat = statbuf; 6363e12c5d1SDavid du Colombier return 0; 6373e12c5d1SDavid du Colombier } 6383e12c5d1SDavid du Colombier 6393e12c5d1SDavid du Colombier char * 6403e12c5d1SDavid du Colombier rwstat(Fid *f) 6413e12c5d1SDavid du Colombier { 6423e12c5d1SDavid du Colombier Ram *r, *s; 6433e12c5d1SDavid du Colombier Dir dir; 6443e12c5d1SDavid du Colombier 6453e12c5d1SDavid du Colombier if(f->ram->busy == 0) 6463e12c5d1SDavid du Colombier return Enotexist; 6479a747e4fSDavid du Colombier convM2D(thdr.stat, thdr.nstat, &dir, (char*)statbuf); 6483e12c5d1SDavid du Colombier r = f->ram; 6493e12c5d1SDavid du Colombier 6503e12c5d1SDavid du Colombier /* 6519a747e4fSDavid du Colombier * To change length, must have write permission on file. 6529a747e4fSDavid du Colombier */ 6539a747e4fSDavid du Colombier if(dir.length!=~0 && dir.length!=r->ndata){ 6549a747e4fSDavid du Colombier if(!perm(f, r, Pwrite)) 6559a747e4fSDavid du Colombier return Eperm; 6569a747e4fSDavid du Colombier } 6579a747e4fSDavid du Colombier 6589a747e4fSDavid du Colombier /* 6593e12c5d1SDavid du Colombier * To change name, must have write permission in parent 6603e12c5d1SDavid du Colombier * and name must be unique. 6613e12c5d1SDavid du Colombier */ 6629a747e4fSDavid du Colombier if(dir.name[0]!='\0' && strcmp(dir.name, r->name)!=0){ 6633e12c5d1SDavid du Colombier if(!perm(f, &ram[r->parent], Pwrite)) 6643e12c5d1SDavid du Colombier return Eperm; 6653e12c5d1SDavid du Colombier for(s=ram; s<&ram[nram]; s++) 6663e12c5d1SDavid du Colombier if(s->busy && s->parent==r->parent) 6673e12c5d1SDavid du Colombier if(strcmp(dir.name, s->name)==0) 6683e12c5d1SDavid du Colombier return Eexist; 6693e12c5d1SDavid du Colombier } 6703e12c5d1SDavid du Colombier 6713e12c5d1SDavid du Colombier /* 6729a747e4fSDavid du Colombier * To change mode, must be owner or group leader. 6733e12c5d1SDavid du Colombier * Because of lack of users file, leader=>group itself. 6743e12c5d1SDavid du Colombier */ 6759a747e4fSDavid du Colombier if(dir.mode!=~0 && r->perm!=dir.mode){ 6763e12c5d1SDavid du Colombier if(strcmp(f->user, r->user) != 0) 6773e12c5d1SDavid du Colombier if(strcmp(f->user, r->group) != 0) 6783e12c5d1SDavid du Colombier return Enotowner; 6793e12c5d1SDavid du Colombier } 6803e12c5d1SDavid du Colombier 6813e12c5d1SDavid du Colombier /* 6823e12c5d1SDavid du Colombier * To change group, must be owner and member of new group, 6833e12c5d1SDavid du Colombier * or leader of current group and leader of new group. 6843e12c5d1SDavid du Colombier * Second case cannot happen, but we check anyway. 6853e12c5d1SDavid du Colombier */ 6869a747e4fSDavid du Colombier if(dir.gid[0]!='\0' && strcmp(r->group, dir.gid)!=0){ 6873e12c5d1SDavid du Colombier if(strcmp(f->user, r->user) == 0) 688dc5a79c1SDavid du Colombier // if(strcmp(f->user, dir.gid) == 0) 6893e12c5d1SDavid du Colombier goto ok; 6903e12c5d1SDavid du Colombier if(strcmp(f->user, r->group) == 0) 6913e12c5d1SDavid du Colombier if(strcmp(f->user, dir.gid) == 0) 6923e12c5d1SDavid du Colombier goto ok; 6933e12c5d1SDavid du Colombier return Enotowner; 6943e12c5d1SDavid du Colombier ok:; 6953e12c5d1SDavid du Colombier } 6963e12c5d1SDavid du Colombier 6973e12c5d1SDavid du Colombier /* all ok; do it */ 6989a747e4fSDavid du Colombier if(dir.mode != ~0){ 6999a747e4fSDavid du Colombier dir.mode &= ~DMDIR; /* cannot change dir bit */ 7009a747e4fSDavid du Colombier dir.mode |= r->perm&DMDIR; 7013e12c5d1SDavid du Colombier r->perm = dir.mode; 7029a747e4fSDavid du Colombier } 7039a747e4fSDavid du Colombier if(dir.name[0] != '\0'){ 7049a747e4fSDavid du Colombier free(r->name); 7059a747e4fSDavid du Colombier r->name = estrdup(dir.name); 7069a747e4fSDavid du Colombier } 7079a747e4fSDavid du Colombier if(dir.gid[0] != '\0') 7089a747e4fSDavid du Colombier r->group = estrdup(dir.gid); 7099a747e4fSDavid du Colombier if(dir.length!=~0 && dir.length!=r->ndata){ 7109a747e4fSDavid du Colombier r->data = erealloc(r->data, dir.length); 7119a747e4fSDavid du Colombier if(r->ndata < dir.length) 7129a747e4fSDavid du Colombier memset(r->data+r->ndata, 0, dir.length-r->ndata); 7139a747e4fSDavid du Colombier r->ndata = dir.length; 7149a747e4fSDavid du Colombier } 7153e12c5d1SDavid du Colombier ram[r->parent].mtime = time(0); 7163e12c5d1SDavid du Colombier return 0; 7173e12c5d1SDavid du Colombier } 7183e12c5d1SDavid du Colombier 7199a747e4fSDavid du Colombier uint 7209a747e4fSDavid du Colombier ramstat(Ram *r, uchar *buf, uint nbuf) 7213e12c5d1SDavid du Colombier { 7226b6b9ac8SDavid du Colombier int n; 7233e12c5d1SDavid du Colombier Dir dir; 7243e12c5d1SDavid du Colombier 7259a747e4fSDavid du Colombier dir.name = r->name; 7263e12c5d1SDavid du Colombier dir.qid = r->qid; 7273e12c5d1SDavid du Colombier dir.mode = r->perm; 7283e12c5d1SDavid du Colombier dir.length = r->ndata; 7299a747e4fSDavid du Colombier dir.uid = r->user; 7309a747e4fSDavid du Colombier dir.gid = r->group; 7319a747e4fSDavid du Colombier dir.muid = r->muid; 7323e12c5d1SDavid du Colombier dir.atime = r->atime; 7333e12c5d1SDavid du Colombier dir.mtime = r->mtime; 7346b6b9ac8SDavid du Colombier n = convD2M(&dir, buf, nbuf); 7356b6b9ac8SDavid du Colombier if(n > 2) 7366b6b9ac8SDavid du Colombier return n; 7376b6b9ac8SDavid du Colombier return 0; 7383e12c5d1SDavid du Colombier } 7393e12c5d1SDavid du Colombier 7403e12c5d1SDavid du Colombier Fid * 7413e12c5d1SDavid du Colombier newfid(int fid) 7423e12c5d1SDavid du Colombier { 7433e12c5d1SDavid du Colombier Fid *f, *ff; 7443e12c5d1SDavid du Colombier 7453e12c5d1SDavid du Colombier ff = 0; 7463e12c5d1SDavid du Colombier for(f = fids; f; f = f->next) 7473e12c5d1SDavid du Colombier if(f->fid == fid) 7483e12c5d1SDavid du Colombier return f; 7493e12c5d1SDavid du Colombier else if(!ff && !f->busy) 7503e12c5d1SDavid du Colombier ff = f; 7513e12c5d1SDavid du Colombier if(ff){ 7523e12c5d1SDavid du Colombier ff->fid = fid; 7533e12c5d1SDavid du Colombier return ff; 7543e12c5d1SDavid du Colombier } 7553e12c5d1SDavid du Colombier f = emalloc(sizeof *f); 7567dd7cddfSDavid du Colombier f->ram = nil; 7573e12c5d1SDavid du Colombier f->fid = fid; 7583e12c5d1SDavid du Colombier f->next = fids; 7593e12c5d1SDavid du Colombier fids = f; 7603e12c5d1SDavid du Colombier return f; 7613e12c5d1SDavid du Colombier } 7623e12c5d1SDavid du Colombier 7633e12c5d1SDavid du Colombier void 7643e12c5d1SDavid du Colombier io(void) 7653e12c5d1SDavid du Colombier { 76624e2e655SDavid du Colombier char *err, buf[40]; 7679a747e4fSDavid du Colombier int n, pid, ctl; 7689fa41221SDavid du Colombier Fid *fid; 7699a747e4fSDavid du Colombier 7709a747e4fSDavid du Colombier pid = getpid(); 7719a747e4fSDavid du Colombier if(private){ 7729a747e4fSDavid du Colombier snprint(buf, sizeof buf, "/proc/%d/ctl", pid); 7739a747e4fSDavid du Colombier ctl = open(buf, OWRITE); 7749a747e4fSDavid du Colombier if(ctl < 0){ 7759a747e4fSDavid du Colombier fprint(2, "can't protect ramfs\n"); 7769a747e4fSDavid du Colombier }else{ 7779a747e4fSDavid du Colombier fprint(ctl, "noswap\n"); 7789a747e4fSDavid du Colombier fprint(ctl, "private\n"); 7799a747e4fSDavid du Colombier close(ctl); 7809a747e4fSDavid du Colombier } 7819a747e4fSDavid du Colombier } 7823e12c5d1SDavid du Colombier 7833e12c5d1SDavid du Colombier for(;;){ 7843e12c5d1SDavid du Colombier /* 7853e12c5d1SDavid du Colombier * reading from a pipe or a network device 7869a747e4fSDavid du Colombier * will give an error after a few eof reads. 7873e12c5d1SDavid du Colombier * however, we cannot tell the difference 7883e12c5d1SDavid du Colombier * between a zero-length read and an interrupt 7893e12c5d1SDavid du Colombier * on the processes writing to us, 7909a747e4fSDavid du Colombier * so we wait for the error. 7913e12c5d1SDavid du Colombier */ 7929a747e4fSDavid du Colombier n = read9pmsg(mfd[0], mdata, messagesize); 79324e2e655SDavid du Colombier if(n < 0){ 79424e2e655SDavid du Colombier errstr(buf, sizeof buf); 79524e2e655SDavid du Colombier if(buf[0]=='\0' || strstr(buf, "hungup")) 79624e2e655SDavid du Colombier exits(""); 79724e2e655SDavid du Colombier error("mount read"); 79824e2e655SDavid du Colombier } 7993e12c5d1SDavid du Colombier if(n < 0) 8003e12c5d1SDavid du Colombier error("mount read"); 8019a747e4fSDavid du Colombier if(n == 0) 8029a747e4fSDavid du Colombier continue; 8039a747e4fSDavid du Colombier if(convM2S(mdata, n, &thdr) == 0) 8043e12c5d1SDavid du Colombier continue; 8053e12c5d1SDavid du Colombier 806219b2ee8SDavid du Colombier if(debug) 8079a747e4fSDavid du Colombier fprint(2, "ramfs %d:<-%F\n", pid, &thdr); 8083e12c5d1SDavid du Colombier 8099fa41221SDavid du Colombier if(thdr.type<0 || thdr.type>=nelem(fcalls) || !fcalls[thdr.type]) 8103e12c5d1SDavid du Colombier err = "bad fcall type"; 8119fa41221SDavid du Colombier else if(((fid=newfid(thdr.fid))==nil || !fid->ram) && needfid[thdr.type]) 8129fa41221SDavid du Colombier err = "fid not in use"; 8133e12c5d1SDavid du Colombier else 8149fa41221SDavid du Colombier err = (*fcalls[thdr.type])(fid); 8153e12c5d1SDavid du Colombier if(err){ 8169a747e4fSDavid du Colombier rhdr.type = Rerror; 8179a747e4fSDavid du Colombier rhdr.ename = err; 8183e12c5d1SDavid du Colombier }else{ 8199a747e4fSDavid du Colombier rhdr.type = thdr.type + 1; 8209a747e4fSDavid du Colombier rhdr.fid = thdr.fid; 8213e12c5d1SDavid du Colombier } 8229a747e4fSDavid du Colombier rhdr.tag = thdr.tag; 823219b2ee8SDavid du Colombier if(debug) 8249a747e4fSDavid du Colombier fprint(2, "ramfs %d:->%F\n", pid, &rhdr);/**/ 8259a747e4fSDavid du Colombier n = convS2M(&rhdr, mdata, messagesize); 8269a747e4fSDavid du Colombier if(n == 0) 8279a747e4fSDavid du Colombier error("convS2M error on write"); 8283e12c5d1SDavid du Colombier if(write(mfd[1], mdata, n) != n) 8293e12c5d1SDavid du Colombier error("mount write"); 8303e12c5d1SDavid du Colombier } 8313e12c5d1SDavid du Colombier } 8323e12c5d1SDavid du Colombier 8333e12c5d1SDavid du Colombier int 8343e12c5d1SDavid du Colombier perm(Fid *f, Ram *r, int p) 8353e12c5d1SDavid du Colombier { 8363e12c5d1SDavid du Colombier if((p*Pother) & r->perm) 8373e12c5d1SDavid du Colombier return 1; 8383e12c5d1SDavid du Colombier if(strcmp(f->user, r->group)==0 && ((p*Pgroup) & r->perm)) 8393e12c5d1SDavid du Colombier return 1; 8403e12c5d1SDavid du Colombier if(strcmp(f->user, r->user)==0 && ((p*Powner) & r->perm)) 8413e12c5d1SDavid du Colombier return 1; 8423e12c5d1SDavid du Colombier return 0; 8433e12c5d1SDavid du Colombier } 8443e12c5d1SDavid du Colombier 8453e12c5d1SDavid du Colombier void 8463e12c5d1SDavid du Colombier error(char *s) 8473e12c5d1SDavid du Colombier { 848219b2ee8SDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, s); 8493e12c5d1SDavid du Colombier exits(s); 8503e12c5d1SDavid du Colombier } 8513e12c5d1SDavid du Colombier 8523e12c5d1SDavid du Colombier void * 8533e12c5d1SDavid du Colombier emalloc(ulong n) 8543e12c5d1SDavid du Colombier { 8553e12c5d1SDavid du Colombier void *p; 8563e12c5d1SDavid du Colombier 8573e12c5d1SDavid du Colombier p = malloc(n); 8583e12c5d1SDavid du Colombier if(!p) 8593e12c5d1SDavid du Colombier error("out of memory"); 8607dd7cddfSDavid du Colombier memset(p, 0, n); 8613e12c5d1SDavid du Colombier return p; 8623e12c5d1SDavid du Colombier } 8633e12c5d1SDavid du Colombier 8643e12c5d1SDavid du Colombier void * 8653e12c5d1SDavid du Colombier erealloc(void *p, ulong n) 8663e12c5d1SDavid du Colombier { 8673e12c5d1SDavid du Colombier p = realloc(p, n); 8683e12c5d1SDavid du Colombier if(!p) 8693e12c5d1SDavid du Colombier error("out of memory"); 8703e12c5d1SDavid du Colombier return p; 8713e12c5d1SDavid du Colombier } 8723e12c5d1SDavid du Colombier 8739a747e4fSDavid du Colombier char * 8749a747e4fSDavid du Colombier estrdup(char *q) 8759a747e4fSDavid du Colombier { 8769a747e4fSDavid du Colombier char *p; 8779a747e4fSDavid du Colombier int n; 8789a747e4fSDavid du Colombier 8799a747e4fSDavid du Colombier n = strlen(q)+1; 8809a747e4fSDavid du Colombier p = malloc(n); 8819a747e4fSDavid du Colombier if(!p) 8829a747e4fSDavid du Colombier error("out of memory"); 8839a747e4fSDavid du Colombier memmove(p, q, n); 8849a747e4fSDavid du Colombier return p; 8859a747e4fSDavid du Colombier } 8869a747e4fSDavid du Colombier 8873e12c5d1SDavid du Colombier void 8883e12c5d1SDavid du Colombier usage(void) 8893e12c5d1SDavid du Colombier { 890*ab3dc52fSDavid du Colombier fprint(2, "usage: %s [-Dips] [-m mountpoint] [-S srvname]\n", argv0); 8913e12c5d1SDavid du Colombier exits("usage"); 8923e12c5d1SDavid du Colombier } 893