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 */
16*ae886fecSDavid du Colombier Nram = 4096,
1746228ac7SDavid du Colombier Maxsize = 768*1024*1024,
189a747e4fSDavid du Colombier Maxfdata = 8192,
19b3b810bfSDavid du Colombier Maxulong= (1ULL << 32) - 1,
203e12c5d1SDavid du Colombier };
213e12c5d1SDavid du Colombier
223e12c5d1SDavid du Colombier typedef struct Fid Fid;
233e12c5d1SDavid du Colombier typedef struct Ram Ram;
243e12c5d1SDavid du Colombier
253e12c5d1SDavid du Colombier struct Fid
263e12c5d1SDavid du Colombier {
273e12c5d1SDavid du Colombier short busy;
283e12c5d1SDavid du Colombier short open;
293e12c5d1SDavid du Colombier short rclose;
303e12c5d1SDavid du Colombier int fid;
313e12c5d1SDavid du Colombier Fid *next;
323e12c5d1SDavid du Colombier char *user;
333e12c5d1SDavid du Colombier Ram *ram;
343e12c5d1SDavid du Colombier };
353e12c5d1SDavid du Colombier
363e12c5d1SDavid du Colombier struct Ram
373e12c5d1SDavid du Colombier {
383e12c5d1SDavid du Colombier short busy;
393e12c5d1SDavid du Colombier short open;
403e12c5d1SDavid du Colombier long parent; /* index in Ram array */
413e12c5d1SDavid du Colombier Qid qid;
423e12c5d1SDavid du Colombier long perm;
439a747e4fSDavid du Colombier char *name;
443e12c5d1SDavid du Colombier ulong atime;
453e12c5d1SDavid du Colombier ulong mtime;
463e12c5d1SDavid du Colombier char *user;
473e12c5d1SDavid du Colombier char *group;
489a747e4fSDavid du Colombier char *muid;
493e12c5d1SDavid du Colombier char *data;
503e12c5d1SDavid du Colombier long ndata;
513e12c5d1SDavid du Colombier };
523e12c5d1SDavid du Colombier
533e12c5d1SDavid du Colombier enum
543e12c5d1SDavid du Colombier {
553e12c5d1SDavid du Colombier Pexec = 1,
563e12c5d1SDavid du Colombier Pwrite = 2,
573e12c5d1SDavid du Colombier Pread = 4,
583e12c5d1SDavid du Colombier Pother = 1,
593e12c5d1SDavid du Colombier Pgroup = 8,
603e12c5d1SDavid du Colombier Powner = 64,
613e12c5d1SDavid du Colombier };
623e12c5d1SDavid du Colombier
633e12c5d1SDavid du Colombier ulong path; /* incremented for each new file */
643e12c5d1SDavid du Colombier Fid *fids;
653e12c5d1SDavid du Colombier Ram ram[Nram];
663e12c5d1SDavid du Colombier int nram;
673e12c5d1SDavid du Colombier int mfd[2];
689a747e4fSDavid du Colombier char *user;
699a747e4fSDavid du Colombier uchar mdata[IOHDRSZ+Maxfdata];
709a747e4fSDavid du Colombier uchar rdata[Maxfdata]; /* buffer for data in reply */
719a747e4fSDavid du Colombier uchar statbuf[STATMAX];
723e12c5d1SDavid du Colombier Fcall thdr;
739a747e4fSDavid du Colombier Fcall rhdr;
749a747e4fSDavid du Colombier int messagesize = sizeof mdata;
753e12c5d1SDavid du Colombier
763e12c5d1SDavid du Colombier Fid * newfid(int);
779a747e4fSDavid du Colombier uint ramstat(Ram*, uchar*, uint);
783e12c5d1SDavid du Colombier void error(char*);
793e12c5d1SDavid du Colombier void io(void);
803e12c5d1SDavid du Colombier void *erealloc(void*, ulong);
813e12c5d1SDavid du Colombier void *emalloc(ulong);
829a747e4fSDavid du Colombier char *estrdup(char*);
833e12c5d1SDavid du Colombier void usage(void);
843e12c5d1SDavid du Colombier int perm(Fid*, Ram*, int);
853e12c5d1SDavid du Colombier
869a747e4fSDavid du Colombier char *rflush(Fid*), *rversion(Fid*), *rauth(Fid*),
879a747e4fSDavid du Colombier *rattach(Fid*), *rwalk(Fid*),
889a747e4fSDavid du Colombier *ropen(Fid*), *rcreate(Fid*),
893e12c5d1SDavid du Colombier *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
90219b2ee8SDavid du Colombier *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
913e12c5d1SDavid du Colombier
929fa41221SDavid du Colombier int needfid[] = {
939fa41221SDavid du Colombier [Tversion] 0,
949fa41221SDavid du Colombier [Tflush] 0,
959fa41221SDavid du Colombier [Tauth] 0,
969fa41221SDavid du Colombier [Tattach] 0,
979fa41221SDavid du Colombier [Twalk] 1,
989fa41221SDavid du Colombier [Topen] 1,
999fa41221SDavid du Colombier [Tcreate] 1,
1009fa41221SDavid du Colombier [Tread] 1,
1019fa41221SDavid du Colombier [Twrite] 1,
1029fa41221SDavid du Colombier [Tclunk] 1,
1039fa41221SDavid du Colombier [Tremove] 1,
1049fa41221SDavid du Colombier [Tstat] 1,
1059fa41221SDavid du Colombier [Twstat] 1,
1069fa41221SDavid du Colombier };
1079fa41221SDavid du Colombier
1083e12c5d1SDavid du Colombier char *(*fcalls[])(Fid*) = {
1099a747e4fSDavid du Colombier [Tversion] rversion,
1103e12c5d1SDavid du Colombier [Tflush] rflush,
1119a747e4fSDavid du Colombier [Tauth] rauth,
1123e12c5d1SDavid du Colombier [Tattach] rattach,
1133e12c5d1SDavid du Colombier [Twalk] rwalk,
1143e12c5d1SDavid du Colombier [Topen] ropen,
1153e12c5d1SDavid du Colombier [Tcreate] rcreate,
1163e12c5d1SDavid du Colombier [Tread] rread,
1173e12c5d1SDavid du Colombier [Twrite] rwrite,
1183e12c5d1SDavid du Colombier [Tclunk] rclunk,
1193e12c5d1SDavid du Colombier [Tremove] rremove,
1203e12c5d1SDavid du Colombier [Tstat] rstat,
1213e12c5d1SDavid du Colombier [Twstat] rwstat,
1223e12c5d1SDavid du Colombier };
1233e12c5d1SDavid du Colombier
1243e12c5d1SDavid du Colombier char Eperm[] = "permission denied";
1253e12c5d1SDavid du Colombier char Enotdir[] = "not a directory";
1263ff48bf5SDavid du Colombier char Enoauth[] = "ramfs: authentication not required";
1273e12c5d1SDavid du Colombier char Enotexist[] = "file does not exist";
1283e12c5d1SDavid du Colombier char Einuse[] = "file in use";
1293e12c5d1SDavid du Colombier char Eexist[] = "file exists";
1309a747e4fSDavid du Colombier char Eisdir[] = "file is a directory";
1313e12c5d1SDavid du Colombier char Enotowner[] = "not owner";
1323e12c5d1SDavid du Colombier char Eisopen[] = "file already open for I/O";
1333e12c5d1SDavid du Colombier char Excl[] = "exclusive use file already open";
1343e12c5d1SDavid du Colombier char Ename[] = "illegal name";
1359a747e4fSDavid du Colombier char Eversion[] = "unknown 9P version";
136162174bbSDavid du Colombier char Enotempty[] = "directory not empty";
1373e12c5d1SDavid du Colombier
138219b2ee8SDavid du Colombier int debug;
1399a747e4fSDavid du Colombier int private;
140219b2ee8SDavid du Colombier
141208510e1SDavid du Colombier static int memlim = 1;
142208510e1SDavid du Colombier
1433e12c5d1SDavid du Colombier void
notifyf(void * a,char * s)1443e12c5d1SDavid du Colombier notifyf(void *a, char *s)
1453e12c5d1SDavid du Colombier {
1463e12c5d1SDavid du Colombier USED(a);
1473e12c5d1SDavid du Colombier if(strncmp(s, "interrupt", 9) == 0)
1483e12c5d1SDavid du Colombier noted(NCONT);
1493e12c5d1SDavid du Colombier noted(NDFLT);
1503e12c5d1SDavid du Colombier }
1513e12c5d1SDavid du Colombier
1523e12c5d1SDavid du Colombier void
main(int argc,char * argv[])1533e12c5d1SDavid du Colombier main(int argc, char *argv[])
1543e12c5d1SDavid du Colombier {
1553e12c5d1SDavid du Colombier Ram *r;
1562844884eSDavid du Colombier char *defmnt, *service;
1573e12c5d1SDavid du Colombier int p[2];
1583e12c5d1SDavid du Colombier int fd;
1593e12c5d1SDavid du Colombier int stdio = 0;
1603e12c5d1SDavid du Colombier
161b7b24591SDavid du Colombier service = "ramfs";
1623e12c5d1SDavid du Colombier defmnt = "/tmp";
1633e12c5d1SDavid du Colombier ARGBEGIN{
1643e12c5d1SDavid du Colombier case 'i':
1653e12c5d1SDavid du Colombier defmnt = 0;
1663e12c5d1SDavid du Colombier stdio = 1;
1673e12c5d1SDavid du Colombier mfd[0] = 0;
1683e12c5d1SDavid du Colombier mfd[1] = 1;
1693e12c5d1SDavid du Colombier break;
1703e12c5d1SDavid du Colombier case 'm':
171ab3dc52fSDavid du Colombier defmnt = EARGF(usage());
1723e12c5d1SDavid du Colombier break;
1739a747e4fSDavid du Colombier case 'p':
1749a747e4fSDavid du Colombier private++;
1759a747e4fSDavid du Colombier break;
1762844884eSDavid du Colombier case 's':
1772844884eSDavid du Colombier defmnt = 0;
1782844884eSDavid du Colombier break;
179208510e1SDavid du Colombier case 'u':
180208510e1SDavid du Colombier memlim = 0; /* unlimited memory consumption */
181208510e1SDavid du Colombier break;
1822844884eSDavid du Colombier case 'D':
1832844884eSDavid du Colombier debug = 1;
1842844884eSDavid du Colombier break;
185b7b24591SDavid du Colombier case 'S':
186b7b24591SDavid du Colombier defmnt = 0;
187b7b24591SDavid du Colombier service = EARGF(usage());
188b7b24591SDavid du Colombier break;
1893e12c5d1SDavid du Colombier default:
1903e12c5d1SDavid du Colombier usage();
1913e12c5d1SDavid du Colombier }ARGEND
1923e12c5d1SDavid du Colombier
1933e12c5d1SDavid du Colombier if(pipe(p) < 0)
1943e12c5d1SDavid du Colombier error("pipe failed");
1953e12c5d1SDavid du Colombier if(!stdio){
1963e12c5d1SDavid du Colombier mfd[0] = p[0];
1973e12c5d1SDavid du Colombier mfd[1] = p[0];
1983e12c5d1SDavid du Colombier if(defmnt == 0){
199b7b24591SDavid du Colombier char buf[64];
200b7b24591SDavid du Colombier snprint(buf, sizeof buf, "#s/%s", service);
2019fa41221SDavid du Colombier fd = create(buf, OWRITE|ORCLOSE, 0666);
2023e12c5d1SDavid du Colombier if(fd < 0)
203b7b24591SDavid du Colombier error("create failed");
2043e12c5d1SDavid du Colombier sprint(buf, "%d", p[1]);
2053e12c5d1SDavid du Colombier if(write(fd, buf, strlen(buf)) < 0)
206b7b24591SDavid du Colombier error("writing service file");
2073e12c5d1SDavid du Colombier }
2083e12c5d1SDavid du Colombier }
2093e12c5d1SDavid du Colombier
2109a747e4fSDavid du Colombier user = getuser();
2113e12c5d1SDavid du Colombier notify(notifyf);
2123e12c5d1SDavid du Colombier nram = 1;
2133e12c5d1SDavid du Colombier r = &ram[0];
2143e12c5d1SDavid du Colombier r->busy = 1;
2153e12c5d1SDavid du Colombier r->data = 0;
2163e12c5d1SDavid du Colombier r->ndata = 0;
2179a747e4fSDavid du Colombier r->perm = DMDIR | 0775;
2189a747e4fSDavid du Colombier r->qid.type = QTDIR;
2199a747e4fSDavid du Colombier r->qid.path = 0LL;
2203e12c5d1SDavid du Colombier r->qid.vers = 0;
2213e12c5d1SDavid du Colombier r->parent = 0;
2223e12c5d1SDavid du Colombier r->user = user;
2233e12c5d1SDavid du Colombier r->group = user;
2249a747e4fSDavid du Colombier r->muid = user;
2253e12c5d1SDavid du Colombier r->atime = time(0);
2263e12c5d1SDavid du Colombier r->mtime = r->atime;
2279a747e4fSDavid du Colombier r->name = estrdup(".");
2283e12c5d1SDavid du Colombier
2292844884eSDavid du Colombier if(debug) {
2309a747e4fSDavid du Colombier fmtinstall('F', fcallfmt);
2312844884eSDavid du Colombier fmtinstall('M', dirmodefmt);
2322844884eSDavid du Colombier }
2333e12c5d1SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
2343e12c5d1SDavid du Colombier case -1:
2353e12c5d1SDavid du Colombier error("fork");
2363e12c5d1SDavid du Colombier case 0:
2373e12c5d1SDavid du Colombier close(p[1]);
2383e12c5d1SDavid du Colombier io();
2393e12c5d1SDavid du Colombier break;
2403e12c5d1SDavid du Colombier default:
2413e12c5d1SDavid du Colombier close(p[0]); /* don't deadlock if child fails */
2429a747e4fSDavid du Colombier if(defmnt && mount(p[1], -1, defmnt, MREPL|MCREATE, "") < 0)
2433e12c5d1SDavid du Colombier error("mount failed");
2443e12c5d1SDavid du Colombier }
2453e12c5d1SDavid du Colombier exits(0);
2463e12c5d1SDavid du Colombier }
2473e12c5d1SDavid du Colombier
2483e12c5d1SDavid du Colombier char*
rversion(Fid *)2499a747e4fSDavid du Colombier rversion(Fid*)
2503e12c5d1SDavid du Colombier {
2513e12c5d1SDavid du Colombier Fid *f;
2523e12c5d1SDavid du Colombier
2533e12c5d1SDavid du Colombier for(f = fids; f; f = f->next)
2543e12c5d1SDavid du Colombier if(f->busy)
2553e12c5d1SDavid du Colombier rclunk(f);
2569a747e4fSDavid du Colombier if(thdr.msize > sizeof mdata)
2579a747e4fSDavid du Colombier rhdr.msize = sizeof mdata;
2589a747e4fSDavid du Colombier else
2599a747e4fSDavid du Colombier rhdr.msize = thdr.msize;
2609a747e4fSDavid du Colombier messagesize = rhdr.msize;
2619a747e4fSDavid du Colombier if(strncmp(thdr.version, "9P2000", 6) != 0)
2629a747e4fSDavid du Colombier return Eversion;
2639a747e4fSDavid du Colombier rhdr.version = "9P2000";
2643e12c5d1SDavid du Colombier return 0;
2653e12c5d1SDavid du Colombier }
2663e12c5d1SDavid du Colombier
2673e12c5d1SDavid du Colombier char*
rauth(Fid *)2689a747e4fSDavid du Colombier rauth(Fid*)
2699a747e4fSDavid du Colombier {
2709a747e4fSDavid du Colombier return "ramfs: no authentication required";
2719a747e4fSDavid du Colombier }
2729a747e4fSDavid du Colombier
2739a747e4fSDavid du Colombier char*
rflush(Fid * f)2743e12c5d1SDavid du Colombier rflush(Fid *f)
2753e12c5d1SDavid du Colombier {
2763e12c5d1SDavid du Colombier USED(f);
2773e12c5d1SDavid du Colombier return 0;
2783e12c5d1SDavid du Colombier }
2793e12c5d1SDavid du Colombier
2803e12c5d1SDavid du Colombier char*
rattach(Fid * f)2813e12c5d1SDavid du Colombier rattach(Fid *f)
2823e12c5d1SDavid du Colombier {
2833e12c5d1SDavid du Colombier /* no authentication! */
2843e12c5d1SDavid du Colombier f->busy = 1;
2853e12c5d1SDavid du Colombier f->rclose = 0;
2863e12c5d1SDavid du Colombier f->ram = &ram[0];
2879a747e4fSDavid du Colombier rhdr.qid = f->ram->qid;
2889a747e4fSDavid du Colombier if(thdr.uname[0])
2899a747e4fSDavid du Colombier f->user = estrdup(thdr.uname);
2903e12c5d1SDavid du Colombier else
2913e12c5d1SDavid du Colombier f->user = "none";
2927dd7cddfSDavid du Colombier if(strcmp(user, "none") == 0)
2939a747e4fSDavid du Colombier user = f->user;
2943e12c5d1SDavid du Colombier return 0;
2953e12c5d1SDavid du Colombier }
2963e12c5d1SDavid du Colombier
2973e12c5d1SDavid du Colombier char*
clone(Fid * f,Fid ** nf)2989a747e4fSDavid du Colombier clone(Fid *f, Fid **nf)
2993e12c5d1SDavid du Colombier {
3003e12c5d1SDavid du Colombier if(f->open)
3013e12c5d1SDavid du Colombier return Eisopen;
3023e12c5d1SDavid du Colombier if(f->ram->busy == 0)
3033e12c5d1SDavid du Colombier return Enotexist;
3049a747e4fSDavid du Colombier *nf = newfid(thdr.newfid);
3059a747e4fSDavid du Colombier (*nf)->busy = 1;
3069a747e4fSDavid du Colombier (*nf)->open = 0;
3079a747e4fSDavid du Colombier (*nf)->rclose = 0;
3089a747e4fSDavid du Colombier (*nf)->ram = f->ram;
3099a747e4fSDavid du Colombier (*nf)->user = f->user; /* no ref count; the leakage is minor */
3103e12c5d1SDavid du Colombier return 0;
3113e12c5d1SDavid du Colombier }
3123e12c5d1SDavid du Colombier
3133e12c5d1SDavid du Colombier char*
rwalk(Fid * f)3143e12c5d1SDavid du Colombier rwalk(Fid *f)
3153e12c5d1SDavid du Colombier {
3169a747e4fSDavid du Colombier Ram *r, *fram;
3173e12c5d1SDavid du Colombier char *name;
3183e12c5d1SDavid du Colombier Ram *parent;
3193e12c5d1SDavid du Colombier Fid *nf;
3203e12c5d1SDavid du Colombier char *err;
3219a747e4fSDavid du Colombier ulong t;
3229a747e4fSDavid du Colombier int i;
3233e12c5d1SDavid du Colombier
3249a747e4fSDavid du Colombier err = nil;
3259a747e4fSDavid du Colombier nf = nil;
3269a747e4fSDavid du Colombier rhdr.nwqid = 0;
32759c21d95SDavid du Colombier if(thdr.newfid != thdr.fid){
3289a747e4fSDavid du Colombier err = clone(f, &nf);
3299a747e4fSDavid du Colombier if(err)
3309a747e4fSDavid du Colombier return err;
3319a747e4fSDavid du Colombier f = nf; /* walk the new fid */
3329a747e4fSDavid du Colombier }
3339a747e4fSDavid du Colombier fram = f->ram;
3349a747e4fSDavid du Colombier if(thdr.nwname > 0){
3359a747e4fSDavid du Colombier t = time(0);
3369a747e4fSDavid du Colombier for(i=0; i<thdr.nwname && i<MAXWELEM; i++){
3379a747e4fSDavid du Colombier if((fram->qid.type & QTDIR) == 0){
3389a747e4fSDavid du Colombier err = Enotdir;
3399a747e4fSDavid du Colombier break;
3409a747e4fSDavid du Colombier }
3419a747e4fSDavid du Colombier if(fram->busy == 0){
3429a747e4fSDavid du Colombier err = Enotexist;
3439a747e4fSDavid du Colombier break;
3449a747e4fSDavid du Colombier }
3459a747e4fSDavid du Colombier fram->atime = t;
3469a747e4fSDavid du Colombier name = thdr.wname[i];
3479a747e4fSDavid du Colombier if(strcmp(name, ".") == 0){
3489a747e4fSDavid du Colombier Found:
3499a747e4fSDavid du Colombier rhdr.nwqid++;
3509a747e4fSDavid du Colombier rhdr.wqid[i] = fram->qid;
3519a747e4fSDavid du Colombier continue;
3529a747e4fSDavid du Colombier }
3539a747e4fSDavid du Colombier parent = &ram[fram->parent];
3549a747e4fSDavid du Colombier if(!perm(f, parent, Pexec)){
3559a747e4fSDavid du Colombier err = Eperm;
3569a747e4fSDavid du Colombier break;
3579a747e4fSDavid du Colombier }
3589a747e4fSDavid du Colombier if(strcmp(name, "..") == 0){
3599a747e4fSDavid du Colombier fram = parent;
3609a747e4fSDavid du Colombier goto Found;
3619a747e4fSDavid du Colombier }
3629a747e4fSDavid du Colombier for(r=ram; r < &ram[nram]; r++)
3639a747e4fSDavid du Colombier if(r->busy && r->parent==fram-ram && strcmp(name, r->name)==0){
3649a747e4fSDavid du Colombier fram = r;
3659a747e4fSDavid du Colombier goto Found;
3669a747e4fSDavid du Colombier }
3679a747e4fSDavid du Colombier break;
3689a747e4fSDavid du Colombier }
3699a747e4fSDavid du Colombier if(i==0 && err == nil)
3709a747e4fSDavid du Colombier err = Enotexist;
3719a747e4fSDavid du Colombier }
3729a747e4fSDavid du Colombier if(nf != nil && (err!=nil || rhdr.nwqid<thdr.nwname)){
3739a747e4fSDavid du Colombier /* clunk the new fid, which is the one we walked */
3749a747e4fSDavid du Colombier f->busy = 0;
3759a747e4fSDavid du Colombier f->ram = nil;
3769a747e4fSDavid du Colombier }
3779fa41221SDavid du Colombier if(rhdr.nwqid > 0)
3789fa41221SDavid du Colombier err = nil; /* didn't get everything in 9P2000 right! */
3799a747e4fSDavid du Colombier if(rhdr.nwqid == thdr.nwname) /* update the fid after a successful walk */
3809a747e4fSDavid du Colombier f->ram = fram;
3813e12c5d1SDavid du Colombier return err;
3823e12c5d1SDavid du Colombier }
3833e12c5d1SDavid du Colombier
3843e12c5d1SDavid du Colombier char *
ropen(Fid * f)3853e12c5d1SDavid du Colombier ropen(Fid *f)
3863e12c5d1SDavid du Colombier {
3873e12c5d1SDavid du Colombier Ram *r;
3883e12c5d1SDavid du Colombier int mode, trunc;
3893e12c5d1SDavid du Colombier
3903e12c5d1SDavid du Colombier if(f->open)
3913e12c5d1SDavid du Colombier return Eisopen;
3923e12c5d1SDavid du Colombier r = f->ram;
3933e12c5d1SDavid du Colombier if(r->busy == 0)
3943e12c5d1SDavid du Colombier return Enotexist;
3959a747e4fSDavid du Colombier if(r->perm & DMEXCL)
3963e12c5d1SDavid du Colombier if(r->open)
3973e12c5d1SDavid du Colombier return Excl;
3989a747e4fSDavid du Colombier mode = thdr.mode;
3999a747e4fSDavid du Colombier if(r->qid.type & QTDIR){
4003e12c5d1SDavid du Colombier if(mode != OREAD)
4013e12c5d1SDavid du Colombier return Eperm;
4029a747e4fSDavid du Colombier rhdr.qid = r->qid;
4033e12c5d1SDavid du Colombier return 0;
4043e12c5d1SDavid du Colombier }
4053e12c5d1SDavid du Colombier if(mode & ORCLOSE){
4069a747e4fSDavid du Colombier /* can't remove root; must be able to write parent */
4079a747e4fSDavid du Colombier if(r->qid.path==0 || !perm(f, &ram[r->parent], Pwrite))
4083e12c5d1SDavid du Colombier return Eperm;
4093e12c5d1SDavid du Colombier f->rclose = 1;
4103e12c5d1SDavid du Colombier }
4113e12c5d1SDavid du Colombier trunc = mode & OTRUNC;
4123e12c5d1SDavid du Colombier mode &= OPERM;
4133e12c5d1SDavid du Colombier if(mode==OWRITE || mode==ORDWR || trunc)
4143e12c5d1SDavid du Colombier if(!perm(f, r, Pwrite))
4153e12c5d1SDavid du Colombier return Eperm;
4163e12c5d1SDavid du Colombier if(mode==OREAD || mode==ORDWR)
4173e12c5d1SDavid du Colombier if(!perm(f, r, Pread))
4183e12c5d1SDavid du Colombier return Eperm;
4193e12c5d1SDavid du Colombier if(mode==OEXEC)
4203e12c5d1SDavid du Colombier if(!perm(f, r, Pexec))
4213e12c5d1SDavid du Colombier return Eperm;
4229a747e4fSDavid du Colombier if(trunc && (r->perm&DMAPPEND)==0){
4233e12c5d1SDavid du Colombier r->ndata = 0;
4243e12c5d1SDavid du Colombier if(r->data)
4253e12c5d1SDavid du Colombier free(r->data);
4263e12c5d1SDavid du Colombier r->data = 0;
4273e12c5d1SDavid du Colombier r->qid.vers++;
4283e12c5d1SDavid du Colombier }
4299a747e4fSDavid du Colombier rhdr.qid = r->qid;
4309a747e4fSDavid du Colombier rhdr.iounit = messagesize-IOHDRSZ;
4313e12c5d1SDavid du Colombier f->open = 1;
4323e12c5d1SDavid du Colombier r->open++;
4333e12c5d1SDavid du Colombier return 0;
4343e12c5d1SDavid du Colombier }
4353e12c5d1SDavid du Colombier
4363e12c5d1SDavid du Colombier char *
rcreate(Fid * f)4373e12c5d1SDavid du Colombier rcreate(Fid *f)
4383e12c5d1SDavid du Colombier {
4393e12c5d1SDavid du Colombier Ram *r;
4403e12c5d1SDavid du Colombier char *name;
4413e12c5d1SDavid du Colombier long parent, prm;
4423e12c5d1SDavid du Colombier
4433e12c5d1SDavid du Colombier if(f->open)
4443e12c5d1SDavid du Colombier return Eisopen;
4453e12c5d1SDavid du Colombier if(f->ram->busy == 0)
4463e12c5d1SDavid du Colombier return Enotexist;
4473e12c5d1SDavid du Colombier parent = f->ram - ram;
4489a747e4fSDavid du Colombier if((f->ram->qid.type&QTDIR) == 0)
4493e12c5d1SDavid du Colombier return Enotdir;
4503e12c5d1SDavid du Colombier /* must be able to write parent */
4513e12c5d1SDavid du Colombier if(!perm(f, f->ram, Pwrite))
4523e12c5d1SDavid du Colombier return Eperm;
4539a747e4fSDavid du Colombier prm = thdr.perm;
4549a747e4fSDavid du Colombier name = thdr.name;
4553e12c5d1SDavid du Colombier if(strcmp(name, ".")==0 || strcmp(name, "..")==0)
4563e12c5d1SDavid du Colombier return Ename;
4573e12c5d1SDavid du Colombier for(r=ram; r<&ram[nram]; r++)
4583e12c5d1SDavid du Colombier if(r->busy && parent==r->parent)
4593e12c5d1SDavid du Colombier if(strcmp((char*)name, r->name)==0)
4603e12c5d1SDavid du Colombier return Einuse;
4613e12c5d1SDavid du Colombier for(r=ram; r->busy; r++)
4623e12c5d1SDavid du Colombier if(r == &ram[Nram-1])
4633e12c5d1SDavid du Colombier return "no free ram resources";
4643e12c5d1SDavid du Colombier r->busy = 1;
4653e12c5d1SDavid du Colombier r->qid.path = ++path;
4663e12c5d1SDavid du Colombier r->qid.vers = 0;
4679a747e4fSDavid du Colombier if(prm & DMDIR)
4689a747e4fSDavid du Colombier r->qid.type |= QTDIR;
4693e12c5d1SDavid du Colombier r->parent = parent;
4709a747e4fSDavid du Colombier free(r->name);
4719a747e4fSDavid du Colombier r->name = estrdup(name);
4723e12c5d1SDavid du Colombier r->user = f->user;
4733e12c5d1SDavid du Colombier r->group = f->ram->group;
4749a747e4fSDavid du Colombier r->muid = f->ram->muid;
4759a747e4fSDavid du Colombier if(prm & DMDIR)
4763e12c5d1SDavid du Colombier prm = (prm&~0777) | (f->ram->perm&prm&0777);
4773e12c5d1SDavid du Colombier else
4783e12c5d1SDavid du Colombier prm = (prm&(~0777|0111)) | (f->ram->perm&prm&0666);
4793e12c5d1SDavid du Colombier r->perm = prm;
4803e12c5d1SDavid du Colombier r->ndata = 0;
4813e12c5d1SDavid du Colombier if(r-ram >= nram)
4823e12c5d1SDavid du Colombier nram = r - ram + 1;
4833e12c5d1SDavid du Colombier r->atime = time(0);
4843e12c5d1SDavid du Colombier r->mtime = r->atime;
4853e12c5d1SDavid du Colombier f->ram->mtime = r->atime;
4863e12c5d1SDavid du Colombier f->ram = r;
4879a747e4fSDavid du Colombier rhdr.qid = r->qid;
4889a747e4fSDavid du Colombier rhdr.iounit = messagesize-IOHDRSZ;
4893e12c5d1SDavid du Colombier f->open = 1;
4909a747e4fSDavid du Colombier if(thdr.mode & ORCLOSE)
4917dd7cddfSDavid du Colombier f->rclose = 1;
4923e12c5d1SDavid du Colombier r->open++;
4933e12c5d1SDavid du Colombier return 0;
4943e12c5d1SDavid du Colombier }
4953e12c5d1SDavid du Colombier
4963e12c5d1SDavid du Colombier char*
rread(Fid * f)4973e12c5d1SDavid du Colombier rread(Fid *f)
4983e12c5d1SDavid du Colombier {
4993e12c5d1SDavid du Colombier Ram *r;
5009a747e4fSDavid du Colombier uchar *buf;
5011c576da2SDavid du Colombier vlong off;
5029a747e4fSDavid du Colombier int n, m, cnt;
5033e12c5d1SDavid du Colombier
5043e12c5d1SDavid du Colombier if(f->ram->busy == 0)
5053e12c5d1SDavid du Colombier return Enotexist;
5063e12c5d1SDavid du Colombier n = 0;
5079a747e4fSDavid du Colombier rhdr.count = 0;
508b3b810bfSDavid du Colombier rhdr.data = (char*)rdata;
5091c576da2SDavid du Colombier if (thdr.offset < 0)
5101c576da2SDavid du Colombier return "negative seek offset";
5119a747e4fSDavid du Colombier off = thdr.offset;
5129a747e4fSDavid du Colombier buf = rdata;
5139a747e4fSDavid du Colombier cnt = thdr.count;
5149a747e4fSDavid du Colombier if(cnt > messagesize) /* shouldn't happen, anyway */
5159a747e4fSDavid du Colombier cnt = messagesize;
516b3b810bfSDavid du Colombier if(cnt < 0)
517b3b810bfSDavid du Colombier return "negative read count";
5189a747e4fSDavid du Colombier if(f->ram->qid.type & QTDIR){
5199a747e4fSDavid du Colombier for(r=ram+1; off > 0; r++){
5203e12c5d1SDavid du Colombier if(r->busy && r->parent==f->ram-ram)
5219a747e4fSDavid du Colombier off -= ramstat(r, statbuf, sizeof statbuf);
5223e12c5d1SDavid du Colombier if(r == &ram[nram-1])
5233e12c5d1SDavid du Colombier return 0;
5243e12c5d1SDavid du Colombier }
5253e12c5d1SDavid du Colombier for(; r<&ram[nram] && n < cnt; r++){
5263e12c5d1SDavid du Colombier if(!r->busy || r->parent!=f->ram-ram)
5273e12c5d1SDavid du Colombier continue;
5289a747e4fSDavid du Colombier m = ramstat(r, buf+n, cnt-n);
5299a747e4fSDavid du Colombier if(m == 0)
5309a747e4fSDavid du Colombier break;
5319a747e4fSDavid du Colombier n += m;
5323e12c5d1SDavid du Colombier }
5339a747e4fSDavid du Colombier rhdr.data = (char*)rdata;
5349a747e4fSDavid du Colombier rhdr.count = n;
5353e12c5d1SDavid du Colombier return 0;
5363e12c5d1SDavid du Colombier }
5373e12c5d1SDavid du Colombier r = f->ram;
5383e12c5d1SDavid du Colombier if(off >= r->ndata)
5393e12c5d1SDavid du Colombier return 0;
5403e12c5d1SDavid du Colombier r->atime = time(0);
5413e12c5d1SDavid du Colombier n = cnt;
5423e12c5d1SDavid du Colombier if(off+n > r->ndata)
5433e12c5d1SDavid du Colombier n = r->ndata - off;
5449a747e4fSDavid du Colombier rhdr.data = r->data+off;
5459a747e4fSDavid du Colombier rhdr.count = n;
5463e12c5d1SDavid du Colombier return 0;
5473e12c5d1SDavid du Colombier }
5483e12c5d1SDavid du Colombier
5493e12c5d1SDavid du Colombier char*
rwrite(Fid * f)5503e12c5d1SDavid du Colombier rwrite(Fid *f)
5513e12c5d1SDavid du Colombier {
5523e12c5d1SDavid du Colombier Ram *r;
5531c576da2SDavid du Colombier vlong off;
5543e12c5d1SDavid du Colombier int cnt;
5553e12c5d1SDavid du Colombier
5563e12c5d1SDavid du Colombier r = f->ram;
557b3b810bfSDavid du Colombier rhdr.count = 0;
5583e12c5d1SDavid du Colombier if(r->busy == 0)
5593e12c5d1SDavid du Colombier return Enotexist;
5601c576da2SDavid du Colombier if (thdr.offset < 0)
5611c576da2SDavid du Colombier return "negative seek offset";
5629a747e4fSDavid du Colombier off = thdr.offset;
5639a747e4fSDavid du Colombier if(r->perm & DMAPPEND)
5643e12c5d1SDavid du Colombier off = r->ndata;
5659a747e4fSDavid du Colombier cnt = thdr.count;
566b3b810bfSDavid du Colombier if(cnt < 0)
567b3b810bfSDavid du Colombier return "negative write count";
5689a747e4fSDavid du Colombier if(r->qid.type & QTDIR)
5699a747e4fSDavid du Colombier return Eisdir;
570208510e1SDavid du Colombier if(memlim && off+cnt >= Maxsize) /* sanity check */
5713e12c5d1SDavid du Colombier return "write too big";
5723e12c5d1SDavid du Colombier if(off+cnt > r->ndata)
5733e12c5d1SDavid du Colombier r->data = erealloc(r->data, off+cnt);
5743e12c5d1SDavid du Colombier if(off > r->ndata)
5753e12c5d1SDavid du Colombier memset(r->data+r->ndata, 0, off-r->ndata);
5763e12c5d1SDavid du Colombier if(off+cnt > r->ndata)
5773e12c5d1SDavid du Colombier r->ndata = off+cnt;
5789a747e4fSDavid du Colombier memmove(r->data+off, thdr.data, cnt);
5793e12c5d1SDavid du Colombier r->qid.vers++;
5803e12c5d1SDavid du Colombier r->mtime = time(0);
5819a747e4fSDavid du Colombier rhdr.count = cnt;
5823e12c5d1SDavid du Colombier return 0;
5833e12c5d1SDavid du Colombier }
5843e12c5d1SDavid du Colombier
585162174bbSDavid du Colombier static int
emptydir(Ram * dr)586162174bbSDavid du Colombier emptydir(Ram *dr)
587162174bbSDavid du Colombier {
588162174bbSDavid du Colombier long didx = dr - ram;
589162174bbSDavid du Colombier Ram *r;
590162174bbSDavid du Colombier
591162174bbSDavid du Colombier for(r=ram; r<&ram[nram]; r++)
592162174bbSDavid du Colombier if(r->busy && didx==r->parent)
593162174bbSDavid du Colombier return 0;
594162174bbSDavid du Colombier return 1;
595162174bbSDavid du Colombier }
596162174bbSDavid du Colombier
597162174bbSDavid du Colombier char *
realremove(Ram * r)5983e12c5d1SDavid du Colombier realremove(Ram *r)
5993e12c5d1SDavid du Colombier {
600162174bbSDavid du Colombier if(r->qid.type & QTDIR && !emptydir(r))
601162174bbSDavid du Colombier return Enotempty;
6023e12c5d1SDavid du Colombier r->ndata = 0;
6033e12c5d1SDavid du Colombier if(r->data)
6043e12c5d1SDavid du Colombier free(r->data);
6053e12c5d1SDavid du Colombier r->data = 0;
6063e12c5d1SDavid du Colombier r->parent = 0;
6079a747e4fSDavid du Colombier memset(&r->qid, 0, sizeof r->qid);
6089a747e4fSDavid du Colombier free(r->name);
6099a747e4fSDavid du Colombier r->name = nil;
6103e12c5d1SDavid du Colombier r->busy = 0;
611162174bbSDavid du Colombier return nil;
6123e12c5d1SDavid du Colombier }
6133e12c5d1SDavid du Colombier
6143e12c5d1SDavid du Colombier char *
rclunk(Fid * f)6153e12c5d1SDavid du Colombier rclunk(Fid *f)
6163e12c5d1SDavid du Colombier {
617162174bbSDavid du Colombier char *e = nil;
618162174bbSDavid du Colombier
6193e12c5d1SDavid du Colombier if(f->open)
6203e12c5d1SDavid du Colombier f->ram->open--;
6213e12c5d1SDavid du Colombier if(f->rclose)
622162174bbSDavid du Colombier e = realremove(f->ram);
6233e12c5d1SDavid du Colombier f->busy = 0;
6243e12c5d1SDavid du Colombier f->open = 0;
6253e12c5d1SDavid du Colombier f->ram = 0;
626162174bbSDavid du Colombier return e;
6273e12c5d1SDavid du Colombier }
6283e12c5d1SDavid du Colombier
6293e12c5d1SDavid du Colombier char *
rremove(Fid * f)6303e12c5d1SDavid du Colombier rremove(Fid *f)
6313e12c5d1SDavid du Colombier {
6323e12c5d1SDavid du Colombier Ram *r;
6333e12c5d1SDavid du Colombier
6343e12c5d1SDavid du Colombier if(f->open)
6353e12c5d1SDavid du Colombier f->ram->open--;
6363e12c5d1SDavid du Colombier f->busy = 0;
6373e12c5d1SDavid du Colombier f->open = 0;
6383e12c5d1SDavid du Colombier r = f->ram;
6393e12c5d1SDavid du Colombier f->ram = 0;
6409a747e4fSDavid du Colombier if(r->qid.path == 0 || !perm(f, &ram[r->parent], Pwrite))
6413e12c5d1SDavid du Colombier return Eperm;
6423e12c5d1SDavid du Colombier ram[r->parent].mtime = time(0);
643162174bbSDavid du Colombier return realremove(r);
6443e12c5d1SDavid du Colombier }
6453e12c5d1SDavid du Colombier
6463e12c5d1SDavid du Colombier char *
rstat(Fid * f)6473e12c5d1SDavid du Colombier rstat(Fid *f)
6483e12c5d1SDavid du Colombier {
6493e12c5d1SDavid du Colombier if(f->ram->busy == 0)
6503e12c5d1SDavid du Colombier return Enotexist;
6519a747e4fSDavid du Colombier rhdr.nstat = ramstat(f->ram, statbuf, sizeof statbuf);
6529a747e4fSDavid du Colombier rhdr.stat = statbuf;
6533e12c5d1SDavid du Colombier return 0;
6543e12c5d1SDavid du Colombier }
6553e12c5d1SDavid du Colombier
6563e12c5d1SDavid du Colombier char *
rwstat(Fid * f)6573e12c5d1SDavid du Colombier rwstat(Fid *f)
6583e12c5d1SDavid du Colombier {
6593e12c5d1SDavid du Colombier Ram *r, *s;
6603e12c5d1SDavid du Colombier Dir dir;
6613e12c5d1SDavid du Colombier
6623e12c5d1SDavid du Colombier if(f->ram->busy == 0)
6633e12c5d1SDavid du Colombier return Enotexist;
6649a747e4fSDavid du Colombier convM2D(thdr.stat, thdr.nstat, &dir, (char*)statbuf);
6653e12c5d1SDavid du Colombier r = f->ram;
6663e12c5d1SDavid du Colombier
6673e12c5d1SDavid du Colombier /*
6689a747e4fSDavid du Colombier * To change length, must have write permission on file.
6699a747e4fSDavid du Colombier */
6709a747e4fSDavid du Colombier if(dir.length!=~0 && dir.length!=r->ndata){
6719a747e4fSDavid du Colombier if(!perm(f, r, Pwrite))
6729a747e4fSDavid du Colombier return Eperm;
6739a747e4fSDavid du Colombier }
6749a747e4fSDavid du Colombier
6759a747e4fSDavid du Colombier /*
6763e12c5d1SDavid du Colombier * To change name, must have write permission in parent
6773e12c5d1SDavid du Colombier * and name must be unique.
6783e12c5d1SDavid du Colombier */
6799a747e4fSDavid du Colombier if(dir.name[0]!='\0' && strcmp(dir.name, r->name)!=0){
6803e12c5d1SDavid du Colombier if(!perm(f, &ram[r->parent], Pwrite))
6813e12c5d1SDavid du Colombier return Eperm;
6823e12c5d1SDavid du Colombier for(s=ram; s<&ram[nram]; s++)
6833e12c5d1SDavid du Colombier if(s->busy && s->parent==r->parent)
6843e12c5d1SDavid du Colombier if(strcmp(dir.name, s->name)==0)
6853e12c5d1SDavid du Colombier return Eexist;
6863e12c5d1SDavid du Colombier }
6873e12c5d1SDavid du Colombier
6883e12c5d1SDavid du Colombier /*
6899a747e4fSDavid du Colombier * To change mode, must be owner or group leader.
6903e12c5d1SDavid du Colombier * Because of lack of users file, leader=>group itself.
6913e12c5d1SDavid du Colombier */
6929a747e4fSDavid du Colombier if(dir.mode!=~0 && r->perm!=dir.mode){
6933e12c5d1SDavid du Colombier if(strcmp(f->user, r->user) != 0)
6943e12c5d1SDavid du Colombier if(strcmp(f->user, r->group) != 0)
6953e12c5d1SDavid du Colombier return Enotowner;
6963e12c5d1SDavid du Colombier }
6973e12c5d1SDavid du Colombier
6983e12c5d1SDavid du Colombier /*
6993e12c5d1SDavid du Colombier * To change group, must be owner and member of new group,
7003e12c5d1SDavid du Colombier * or leader of current group and leader of new group.
7013e12c5d1SDavid du Colombier * Second case cannot happen, but we check anyway.
7023e12c5d1SDavid du Colombier */
7039a747e4fSDavid du Colombier if(dir.gid[0]!='\0' && strcmp(r->group, dir.gid)!=0){
7043e12c5d1SDavid du Colombier if(strcmp(f->user, r->user) == 0)
705dc5a79c1SDavid du Colombier // if(strcmp(f->user, dir.gid) == 0)
7063e12c5d1SDavid du Colombier goto ok;
7073e12c5d1SDavid du Colombier if(strcmp(f->user, r->group) == 0)
7083e12c5d1SDavid du Colombier if(strcmp(f->user, dir.gid) == 0)
7093e12c5d1SDavid du Colombier goto ok;
7103e12c5d1SDavid du Colombier return Enotowner;
7113e12c5d1SDavid du Colombier ok:;
7123e12c5d1SDavid du Colombier }
7133e12c5d1SDavid du Colombier
7143e12c5d1SDavid du Colombier /* all ok; do it */
7159a747e4fSDavid du Colombier if(dir.mode != ~0){
7169a747e4fSDavid du Colombier dir.mode &= ~DMDIR; /* cannot change dir bit */
7179a747e4fSDavid du Colombier dir.mode |= r->perm&DMDIR;
7183e12c5d1SDavid du Colombier r->perm = dir.mode;
7199a747e4fSDavid du Colombier }
7209a747e4fSDavid du Colombier if(dir.name[0] != '\0'){
7219a747e4fSDavid du Colombier free(r->name);
7229a747e4fSDavid du Colombier r->name = estrdup(dir.name);
7239a747e4fSDavid du Colombier }
7249a747e4fSDavid du Colombier if(dir.gid[0] != '\0')
7259a747e4fSDavid du Colombier r->group = estrdup(dir.gid);
7269a747e4fSDavid du Colombier if(dir.length!=~0 && dir.length!=r->ndata){
7279a747e4fSDavid du Colombier r->data = erealloc(r->data, dir.length);
7289a747e4fSDavid du Colombier if(r->ndata < dir.length)
7299a747e4fSDavid du Colombier memset(r->data+r->ndata, 0, dir.length-r->ndata);
7309a747e4fSDavid du Colombier r->ndata = dir.length;
7319a747e4fSDavid du Colombier }
7323e12c5d1SDavid du Colombier ram[r->parent].mtime = time(0);
7333e12c5d1SDavid du Colombier return 0;
7343e12c5d1SDavid du Colombier }
7353e12c5d1SDavid du Colombier
7369a747e4fSDavid du Colombier uint
ramstat(Ram * r,uchar * buf,uint nbuf)7379a747e4fSDavid du Colombier ramstat(Ram *r, uchar *buf, uint nbuf)
7383e12c5d1SDavid du Colombier {
7396b6b9ac8SDavid du Colombier int n;
7403e12c5d1SDavid du Colombier Dir dir;
7413e12c5d1SDavid du Colombier
7429a747e4fSDavid du Colombier dir.name = r->name;
7433e12c5d1SDavid du Colombier dir.qid = r->qid;
7443e12c5d1SDavid du Colombier dir.mode = r->perm;
7453e12c5d1SDavid du Colombier dir.length = r->ndata;
7469a747e4fSDavid du Colombier dir.uid = r->user;
7479a747e4fSDavid du Colombier dir.gid = r->group;
7489a747e4fSDavid du Colombier dir.muid = r->muid;
7493e12c5d1SDavid du Colombier dir.atime = r->atime;
7503e12c5d1SDavid du Colombier dir.mtime = r->mtime;
7516b6b9ac8SDavid du Colombier n = convD2M(&dir, buf, nbuf);
7526b6b9ac8SDavid du Colombier if(n > 2)
7536b6b9ac8SDavid du Colombier return n;
7546b6b9ac8SDavid du Colombier return 0;
7553e12c5d1SDavid du Colombier }
7563e12c5d1SDavid du Colombier
7573e12c5d1SDavid du Colombier Fid *
newfid(int fid)7583e12c5d1SDavid du Colombier newfid(int fid)
7593e12c5d1SDavid du Colombier {
7603e12c5d1SDavid du Colombier Fid *f, *ff;
7613e12c5d1SDavid du Colombier
7623e12c5d1SDavid du Colombier ff = 0;
7633e12c5d1SDavid du Colombier for(f = fids; f; f = f->next)
7643e12c5d1SDavid du Colombier if(f->fid == fid)
7653e12c5d1SDavid du Colombier return f;
7663e12c5d1SDavid du Colombier else if(!ff && !f->busy)
7673e12c5d1SDavid du Colombier ff = f;
7683e12c5d1SDavid du Colombier if(ff){
7693e12c5d1SDavid du Colombier ff->fid = fid;
7703e12c5d1SDavid du Colombier return ff;
7713e12c5d1SDavid du Colombier }
7723e12c5d1SDavid du Colombier f = emalloc(sizeof *f);
7737dd7cddfSDavid du Colombier f->ram = nil;
7743e12c5d1SDavid du Colombier f->fid = fid;
7753e12c5d1SDavid du Colombier f->next = fids;
7763e12c5d1SDavid du Colombier fids = f;
7773e12c5d1SDavid du Colombier return f;
7783e12c5d1SDavid du Colombier }
7793e12c5d1SDavid du Colombier
7803e12c5d1SDavid du Colombier void
io(void)7813e12c5d1SDavid du Colombier io(void)
7823e12c5d1SDavid du Colombier {
78324e2e655SDavid du Colombier char *err, buf[40];
7849a747e4fSDavid du Colombier int n, pid, ctl;
7859fa41221SDavid du Colombier Fid *fid;
7869a747e4fSDavid du Colombier
7879a747e4fSDavid du Colombier pid = getpid();
7889a747e4fSDavid du Colombier if(private){
7899a747e4fSDavid du Colombier snprint(buf, sizeof buf, "/proc/%d/ctl", pid);
7909a747e4fSDavid du Colombier ctl = open(buf, OWRITE);
7919a747e4fSDavid du Colombier if(ctl < 0){
7929a747e4fSDavid du Colombier fprint(2, "can't protect ramfs\n");
7939a747e4fSDavid du Colombier }else{
7949a747e4fSDavid du Colombier fprint(ctl, "noswap\n");
7959a747e4fSDavid du Colombier fprint(ctl, "private\n");
7969a747e4fSDavid du Colombier close(ctl);
7979a747e4fSDavid du Colombier }
7989a747e4fSDavid du Colombier }
7993e12c5d1SDavid du Colombier
8003e12c5d1SDavid du Colombier for(;;){
8013e12c5d1SDavid du Colombier /*
8023e12c5d1SDavid du Colombier * reading from a pipe or a network device
8039a747e4fSDavid du Colombier * will give an error after a few eof reads.
8043e12c5d1SDavid du Colombier * however, we cannot tell the difference
8053e12c5d1SDavid du Colombier * between a zero-length read and an interrupt
8063e12c5d1SDavid du Colombier * on the processes writing to us,
8079a747e4fSDavid du Colombier * so we wait for the error.
8083e12c5d1SDavid du Colombier */
8099a747e4fSDavid du Colombier n = read9pmsg(mfd[0], mdata, messagesize);
81024e2e655SDavid du Colombier if(n < 0){
81173e742d7SDavid du Colombier rerrstr(buf, sizeof buf);
81224e2e655SDavid du Colombier if(buf[0]=='\0' || strstr(buf, "hungup"))
81324e2e655SDavid du Colombier exits("");
81424e2e655SDavid du Colombier error("mount read");
81524e2e655SDavid du Colombier }
8169a747e4fSDavid du Colombier if(n == 0)
8179a747e4fSDavid du Colombier continue;
8189a747e4fSDavid du Colombier if(convM2S(mdata, n, &thdr) == 0)
8193e12c5d1SDavid du Colombier continue;
8203e12c5d1SDavid du Colombier
821219b2ee8SDavid du Colombier if(debug)
8229a747e4fSDavid du Colombier fprint(2, "ramfs %d:<-%F\n", pid, &thdr);
8233e12c5d1SDavid du Colombier
8249fa41221SDavid du Colombier if(thdr.type<0 || thdr.type>=nelem(fcalls) || !fcalls[thdr.type])
8253e12c5d1SDavid du Colombier err = "bad fcall type";
8269fa41221SDavid du Colombier else if(((fid=newfid(thdr.fid))==nil || !fid->ram) && needfid[thdr.type])
8279fa41221SDavid du Colombier err = "fid not in use";
8283e12c5d1SDavid du Colombier else
8299fa41221SDavid du Colombier err = (*fcalls[thdr.type])(fid);
8303e12c5d1SDavid du Colombier if(err){
8319a747e4fSDavid du Colombier rhdr.type = Rerror;
8329a747e4fSDavid du Colombier rhdr.ename = err;
8333e12c5d1SDavid du Colombier }else{
8349a747e4fSDavid du Colombier rhdr.type = thdr.type + 1;
8359a747e4fSDavid du Colombier rhdr.fid = thdr.fid;
8363e12c5d1SDavid du Colombier }
8379a747e4fSDavid du Colombier rhdr.tag = thdr.tag;
838219b2ee8SDavid du Colombier if(debug)
8399a747e4fSDavid du Colombier fprint(2, "ramfs %d:->%F\n", pid, &rhdr);/**/
8409a747e4fSDavid du Colombier n = convS2M(&rhdr, mdata, messagesize);
8419a747e4fSDavid du Colombier if(n == 0)
8429a747e4fSDavid du Colombier error("convS2M error on write");
8433e12c5d1SDavid du Colombier if(write(mfd[1], mdata, n) != n)
8443e12c5d1SDavid du Colombier error("mount write");
8453e12c5d1SDavid du Colombier }
8463e12c5d1SDavid du Colombier }
8473e12c5d1SDavid du Colombier
8483e12c5d1SDavid du Colombier int
perm(Fid * f,Ram * r,int p)8493e12c5d1SDavid du Colombier perm(Fid *f, Ram *r, int p)
8503e12c5d1SDavid du Colombier {
8513e12c5d1SDavid du Colombier if((p*Pother) & r->perm)
8523e12c5d1SDavid du Colombier return 1;
8533e12c5d1SDavid du Colombier if(strcmp(f->user, r->group)==0 && ((p*Pgroup) & r->perm))
8543e12c5d1SDavid du Colombier return 1;
8553e12c5d1SDavid du Colombier if(strcmp(f->user, r->user)==0 && ((p*Powner) & r->perm))
8563e12c5d1SDavid du Colombier return 1;
8573e12c5d1SDavid du Colombier return 0;
8583e12c5d1SDavid du Colombier }
8593e12c5d1SDavid du Colombier
8603e12c5d1SDavid du Colombier void
error(char * s)8613e12c5d1SDavid du Colombier error(char *s)
8623e12c5d1SDavid du Colombier {
863219b2ee8SDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, s);
8643e12c5d1SDavid du Colombier exits(s);
8653e12c5d1SDavid du Colombier }
8663e12c5d1SDavid du Colombier
8673e12c5d1SDavid du Colombier void *
emalloc(ulong n)8683e12c5d1SDavid du Colombier emalloc(ulong n)
8693e12c5d1SDavid du Colombier {
8703e12c5d1SDavid du Colombier void *p;
8713e12c5d1SDavid du Colombier
8723e12c5d1SDavid du Colombier p = malloc(n);
8733e12c5d1SDavid du Colombier if(!p)
8743e12c5d1SDavid du Colombier error("out of memory");
8757dd7cddfSDavid du Colombier memset(p, 0, n);
8763e12c5d1SDavid du Colombier return p;
8773e12c5d1SDavid du Colombier }
8783e12c5d1SDavid du Colombier
8793e12c5d1SDavid du Colombier void *
erealloc(void * p,ulong n)8803e12c5d1SDavid du Colombier erealloc(void *p, ulong n)
8813e12c5d1SDavid du Colombier {
8823e12c5d1SDavid du Colombier p = realloc(p, n);
8833e12c5d1SDavid du Colombier if(!p)
8843e12c5d1SDavid du Colombier error("out of memory");
8853e12c5d1SDavid du Colombier return p;
8863e12c5d1SDavid du Colombier }
8873e12c5d1SDavid du Colombier
8889a747e4fSDavid du Colombier char *
estrdup(char * q)8899a747e4fSDavid du Colombier estrdup(char *q)
8909a747e4fSDavid du Colombier {
8919a747e4fSDavid du Colombier char *p;
8929a747e4fSDavid du Colombier int n;
8939a747e4fSDavid du Colombier
8949a747e4fSDavid du Colombier n = strlen(q)+1;
8959a747e4fSDavid du Colombier p = malloc(n);
8969a747e4fSDavid du Colombier if(!p)
8979a747e4fSDavid du Colombier error("out of memory");
8989a747e4fSDavid du Colombier memmove(p, q, n);
8999a747e4fSDavid du Colombier return p;
9009a747e4fSDavid du Colombier }
9019a747e4fSDavid du Colombier
9023e12c5d1SDavid du Colombier void
usage(void)9033e12c5d1SDavid du Colombier usage(void)
9043e12c5d1SDavid du Colombier {
905208510e1SDavid du Colombier fprint(2, "usage: %s [-Dipsu] [-m mountpoint] [-S srvname]\n", argv0);
9063e12c5d1SDavid du Colombier exits("usage");
9073e12c5d1SDavid du Colombier }
908