17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
87dd7cddfSDavid du Colombier #include <frame.h>
97dd7cddfSDavid du Colombier #include <fcall.h>
107dd7cddfSDavid du Colombier #include "dat.h"
117dd7cddfSDavid du Colombier #include "fns.h"
127dd7cddfSDavid du Colombier
137dd7cddfSDavid du Colombier char Eperm[] = "permission denied";
147dd7cddfSDavid du Colombier char Eexist[] = "file does not exist";
157dd7cddfSDavid du Colombier char Enotdir[] = "not a directory";
167dd7cddfSDavid du Colombier char Ebadfcall[] = "bad fcall type";
177dd7cddfSDavid du Colombier char Eoffset[] = "illegal offset";
187dd7cddfSDavid du Colombier
19*9a747e4fSDavid du Colombier int messagesize = 8192+IOHDRSZ; /* good start */
20*9a747e4fSDavid du Colombier
21*9a747e4fSDavid du Colombier enum{
22*9a747e4fSDavid du Colombier DEBUG = 0
23*9a747e4fSDavid du Colombier };
24*9a747e4fSDavid du Colombier
257dd7cddfSDavid du Colombier Dirtab dirtab[]=
267dd7cddfSDavid du Colombier {
27*9a747e4fSDavid du Colombier { ".", QTDIR, Qdir, 0500|DMDIR },
28*9a747e4fSDavid du Colombier { "cons", QTFILE, Qcons, 0600 },
29*9a747e4fSDavid du Colombier { "cursor", QTFILE, Qcursor, 0600 },
30*9a747e4fSDavid du Colombier { "consctl", QTFILE, Qconsctl, 0200 },
31*9a747e4fSDavid du Colombier { "winid", QTFILE, Qwinid, 0400 },
32*9a747e4fSDavid du Colombier { "winname", QTFILE, Qwinname, 0400 },
33*9a747e4fSDavid du Colombier { "kbdin", QTFILE, Qkbdin, 0200 },
34*9a747e4fSDavid du Colombier { "label", QTFILE, Qlabel, 0600 },
35*9a747e4fSDavid du Colombier { "mouse", QTFILE, Qmouse, 0600 },
36*9a747e4fSDavid du Colombier { "screen", QTFILE, Qscreen, 0400 },
37*9a747e4fSDavid du Colombier { "snarf", QTFILE, Qsnarf, 0600 },
38*9a747e4fSDavid du Colombier { "text", QTFILE, Qtext, 0400 },
39*9a747e4fSDavid du Colombier { "wdir", QTFILE, Qwdir, 0600 },
40*9a747e4fSDavid du Colombier { "wctl", QTFILE, Qwctl, 0600 },
41*9a747e4fSDavid du Colombier { "window", QTFILE, Qwindow, 0400 },
42*9a747e4fSDavid du Colombier { "wsys", QTDIR, Qwsys, 0500|DMDIR },
437dd7cddfSDavid du Colombier { nil, }
447dd7cddfSDavid du Colombier };
457dd7cddfSDavid du Colombier
467dd7cddfSDavid du Colombier static uint getclock(void);
477dd7cddfSDavid du Colombier static void filsysproc(void*);
487dd7cddfSDavid du Colombier static Fid* newfid(Filsys*, int);
49*9a747e4fSDavid du Colombier static int dostat(Filsys*, int, Dirtab*, uchar*, int, uint);
507dd7cddfSDavid du Colombier
517dd7cddfSDavid du Colombier int clockfd;
52*9a747e4fSDavid du Colombier int firstmessage = 1;
537dd7cddfSDavid du Colombier
547dd7cddfSDavid du Colombier char srvpipe[64];
557dd7cddfSDavid du Colombier char srvwctl[64];
567dd7cddfSDavid du Colombier
577dd7cddfSDavid du Colombier static Xfid* filsysflush(Filsys*, Xfid*, Fid*);
58*9a747e4fSDavid du Colombier static Xfid* filsysversion(Filsys*, Xfid*, Fid*);
59*9a747e4fSDavid du Colombier static Xfid* filsysauth(Filsys*, Xfid*, Fid*);
607dd7cddfSDavid du Colombier static Xfid* filsysnop(Filsys*, Xfid*, Fid*);
617dd7cddfSDavid du Colombier static Xfid* filsysattach(Filsys*, Xfid*, Fid*);
627dd7cddfSDavid du Colombier static Xfid* filsyswalk(Filsys*, Xfid*, Fid*);
637dd7cddfSDavid du Colombier static Xfid* filsysopen(Filsys*, Xfid*, Fid*);
647dd7cddfSDavid du Colombier static Xfid* filsyscreate(Filsys*, Xfid*, Fid*);
657dd7cddfSDavid du Colombier static Xfid* filsysread(Filsys*, Xfid*, Fid*);
667dd7cddfSDavid du Colombier static Xfid* filsyswrite(Filsys*, Xfid*, Fid*);
677dd7cddfSDavid du Colombier static Xfid* filsysclunk(Filsys*, Xfid*, Fid*);
687dd7cddfSDavid du Colombier static Xfid* filsysremove(Filsys*, Xfid*, Fid*);
697dd7cddfSDavid du Colombier static Xfid* filsysstat(Filsys*, Xfid*, Fid*);
707dd7cddfSDavid du Colombier static Xfid* filsyswstat(Filsys*, Xfid*, Fid*);
717dd7cddfSDavid du Colombier
727dd7cddfSDavid du Colombier Xfid* (*fcall[Tmax])(Filsys*, Xfid*, Fid*) =
737dd7cddfSDavid du Colombier {
747dd7cddfSDavid du Colombier [Tflush] = filsysflush,
75*9a747e4fSDavid du Colombier [Tversion] = filsysversion,
76*9a747e4fSDavid du Colombier [Tauth] = filsysauth,
777dd7cddfSDavid du Colombier [Tattach] = filsysattach,
787dd7cddfSDavid du Colombier [Twalk] = filsyswalk,
797dd7cddfSDavid du Colombier [Topen] = filsysopen,
807dd7cddfSDavid du Colombier [Tcreate] = filsyscreate,
817dd7cddfSDavid du Colombier [Tread] = filsysread,
827dd7cddfSDavid du Colombier [Twrite] = filsyswrite,
837dd7cddfSDavid du Colombier [Tclunk] = filsysclunk,
847dd7cddfSDavid du Colombier [Tremove]= filsysremove,
857dd7cddfSDavid du Colombier [Tstat] = filsysstat,
867dd7cddfSDavid du Colombier [Twstat] = filsyswstat,
877dd7cddfSDavid du Colombier };
887dd7cddfSDavid du Colombier
897dd7cddfSDavid du Colombier void
post(char * name,char * envname,int srvfd)907dd7cddfSDavid du Colombier post(char *name, char *envname, int srvfd)
917dd7cddfSDavid du Colombier {
927dd7cddfSDavid du Colombier int fd;
937dd7cddfSDavid du Colombier char buf[32];
947dd7cddfSDavid du Colombier
95*9a747e4fSDavid du Colombier fd = create(name, OWRITE|ORCLOSE|OCEXEC, 0600);
967dd7cddfSDavid du Colombier if(fd < 0)
977dd7cddfSDavid du Colombier error(name);
987dd7cddfSDavid du Colombier sprint(buf, "%d",srvfd);
997dd7cddfSDavid du Colombier if(write(fd, buf, strlen(buf)) != strlen(buf))
1007dd7cddfSDavid du Colombier error("srv write");
1017dd7cddfSDavid du Colombier putenv(envname, name);
1027dd7cddfSDavid du Colombier }
1037dd7cddfSDavid du Colombier
1047dd7cddfSDavid du Colombier /*
1057dd7cddfSDavid du Colombier * Build pipe with OCEXEC set on second fd.
1067dd7cddfSDavid du Colombier * Can't put it on both because we want to post one in /srv.
1077dd7cddfSDavid du Colombier */
1087dd7cddfSDavid du Colombier int
cexecpipe(int * p0,int * p1)1097dd7cddfSDavid du Colombier cexecpipe(int *p0, int *p1)
1107dd7cddfSDavid du Colombier {
1117dd7cddfSDavid du Colombier /* pipe the hard way to get close on exec */
112*9a747e4fSDavid du Colombier if(bind("#|", "/mnt/temp", MREPL) < 0)
1137dd7cddfSDavid du Colombier return -1;
114*9a747e4fSDavid du Colombier *p0 = open("/mnt/temp/data", ORDWR);
115*9a747e4fSDavid du Colombier *p1 = open("/mnt/temp/data1", ORDWR|OCEXEC);
116*9a747e4fSDavid du Colombier unmount(nil, "/mnt/temp");
1177dd7cddfSDavid du Colombier if(*p0<0 || *p1<0)
1187dd7cddfSDavid du Colombier return -1;
1197dd7cddfSDavid du Colombier return 0;
1207dd7cddfSDavid du Colombier }
1217dd7cddfSDavid du Colombier
1227dd7cddfSDavid du Colombier Filsys*
filsysinit(Channel * cxfidalloc)1237dd7cddfSDavid du Colombier filsysinit(Channel *cxfidalloc)
1247dd7cddfSDavid du Colombier {
1257dd7cddfSDavid du Colombier int n, fd, pid, p0;
1267dd7cddfSDavid du Colombier Filsys *fs;
1277dd7cddfSDavid du Colombier Channel *c;
128*9a747e4fSDavid du Colombier char buf[128];
1297dd7cddfSDavid du Colombier
1307dd7cddfSDavid du Colombier fs = emalloc(sizeof(Filsys));
1317dd7cddfSDavid du Colombier if(cexecpipe(&fs->cfd, &fs->sfd) < 0)
1327dd7cddfSDavid du Colombier goto Rescue;
133*9a747e4fSDavid du Colombier fmtinstall('F', fcallfmt);
1347dd7cddfSDavid du Colombier clockfd = open("/dev/time", OREAD|OCEXEC);
1357dd7cddfSDavid du Colombier fd = open("/dev/user", OREAD);
136*9a747e4fSDavid du Colombier strcpy(buf, "Jean-Paul_Belmondo");
1377dd7cddfSDavid du Colombier if(fd >= 0){
138*9a747e4fSDavid du Colombier n = read(fd, buf, sizeof buf-1);
1397dd7cddfSDavid du Colombier if(n > 0)
140*9a747e4fSDavid du Colombier buf[n] = 0;
1417dd7cddfSDavid du Colombier close(fd);
1427dd7cddfSDavid du Colombier }
143*9a747e4fSDavid du Colombier fs->user = estrdup(buf);
1447dd7cddfSDavid du Colombier fs->cxfidalloc = cxfidalloc;
1457dd7cddfSDavid du Colombier pid = getpid();
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier /*
1487dd7cddfSDavid du Colombier * Create and post wctl pipe
1497dd7cddfSDavid du Colombier */
1507dd7cddfSDavid du Colombier if(cexecpipe(&p0, &wctlfd) < 0)
1517dd7cddfSDavid du Colombier goto Rescue;
1527dd7cddfSDavid du Colombier sprint(srvwctl, "/srv/riowctl.%s.%d", fs->user, pid);
1537dd7cddfSDavid du Colombier post(srvwctl, "wctl", p0);
1547dd7cddfSDavid du Colombier close(p0);
1557dd7cddfSDavid du Colombier
1567dd7cddfSDavid du Colombier /*
1577dd7cddfSDavid du Colombier * Start server processes
1587dd7cddfSDavid du Colombier */
1597dd7cddfSDavid du Colombier c = chancreate(sizeof(char*), 0);
1607dd7cddfSDavid du Colombier if(c == nil)
1617dd7cddfSDavid du Colombier error("wctl channel");
1627dd7cddfSDavid du Colombier proccreate(wctlproc, c, 4096);
1637dd7cddfSDavid du Colombier threadcreate(wctlthread, c, 4096);
1647dd7cddfSDavid du Colombier proccreate(filsysproc, fs, 10000);
1657dd7cddfSDavid du Colombier
166*9a747e4fSDavid du Colombier /*
167*9a747e4fSDavid du Colombier * Post srv pipe
168*9a747e4fSDavid du Colombier */
169*9a747e4fSDavid du Colombier sprint(srvpipe, "/srv/rio.%s.%d", fs->user, pid);
170*9a747e4fSDavid du Colombier post(srvpipe, "wsys", fs->cfd);
171*9a747e4fSDavid du Colombier
1727dd7cddfSDavid du Colombier return fs;
1737dd7cddfSDavid du Colombier
1747dd7cddfSDavid du Colombier Rescue:
1757dd7cddfSDavid du Colombier free(fs);
1767dd7cddfSDavid du Colombier return nil;
1777dd7cddfSDavid du Colombier }
1787dd7cddfSDavid du Colombier
1797dd7cddfSDavid du Colombier static
1807dd7cddfSDavid du Colombier void
filsysproc(void * arg)1817dd7cddfSDavid du Colombier filsysproc(void *arg)
1827dd7cddfSDavid du Colombier {
1837dd7cddfSDavid du Colombier int n;
1847dd7cddfSDavid du Colombier Xfid *x;
1857dd7cddfSDavid du Colombier Fid *f;
1867dd7cddfSDavid du Colombier Fcall t;
187*9a747e4fSDavid du Colombier uchar *buf;
1887dd7cddfSDavid du Colombier Filsys *fs;
1897dd7cddfSDavid du Colombier
19059cc4ca5SDavid du Colombier threadsetname("FILSYSPROC");
1917dd7cddfSDavid du Colombier fs = arg;
1927dd7cddfSDavid du Colombier fs->pid = getpid();
1937dd7cddfSDavid du Colombier x = nil;
1947dd7cddfSDavid du Colombier for(;;){
195*9a747e4fSDavid du Colombier buf = emalloc(messagesize+UTFmax); /* UTFmax for appending partial rune in xfidwrite */
196*9a747e4fSDavid du Colombier n = read9pmsg(fs->sfd, buf, messagesize);
19759cc4ca5SDavid du Colombier if(n <= 0){
198*9a747e4fSDavid du Colombier yield(); /* if threadexitsall'ing, will not return */
199*9a747e4fSDavid du Colombier fprint(2, "rio: %d: read9pmsg: %d %r\n", getpid(), n);
20059cc4ca5SDavid du Colombier errorshouldabort = 0;
20159cc4ca5SDavid du Colombier error("eof or i/o error on server channel");
20259cc4ca5SDavid du Colombier }
2037dd7cddfSDavid du Colombier if(x == nil){
2047dd7cddfSDavid du Colombier send(fs->cxfidalloc, nil);
2057dd7cddfSDavid du Colombier recv(fs->cxfidalloc, &x);
2067dd7cddfSDavid du Colombier x->fs = fs;
2077dd7cddfSDavid du Colombier }
2087dd7cddfSDavid du Colombier x->buf = buf;
209*9a747e4fSDavid du Colombier if(convM2S(buf, n, x) != n)
2107dd7cddfSDavid du Colombier error("convert error in convM2S");
211*9a747e4fSDavid du Colombier if(DEBUG)
212*9a747e4fSDavid du Colombier fprint(2, "rio:<-%F\n", &x->Fcall);
2137dd7cddfSDavid du Colombier if(fcall[x->type] == nil)
2147dd7cddfSDavid du Colombier x = filsysrespond(fs, x, &t, Ebadfcall);
2157dd7cddfSDavid du Colombier else{
216*9a747e4fSDavid du Colombier if(x->type==Tversion || x->type==Tauth)
2177dd7cddfSDavid du Colombier f = nil;
2187dd7cddfSDavid du Colombier else
2197dd7cddfSDavid du Colombier f = newfid(fs, x->fid);
2207dd7cddfSDavid du Colombier x->f = f;
2217dd7cddfSDavid du Colombier x = (*fcall[x->type])(fs, x, f);
2227dd7cddfSDavid du Colombier }
223*9a747e4fSDavid du Colombier firstmessage = 0;
2247dd7cddfSDavid du Colombier }
2257dd7cddfSDavid du Colombier }
2267dd7cddfSDavid du Colombier
2277dd7cddfSDavid du Colombier /*
2287dd7cddfSDavid du Colombier * Called only from a different FD group
2297dd7cddfSDavid du Colombier */
2307dd7cddfSDavid du Colombier int
filsysmount(Filsys * fs,int id)2317dd7cddfSDavid du Colombier filsysmount(Filsys *fs, int id)
2327dd7cddfSDavid du Colombier {
233*9a747e4fSDavid du Colombier char buf[32];
2347dd7cddfSDavid du Colombier
2357dd7cddfSDavid du Colombier close(fs->sfd); /* close server end so mount won't hang if exiting */
2367dd7cddfSDavid du Colombier sprint(buf, "%d", id);
237*9a747e4fSDavid du Colombier if(mount(fs->cfd, -1, "/mnt/wsys", MREPL, buf) < 0){
238*9a747e4fSDavid du Colombier fprint(2, "mount failed: %r\n");
2397dd7cddfSDavid du Colombier return -1;
2407dd7cddfSDavid du Colombier }
2417dd7cddfSDavid du Colombier if(bind("/mnt/wsys", "/dev", MBEFORE) < 0){
242*9a747e4fSDavid du Colombier fprint(2, "bind failed: %r\n");
2437dd7cddfSDavid du Colombier return -1;
2447dd7cddfSDavid du Colombier }
2457dd7cddfSDavid du Colombier return 0;
2467dd7cddfSDavid du Colombier }
2477dd7cddfSDavid du Colombier
2487dd7cddfSDavid du Colombier Xfid*
filsysrespond(Filsys * fs,Xfid * x,Fcall * t,char * err)2497dd7cddfSDavid du Colombier filsysrespond(Filsys *fs, Xfid *x, Fcall *t, char *err)
2507dd7cddfSDavid du Colombier {
2517dd7cddfSDavid du Colombier int n;
2527dd7cddfSDavid du Colombier
2537dd7cddfSDavid du Colombier if(err){
2547dd7cddfSDavid du Colombier t->type = Rerror;
255*9a747e4fSDavid du Colombier t->ename = err;
2567dd7cddfSDavid du Colombier }else
2577dd7cddfSDavid du Colombier t->type = x->type+1;
2587dd7cddfSDavid du Colombier t->fid = x->fid;
2597dd7cddfSDavid du Colombier t->tag = x->tag;
2607dd7cddfSDavid du Colombier if(x->buf == nil)
261*9a747e4fSDavid du Colombier x->buf = malloc(messagesize);
262*9a747e4fSDavid du Colombier n = convS2M(t, x->buf, messagesize);
263*9a747e4fSDavid du Colombier if(n <= 0)
2647dd7cddfSDavid du Colombier error("convert error in convS2M");
2657dd7cddfSDavid du Colombier if(write(fs->sfd, x->buf, n) != n)
2667dd7cddfSDavid du Colombier error("write error in respond");
267*9a747e4fSDavid du Colombier if(DEBUG)
268*9a747e4fSDavid du Colombier fprint(2, "rio:->%F\n", t);
2697dd7cddfSDavid du Colombier free(x->buf);
2707dd7cddfSDavid du Colombier x->buf = nil;
2717dd7cddfSDavid du Colombier return x;
2727dd7cddfSDavid du Colombier }
2737dd7cddfSDavid du Colombier
2747dd7cddfSDavid du Colombier void
filsyscancel(Xfid * x)2757dd7cddfSDavid du Colombier filsyscancel(Xfid *x)
2767dd7cddfSDavid du Colombier {
2777dd7cddfSDavid du Colombier if(x->buf){
2787dd7cddfSDavid du Colombier free(x->buf);
2797dd7cddfSDavid du Colombier x->buf = nil;
2807dd7cddfSDavid du Colombier }
2817dd7cddfSDavid du Colombier }
2827dd7cddfSDavid du Colombier
2837dd7cddfSDavid du Colombier static
2847dd7cddfSDavid du Colombier Xfid*
filsysversion(Filsys * fs,Xfid * x,Fid *)285*9a747e4fSDavid du Colombier filsysversion(Filsys *fs, Xfid *x, Fid*)
2867dd7cddfSDavid du Colombier {
2877dd7cddfSDavid du Colombier Fcall t;
2887dd7cddfSDavid du Colombier
289*9a747e4fSDavid du Colombier if(!firstmessage)
290*9a747e4fSDavid du Colombier return filsysrespond(x->fs, x, &t, "version request not first message");
291*9a747e4fSDavid du Colombier if(x->msize < 256)
292*9a747e4fSDavid du Colombier return filsysrespond(x->fs, x, &t, "version: message size too small");
293*9a747e4fSDavid du Colombier messagesize = x->msize;
294*9a747e4fSDavid du Colombier t.msize = messagesize;
295*9a747e4fSDavid du Colombier if(strncmp(x->version, "9P2000", 6) != 0)
296*9a747e4fSDavid du Colombier return filsysrespond(x->fs, x, &t, "unrecognized 9P version");
297*9a747e4fSDavid du Colombier t.version = "9P2000";
2987dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, nil);
2997dd7cddfSDavid du Colombier }
3007dd7cddfSDavid du Colombier
3017dd7cddfSDavid du Colombier static
3027dd7cddfSDavid du Colombier Xfid*
filsysauth(Filsys * fs,Xfid * x,Fid *)303*9a747e4fSDavid du Colombier filsysauth(Filsys *fs, Xfid *x, Fid*)
3047dd7cddfSDavid du Colombier {
3057dd7cddfSDavid du Colombier Fcall t;
3067dd7cddfSDavid du Colombier
307*9a747e4fSDavid du Colombier return filsysrespond(fs, x, &t, "rio: authentication not required");
3087dd7cddfSDavid du Colombier }
3097dd7cddfSDavid du Colombier
3107dd7cddfSDavid du Colombier static
3117dd7cddfSDavid du Colombier Xfid*
filsysflush(Filsys *,Xfid * x,Fid *)3127dd7cddfSDavid du Colombier filsysflush(Filsys*, Xfid *x, Fid*)
3137dd7cddfSDavid du Colombier {
3147dd7cddfSDavid du Colombier sendp(x->c, xfidflush);
3157dd7cddfSDavid du Colombier return nil;
3167dd7cddfSDavid du Colombier }
3177dd7cddfSDavid du Colombier
3187dd7cddfSDavid du Colombier static
3197dd7cddfSDavid du Colombier Xfid*
filsysattach(Filsys *,Xfid * x,Fid * f)3207dd7cddfSDavid du Colombier filsysattach(Filsys *, Xfid *x, Fid *f)
3217dd7cddfSDavid du Colombier {
3227dd7cddfSDavid du Colombier Fcall t;
3237dd7cddfSDavid du Colombier
3247dd7cddfSDavid du Colombier if(strcmp(x->uname, x->fs->user) != 0)
3257dd7cddfSDavid du Colombier return filsysrespond(x->fs, x, &t, Eperm);
3267dd7cddfSDavid du Colombier f->busy = TRUE;
3277dd7cddfSDavid du Colombier f->open = FALSE;
328*9a747e4fSDavid du Colombier f->qid.path = Qdir;
329*9a747e4fSDavid du Colombier f->qid.type = QTDIR;
330*9a747e4fSDavid du Colombier f->qid.vers = 0;
3317dd7cddfSDavid du Colombier f->dir = dirtab;
3327dd7cddfSDavid du Colombier f->nrpart = 0;
3337dd7cddfSDavid du Colombier sendp(x->c, xfidattach);
3347dd7cddfSDavid du Colombier return nil;
3357dd7cddfSDavid du Colombier }
3367dd7cddfSDavid du Colombier
3377dd7cddfSDavid du Colombier static
338*9a747e4fSDavid du Colombier int
numeric(char * s)339*9a747e4fSDavid du Colombier numeric(char *s)
3407dd7cddfSDavid du Colombier {
341*9a747e4fSDavid du Colombier for(; *s!='\0'; s++)
342*9a747e4fSDavid du Colombier if(*s<'0' || '9'<*s)
343*9a747e4fSDavid du Colombier return 0;
344*9a747e4fSDavid du Colombier return 1;
3457dd7cddfSDavid du Colombier }
3467dd7cddfSDavid du Colombier
3477dd7cddfSDavid du Colombier static
3487dd7cddfSDavid du Colombier Xfid*
filsyswalk(Filsys * fs,Xfid * x,Fid * f)3497dd7cddfSDavid du Colombier filsyswalk(Filsys *fs, Xfid *x, Fid *f)
3507dd7cddfSDavid du Colombier {
3517dd7cddfSDavid du Colombier Fcall t;
352*9a747e4fSDavid du Colombier Fid *nf;
353*9a747e4fSDavid du Colombier int i, id;
354*9a747e4fSDavid du Colombier uchar type;
355*9a747e4fSDavid du Colombier ulong path;
356*9a747e4fSDavid du Colombier Dirtab *d, *dir;
3577dd7cddfSDavid du Colombier Window *w;
358*9a747e4fSDavid du Colombier char *err;
359*9a747e4fSDavid du Colombier Qid qid;
3607dd7cddfSDavid du Colombier
361*9a747e4fSDavid du Colombier if(f->open)
362*9a747e4fSDavid du Colombier return filsysrespond(fs, x, &t, "walk of open file");
363*9a747e4fSDavid du Colombier nf = nil;
364*9a747e4fSDavid du Colombier if(x->fid != x->newfid){
365*9a747e4fSDavid du Colombier /* BUG: check exists */
366*9a747e4fSDavid du Colombier nf = newfid(fs, x->newfid);
367*9a747e4fSDavid du Colombier if(nf->busy)
368*9a747e4fSDavid du Colombier return filsysrespond(fs, x, &t, "clone to busy fid");
369*9a747e4fSDavid du Colombier nf->busy = TRUE;
370*9a747e4fSDavid du Colombier nf->open = FALSE;
371*9a747e4fSDavid du Colombier nf->dir = f->dir;
372*9a747e4fSDavid du Colombier nf->qid = f->qid;
373*9a747e4fSDavid du Colombier nf->w = f->w;
374*9a747e4fSDavid du Colombier incref(f->w);
375*9a747e4fSDavid du Colombier nf->nrpart = 0; /* not open, so must be zero */
376*9a747e4fSDavid du Colombier f = nf; /* walk f */
3777dd7cddfSDavid du Colombier }
378*9a747e4fSDavid du Colombier
379*9a747e4fSDavid du Colombier t.nwqid = 0;
380*9a747e4fSDavid du Colombier err = nil;
381*9a747e4fSDavid du Colombier
382*9a747e4fSDavid du Colombier /* update f->qid, f->dir only if walk completes */
383*9a747e4fSDavid du Colombier qid = f->qid;
384*9a747e4fSDavid du Colombier dir = f->dir;
385*9a747e4fSDavid du Colombier
386*9a747e4fSDavid du Colombier if(x->nwname > 0){
387*9a747e4fSDavid du Colombier for(i=0; i<x->nwname; i++){
388*9a747e4fSDavid du Colombier if((qid.type & QTDIR) == 0){
389*9a747e4fSDavid du Colombier err = Enotdir;
390*9a747e4fSDavid du Colombier break;
391*9a747e4fSDavid du Colombier }
392*9a747e4fSDavid du Colombier if(strcmp(x->wname[i], "..") == 0){
393*9a747e4fSDavid du Colombier type = QTDIR;
394*9a747e4fSDavid du Colombier path = Qdir;
395*9a747e4fSDavid du Colombier dir = dirtab;
396*9a747e4fSDavid du Colombier if(FILE(qid) == Qwsysdir)
397*9a747e4fSDavid du Colombier path = Qwsys;
398*9a747e4fSDavid du Colombier id = 0;
399*9a747e4fSDavid du Colombier Accept:
400*9a747e4fSDavid du Colombier if(i == MAXWELEM){
401*9a747e4fSDavid du Colombier err = "name too long";
402*9a747e4fSDavid du Colombier break;
403*9a747e4fSDavid du Colombier }
404*9a747e4fSDavid du Colombier qid.type = type;
405*9a747e4fSDavid du Colombier qid.vers = 0;
406*9a747e4fSDavid du Colombier qid.path = QID(id, path);
407*9a747e4fSDavid du Colombier t.wqid[t.nwqid++] = qid;
408*9a747e4fSDavid du Colombier continue;
409*9a747e4fSDavid du Colombier }
410*9a747e4fSDavid du Colombier
411*9a747e4fSDavid du Colombier if(qid.path == Qwsys){
4127dd7cddfSDavid du Colombier /* is it a numeric name? */
413*9a747e4fSDavid du Colombier if(!numeric(x->wname[i]))
414*9a747e4fSDavid du Colombier break;
4157dd7cddfSDavid du Colombier /* yes: it's a directory */
416*9a747e4fSDavid du Colombier id = atoi(x->wname[i]);
4177dd7cddfSDavid du Colombier qlock(&all);
4187dd7cddfSDavid du Colombier w = wlookid(id);
4197dd7cddfSDavid du Colombier if(w == nil){
4207dd7cddfSDavid du Colombier qunlock(&all);
421*9a747e4fSDavid du Colombier break;
4227dd7cddfSDavid du Colombier }
423*9a747e4fSDavid du Colombier path = Qwsysdir;
424*9a747e4fSDavid du Colombier type = QTDIR;
4257dd7cddfSDavid du Colombier qunlock(&all);
4267dd7cddfSDavid du Colombier incref(w);
4277dd7cddfSDavid du Colombier sendp(winclosechan, f->w);
4287dd7cddfSDavid du Colombier f->w = w;
429*9a747e4fSDavid du Colombier dir = dirtab;
430*9a747e4fSDavid du Colombier goto Accept;
4317dd7cddfSDavid du Colombier }
4327dd7cddfSDavid du Colombier
433*9a747e4fSDavid du Colombier if(snarffd>=0 && strcmp(x->wname[i], "snarf")==0)
434*9a747e4fSDavid du Colombier break; /* don't serve /dev/snarf if it's provided in the environment */
4357dd7cddfSDavid du Colombier id = WIN(f->qid);
4367dd7cddfSDavid du Colombier d = dirtab;
4377dd7cddfSDavid du Colombier d++; /* skip '.' */
4387dd7cddfSDavid du Colombier for(; d->name; d++)
439*9a747e4fSDavid du Colombier if(strcmp(x->wname[i], d->name) == 0){
440*9a747e4fSDavid du Colombier path = d->qid;
441*9a747e4fSDavid du Colombier type = d->type;
442*9a747e4fSDavid du Colombier dir = d;
443*9a747e4fSDavid du Colombier goto Accept;
4447dd7cddfSDavid du Colombier }
4457dd7cddfSDavid du Colombier
446*9a747e4fSDavid du Colombier break; /* file not found */
4477dd7cddfSDavid du Colombier }
4487dd7cddfSDavid du Colombier
449*9a747e4fSDavid du Colombier if(i==0 && err==nil)
450*9a747e4fSDavid du Colombier err = Eexist;
451*9a747e4fSDavid du Colombier }
4527dd7cddfSDavid du Colombier
453*9a747e4fSDavid du Colombier if(err!=nil || t.nwqid<x->nwname){
454*9a747e4fSDavid du Colombier if(nf){
455*9a747e4fSDavid du Colombier if(nf->w)
456*9a747e4fSDavid du Colombier sendp(winclosechan, nf->w);
457*9a747e4fSDavid du Colombier nf->open = FALSE;
458*9a747e4fSDavid du Colombier nf->busy = FALSE;
459*9a747e4fSDavid du Colombier }
460*9a747e4fSDavid du Colombier }else if(t.nwqid == x->nwname){
461*9a747e4fSDavid du Colombier f->dir = dir;
462*9a747e4fSDavid du Colombier f->qid = qid;
463*9a747e4fSDavid du Colombier }
464*9a747e4fSDavid du Colombier
465*9a747e4fSDavid du Colombier return filsysrespond(fs, x, &t, err);
4667dd7cddfSDavid du Colombier }
4677dd7cddfSDavid du Colombier
4687dd7cddfSDavid du Colombier static
4697dd7cddfSDavid du Colombier Xfid*
filsysopen(Filsys * fs,Xfid * x,Fid * f)4707dd7cddfSDavid du Colombier filsysopen(Filsys *fs, Xfid *x, Fid *f)
4717dd7cddfSDavid du Colombier {
4727dd7cddfSDavid du Colombier Fcall t;
4737dd7cddfSDavid du Colombier int m;
4747dd7cddfSDavid du Colombier
4757dd7cddfSDavid du Colombier /* can't truncate anything, so just disregard */
4767dd7cddfSDavid du Colombier x->mode &= ~(OTRUNC|OCEXEC);
4777dd7cddfSDavid du Colombier /* can't execute or remove anything */
4787dd7cddfSDavid du Colombier if(x->mode==OEXEC || (x->mode&ORCLOSE))
4797dd7cddfSDavid du Colombier goto Deny;
4807dd7cddfSDavid du Colombier switch(x->mode){
4817dd7cddfSDavid du Colombier default:
4827dd7cddfSDavid du Colombier goto Deny;
4837dd7cddfSDavid du Colombier case OREAD:
4847dd7cddfSDavid du Colombier m = 0400;
4857dd7cddfSDavid du Colombier break;
4867dd7cddfSDavid du Colombier case OWRITE:
4877dd7cddfSDavid du Colombier m = 0200;
4887dd7cddfSDavid du Colombier break;
4897dd7cddfSDavid du Colombier case ORDWR:
4907dd7cddfSDavid du Colombier m = 0600;
4917dd7cddfSDavid du Colombier break;
4927dd7cddfSDavid du Colombier }
493*9a747e4fSDavid du Colombier if(((f->dir->perm&~(DMDIR|DMAPPEND))&m) != m)
4947dd7cddfSDavid du Colombier goto Deny;
4957dd7cddfSDavid du Colombier
4967dd7cddfSDavid du Colombier sendp(x->c, xfidopen);
4977dd7cddfSDavid du Colombier return nil;
4987dd7cddfSDavid du Colombier
4997dd7cddfSDavid du Colombier Deny:
5007dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, Eperm);
5017dd7cddfSDavid du Colombier }
5027dd7cddfSDavid du Colombier
5037dd7cddfSDavid du Colombier static
5047dd7cddfSDavid du Colombier Xfid*
filsyscreate(Filsys * fs,Xfid * x,Fid *)5057dd7cddfSDavid du Colombier filsyscreate(Filsys *fs, Xfid *x, Fid*)
5067dd7cddfSDavid du Colombier {
5077dd7cddfSDavid du Colombier Fcall t;
5087dd7cddfSDavid du Colombier
5097dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, Eperm);
5107dd7cddfSDavid du Colombier }
5117dd7cddfSDavid du Colombier
5127dd7cddfSDavid du Colombier static
5137dd7cddfSDavid du Colombier int
idcmp(void * a,void * b)5147dd7cddfSDavid du Colombier idcmp(void *a, void *b)
5157dd7cddfSDavid du Colombier {
5167dd7cddfSDavid du Colombier return *(int*)a - *(int*)b;
5177dd7cddfSDavid du Colombier }
5187dd7cddfSDavid du Colombier
5197dd7cddfSDavid du Colombier static
5207dd7cddfSDavid du Colombier Xfid*
filsysread(Filsys * fs,Xfid * x,Fid * f)5217dd7cddfSDavid du Colombier filsysread(Filsys *fs, Xfid *x, Fid *f)
5227dd7cddfSDavid du Colombier {
5237dd7cddfSDavid du Colombier Fcall t;
524*9a747e4fSDavid du Colombier uchar *b;
525*9a747e4fSDavid du Colombier int i, n, o, e, len, j, k, *ids;
5267dd7cddfSDavid du Colombier Dirtab *d, dt;
5277dd7cddfSDavid du Colombier uint clock;
5287dd7cddfSDavid du Colombier char buf[16];
5297dd7cddfSDavid du Colombier
530*9a747e4fSDavid du Colombier if((f->qid.type & QTDIR) == 0){
5317dd7cddfSDavid du Colombier sendp(x->c, xfidread);
5327dd7cddfSDavid du Colombier return nil;
5337dd7cddfSDavid du Colombier }
5347dd7cddfSDavid du Colombier o = x->offset;
5357dd7cddfSDavid du Colombier e = x->offset+x->count;
5367dd7cddfSDavid du Colombier clock = getclock();
537*9a747e4fSDavid du Colombier b = malloc(messagesize-IOHDRSZ); /* avoid memset of emalloc */
538*9a747e4fSDavid du Colombier if(b == nil)
539*9a747e4fSDavid du Colombier return filsysrespond(fs, x, &t, "out of memory");
5407dd7cddfSDavid du Colombier n = 0;
5417dd7cddfSDavid du Colombier switch(FILE(f->qid)){
5427dd7cddfSDavid du Colombier case Qdir:
5437dd7cddfSDavid du Colombier case Qwsysdir:
5447dd7cddfSDavid du Colombier d = dirtab;
5457dd7cddfSDavid du Colombier d++; /* first entry is '.' */
546*9a747e4fSDavid du Colombier for(i=0; d->name!=nil && i<e; i+=len){
547*9a747e4fSDavid du Colombier len = dostat(fs, WIN(x->f->qid), d, b+n, x->count-n, clock);
548*9a747e4fSDavid du Colombier if(len <= BIT16SZ)
549*9a747e4fSDavid du Colombier break;
550*9a747e4fSDavid du Colombier if(i >= o)
551*9a747e4fSDavid du Colombier n += len;
5527dd7cddfSDavid du Colombier d++;
5537dd7cddfSDavid du Colombier }
5547dd7cddfSDavid du Colombier break;
5557dd7cddfSDavid du Colombier case Qwsys:
5567dd7cddfSDavid du Colombier qlock(&all);
5577dd7cddfSDavid du Colombier ids = emalloc(nwindow*sizeof(int));
5587dd7cddfSDavid du Colombier for(j=0; j<nwindow; j++)
5597dd7cddfSDavid du Colombier ids[j] = window[j]->id;
5607dd7cddfSDavid du Colombier qunlock(&all);
5617dd7cddfSDavid du Colombier qsort(ids, nwindow, sizeof ids[0], idcmp);
5627dd7cddfSDavid du Colombier dt.name = buf;
563*9a747e4fSDavid du Colombier for(i=0, j=0; j<nwindow && i<e; i+=len){
5647dd7cddfSDavid du Colombier k = ids[j];
5657dd7cddfSDavid du Colombier sprint(dt.name, "%d", k);
566*9a747e4fSDavid du Colombier dt.qid = QID(k, Qdir);
567*9a747e4fSDavid du Colombier dt.type = QTDIR;
568*9a747e4fSDavid du Colombier dt.perm = DMDIR|0700;
569*9a747e4fSDavid du Colombier len = dostat(fs, k, &dt, b+n, x->count-n, clock);
570*9a747e4fSDavid du Colombier if(len == 0)
571*9a747e4fSDavid du Colombier break;
572*9a747e4fSDavid du Colombier if(i >= o)
573*9a747e4fSDavid du Colombier n += len;
5747dd7cddfSDavid du Colombier j++;
5757dd7cddfSDavid du Colombier }
5767dd7cddfSDavid du Colombier free(ids);
5777dd7cddfSDavid du Colombier break;
5787dd7cddfSDavid du Colombier }
579*9a747e4fSDavid du Colombier t.data = (char*)b;
5807dd7cddfSDavid du Colombier t.count = n;
5817dd7cddfSDavid du Colombier filsysrespond(fs, x, &t, nil);
5827dd7cddfSDavid du Colombier free(b);
5837dd7cddfSDavid du Colombier return x;
5847dd7cddfSDavid du Colombier }
5857dd7cddfSDavid du Colombier
5867dd7cddfSDavid du Colombier static
5877dd7cddfSDavid du Colombier Xfid*
filsyswrite(Filsys *,Xfid * x,Fid *)5887dd7cddfSDavid du Colombier filsyswrite(Filsys*, Xfid *x, Fid*)
5897dd7cddfSDavid du Colombier {
5907dd7cddfSDavid du Colombier sendp(x->c, xfidwrite);
5917dd7cddfSDavid du Colombier return nil;
5927dd7cddfSDavid du Colombier }
5937dd7cddfSDavid du Colombier
5947dd7cddfSDavid du Colombier static
5957dd7cddfSDavid du Colombier Xfid*
filsysclunk(Filsys * fs,Xfid * x,Fid * f)5967dd7cddfSDavid du Colombier filsysclunk(Filsys *fs, Xfid *x, Fid *f)
5977dd7cddfSDavid du Colombier {
5987dd7cddfSDavid du Colombier Fcall t;
5997dd7cddfSDavid du Colombier
6007dd7cddfSDavid du Colombier if(f->open){
6017dd7cddfSDavid du Colombier f->busy = FALSE;
6027dd7cddfSDavid du Colombier f->open = FALSE;
6037dd7cddfSDavid du Colombier sendp(x->c, xfidclose);
6047dd7cddfSDavid du Colombier return nil;
6057dd7cddfSDavid du Colombier }
6067dd7cddfSDavid du Colombier if(f->w)
6077dd7cddfSDavid du Colombier sendp(winclosechan, f->w);
6087dd7cddfSDavid du Colombier f->busy = FALSE;
6097dd7cddfSDavid du Colombier f->open = FALSE;
6107dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, nil);
6117dd7cddfSDavid du Colombier }
6127dd7cddfSDavid du Colombier
6137dd7cddfSDavid du Colombier static
6147dd7cddfSDavid du Colombier Xfid*
filsysremove(Filsys * fs,Xfid * x,Fid *)6157dd7cddfSDavid du Colombier filsysremove(Filsys *fs, Xfid *x, Fid*)
6167dd7cddfSDavid du Colombier {
6177dd7cddfSDavid du Colombier Fcall t;
6187dd7cddfSDavid du Colombier
6197dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, Eperm);
6207dd7cddfSDavid du Colombier }
6217dd7cddfSDavid du Colombier
6227dd7cddfSDavid du Colombier static
6237dd7cddfSDavid du Colombier Xfid*
filsysstat(Filsys * fs,Xfid * x,Fid * f)6247dd7cddfSDavid du Colombier filsysstat(Filsys *fs, Xfid *x, Fid *f)
6257dd7cddfSDavid du Colombier {
6267dd7cddfSDavid du Colombier Fcall t;
6277dd7cddfSDavid du Colombier
628*9a747e4fSDavid du Colombier t.stat = emalloc(messagesize-IOHDRSZ);
629*9a747e4fSDavid du Colombier t.nstat = dostat(fs, WIN(x->f->qid), f->dir, t.stat, messagesize-IOHDRSZ, getclock());
630*9a747e4fSDavid du Colombier x = filsysrespond(fs, x, &t, nil);
631*9a747e4fSDavid du Colombier free(t.stat);
632*9a747e4fSDavid du Colombier return x;
6337dd7cddfSDavid du Colombier }
6347dd7cddfSDavid du Colombier
6357dd7cddfSDavid du Colombier static
6367dd7cddfSDavid du Colombier Xfid*
filsyswstat(Filsys * fs,Xfid * x,Fid *)6377dd7cddfSDavid du Colombier filsyswstat(Filsys *fs, Xfid *x, Fid*)
6387dd7cddfSDavid du Colombier {
6397dd7cddfSDavid du Colombier Fcall t;
6407dd7cddfSDavid du Colombier
6417dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, Eperm);
6427dd7cddfSDavid du Colombier }
6437dd7cddfSDavid du Colombier
6447dd7cddfSDavid du Colombier static
6457dd7cddfSDavid du Colombier Fid*
newfid(Filsys * fs,int fid)6467dd7cddfSDavid du Colombier newfid(Filsys *fs, int fid)
6477dd7cddfSDavid du Colombier {
6487dd7cddfSDavid du Colombier Fid *f, *ff, **fh;
6497dd7cddfSDavid du Colombier
6507dd7cddfSDavid du Colombier ff = nil;
6517dd7cddfSDavid du Colombier fh = &fs->fids[fid&(Nhash-1)];
6527dd7cddfSDavid du Colombier for(f=*fh; f; f=f->next)
6537dd7cddfSDavid du Colombier if(f->fid == fid)
6547dd7cddfSDavid du Colombier return f;
6557dd7cddfSDavid du Colombier else if(ff==nil && f->busy==FALSE)
6567dd7cddfSDavid du Colombier ff = f;
6577dd7cddfSDavid du Colombier if(ff){
6587dd7cddfSDavid du Colombier ff->fid = fid;
6597dd7cddfSDavid du Colombier return ff;
6607dd7cddfSDavid du Colombier }
6617dd7cddfSDavid du Colombier f = emalloc(sizeof *f);
6627dd7cddfSDavid du Colombier f->fid = fid;
6637dd7cddfSDavid du Colombier f->next = *fh;
6647dd7cddfSDavid du Colombier *fh = f;
6657dd7cddfSDavid du Colombier return f;
6667dd7cddfSDavid du Colombier }
6677dd7cddfSDavid du Colombier
6687dd7cddfSDavid du Colombier static
6697dd7cddfSDavid du Colombier uint
getclock(void)6707dd7cddfSDavid du Colombier getclock(void)
6717dd7cddfSDavid du Colombier {
6727dd7cddfSDavid du Colombier char buf[32];
6737dd7cddfSDavid du Colombier
6747dd7cddfSDavid du Colombier seek(clockfd, 0, 0);
6757dd7cddfSDavid du Colombier read(clockfd, buf, sizeof buf);
6767dd7cddfSDavid du Colombier return atoi(buf);
6777dd7cddfSDavid du Colombier }
6787dd7cddfSDavid du Colombier
6797dd7cddfSDavid du Colombier static
680*9a747e4fSDavid du Colombier int
dostat(Filsys * fs,int id,Dirtab * dir,uchar * buf,int nbuf,uint clock)681*9a747e4fSDavid du Colombier dostat(Filsys *fs, int id, Dirtab *dir, uchar *buf, int nbuf, uint clock)
6827dd7cddfSDavid du Colombier {
6837dd7cddfSDavid du Colombier Dir d;
6847dd7cddfSDavid du Colombier
6857dd7cddfSDavid du Colombier d.qid.path = QID(id, dir->qid);
68680ee5cbfSDavid du Colombier if(dir->qid == Qsnarf)
68780ee5cbfSDavid du Colombier d.qid.vers = snarfversion;
68880ee5cbfSDavid du Colombier else
6897dd7cddfSDavid du Colombier d.qid.vers = 0;
690*9a747e4fSDavid du Colombier d.qid.type = dir->type;
6917dd7cddfSDavid du Colombier d.mode = dir->perm;
6927dd7cddfSDavid du Colombier d.length = 0; /* would be nice to do better */
693*9a747e4fSDavid du Colombier d.name = dir->name;
694*9a747e4fSDavid du Colombier d.uid = fs->user;
695*9a747e4fSDavid du Colombier d.gid = fs->user;
696*9a747e4fSDavid du Colombier d.muid = fs->user;
6977dd7cddfSDavid du Colombier d.atime = clock;
6987dd7cddfSDavid du Colombier d.mtime = clock;
699*9a747e4fSDavid du Colombier return convD2M(&d, buf, nbuf);
7007dd7cddfSDavid du Colombier }
701