xref: /plan9/sys/src/cmd/rio/fsys.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier #include <u.h>
2*7dd7cddfSDavid du Colombier #include <libc.h>
3*7dd7cddfSDavid du Colombier #include <draw.h>
4*7dd7cddfSDavid du Colombier #include <thread.h>
5*7dd7cddfSDavid du Colombier #include <cursor.h>
6*7dd7cddfSDavid du Colombier #include <mouse.h>
7*7dd7cddfSDavid du Colombier #include <keyboard.h>
8*7dd7cddfSDavid du Colombier #include <frame.h>
9*7dd7cddfSDavid du Colombier #include <auth.h>
10*7dd7cddfSDavid du Colombier #include <fcall.h>
11*7dd7cddfSDavid du Colombier #include "dat.h"
12*7dd7cddfSDavid du Colombier #include "fns.h"
13*7dd7cddfSDavid du Colombier 
14*7dd7cddfSDavid du Colombier char Eperm[] = "permission denied";
15*7dd7cddfSDavid du Colombier char Eexist[] = "file does not exist";
16*7dd7cddfSDavid du Colombier char Enotdir[] = "not a directory";
17*7dd7cddfSDavid du Colombier char	Ebadfcall[] = "bad fcall type";
18*7dd7cddfSDavid du Colombier char	Eoffset[] = "illegal offset";
19*7dd7cddfSDavid du Colombier 
20*7dd7cddfSDavid du Colombier Dirtab dirtab[]=
21*7dd7cddfSDavid du Colombier {
22*7dd7cddfSDavid du Colombier 	{ ".",			Qdir|CHDIR,	0500|CHDIR },
23*7dd7cddfSDavid du Colombier 	{ "cons",		Qcons,		0600 },
24*7dd7cddfSDavid du Colombier 	{ "cursor",		Qcursor,		0600 },
25*7dd7cddfSDavid du Colombier 	{ "consctl",	Qconsctl,		0200 },
26*7dd7cddfSDavid du Colombier 	{ "winid",		Qwinid,		0400 },
27*7dd7cddfSDavid du Colombier 	{ "winname",	Qwinname,	0400 },
28*7dd7cddfSDavid du Colombier 	{ "label",		Qlabel,		0600 },
29*7dd7cddfSDavid du Colombier 	{ "mouse",	Qmouse,		0600 },
30*7dd7cddfSDavid du Colombier 	{ "screen",		Qscreen,		0400 },
31*7dd7cddfSDavid du Colombier 	{ "snarf",		Qsnarf,		0600 },
32*7dd7cddfSDavid du Colombier 	{ "text",		Qtext,		0400 },
33*7dd7cddfSDavid du Colombier 	{ "wdir",		Qwdir,		0600 },
34*7dd7cddfSDavid du Colombier 	{ "wctl",		Qwctl,		0600 },
35*7dd7cddfSDavid du Colombier 	{ "window",	Qwindow,		0400 },
36*7dd7cddfSDavid du Colombier 	{ "wsys",		Qwsys|CHDIR,	0500|CHDIR },
37*7dd7cddfSDavid du Colombier 	{ nil, }
38*7dd7cddfSDavid du Colombier };
39*7dd7cddfSDavid du Colombier 
40*7dd7cddfSDavid du Colombier static uint		getclock(void);
41*7dd7cddfSDavid du Colombier static void		filsysproc(void*);
42*7dd7cddfSDavid du Colombier static Fid*		newfid(Filsys*, int);
43*7dd7cddfSDavid du Colombier static void		dostat(Filsys*, int, Dirtab*, char*, uint);
44*7dd7cddfSDavid du Colombier 
45*7dd7cddfSDavid du Colombier int	clockfd;
46*7dd7cddfSDavid du Colombier 
47*7dd7cddfSDavid du Colombier char	srvpipe[64];
48*7dd7cddfSDavid du Colombier char	srvwctl[64];
49*7dd7cddfSDavid du Colombier 
50*7dd7cddfSDavid du Colombier static	Xfid*	filsysflush(Filsys*, Xfid*, Fid*);
51*7dd7cddfSDavid du Colombier static	Xfid*	filsyssession(Filsys*, Xfid*, Fid*);
52*7dd7cddfSDavid du Colombier static	Xfid*	filsysnop(Filsys*, Xfid*, Fid*);
53*7dd7cddfSDavid du Colombier static	Xfid*	filsysattach(Filsys*, Xfid*, Fid*);
54*7dd7cddfSDavid du Colombier static	Xfid*	filsysclone(Filsys*, Xfid*, Fid*);
55*7dd7cddfSDavid du Colombier static	Xfid*	filsyswalk(Filsys*, Xfid*, Fid*);
56*7dd7cddfSDavid du Colombier static	Xfid*	filsysclwalk(Filsys*, Xfid*, Fid*);
57*7dd7cddfSDavid du Colombier static	Xfid*	filsysopen(Filsys*, Xfid*, Fid*);
58*7dd7cddfSDavid du Colombier static	Xfid*	filsyscreate(Filsys*, Xfid*, Fid*);
59*7dd7cddfSDavid du Colombier static	Xfid*	filsysread(Filsys*, Xfid*, Fid*);
60*7dd7cddfSDavid du Colombier static	Xfid*	filsyswrite(Filsys*, Xfid*, Fid*);
61*7dd7cddfSDavid du Colombier static	Xfid*	filsysclunk(Filsys*, Xfid*, Fid*);
62*7dd7cddfSDavid du Colombier static	Xfid*	filsysremove(Filsys*, Xfid*, Fid*);
63*7dd7cddfSDavid du Colombier static	Xfid*	filsysstat(Filsys*, Xfid*, Fid*);
64*7dd7cddfSDavid du Colombier static	Xfid*	filsyswstat(Filsys*, Xfid*, Fid*);
65*7dd7cddfSDavid du Colombier 
66*7dd7cddfSDavid du Colombier Xfid* 	(*fcall[Tmax])(Filsys*, Xfid*, Fid*) =
67*7dd7cddfSDavid du Colombier {
68*7dd7cddfSDavid du Colombier 	[Tflush]	= filsysflush,
69*7dd7cddfSDavid du Colombier 	[Tsession]	= filsyssession,
70*7dd7cddfSDavid du Colombier 	[Tnop]	= filsysnop,
71*7dd7cddfSDavid du Colombier 	[Tattach]	= filsysattach,
72*7dd7cddfSDavid du Colombier 	[Tclone]	= filsysclone,
73*7dd7cddfSDavid du Colombier 	[Twalk]	= filsyswalk,
74*7dd7cddfSDavid du Colombier 	[Tclwalk]	= filsysclwalk,
75*7dd7cddfSDavid du Colombier 	[Topen]	= filsysopen,
76*7dd7cddfSDavid du Colombier 	[Tcreate]	= filsyscreate,
77*7dd7cddfSDavid du Colombier 	[Tread]	= filsysread,
78*7dd7cddfSDavid du Colombier 	[Twrite]	= filsyswrite,
79*7dd7cddfSDavid du Colombier 	[Tclunk]	= filsysclunk,
80*7dd7cddfSDavid du Colombier 	[Tremove]= filsysremove,
81*7dd7cddfSDavid du Colombier 	[Tstat]	= filsysstat,
82*7dd7cddfSDavid du Colombier 	[Twstat]	= filsyswstat,
83*7dd7cddfSDavid du Colombier };
84*7dd7cddfSDavid du Colombier 
85*7dd7cddfSDavid du Colombier void
86*7dd7cddfSDavid du Colombier post(char *name, char *envname, int srvfd)
87*7dd7cddfSDavid du Colombier {
88*7dd7cddfSDavid du Colombier 	int fd;
89*7dd7cddfSDavid du Colombier 	char buf[32];
90*7dd7cddfSDavid du Colombier 
91*7dd7cddfSDavid du Colombier 	fd = create(name, OWRITE, 0600);
92*7dd7cddfSDavid du Colombier 	if(fd < 0)
93*7dd7cddfSDavid du Colombier 		error(name);
94*7dd7cddfSDavid du Colombier 	sprint(buf, "%d",srvfd);
95*7dd7cddfSDavid du Colombier 	if(write(fd, buf, strlen(buf)) != strlen(buf))
96*7dd7cddfSDavid du Colombier 		error("srv write");
97*7dd7cddfSDavid du Colombier 	close(fd);
98*7dd7cddfSDavid du Colombier 	putenv(envname, name);
99*7dd7cddfSDavid du Colombier }
100*7dd7cddfSDavid du Colombier 
101*7dd7cddfSDavid du Colombier /*
102*7dd7cddfSDavid du Colombier  * Build pipe with OCEXEC set on second fd.
103*7dd7cddfSDavid du Colombier  * Can't put it on both because we want to post one in /srv.
104*7dd7cddfSDavid du Colombier  */
105*7dd7cddfSDavid du Colombier int
106*7dd7cddfSDavid du Colombier cexecpipe(int *p0, int *p1)
107*7dd7cddfSDavid du Colombier {
108*7dd7cddfSDavid du Colombier 	/* pipe the hard way to get close on exec */
109*7dd7cddfSDavid du Colombier 	if(bind("#|", "/mnt", MREPL) < 0)
110*7dd7cddfSDavid du Colombier 		return -1;
111*7dd7cddfSDavid du Colombier 	*p0 = open("/mnt/data", ORDWR);
112*7dd7cddfSDavid du Colombier 	*p1 = open("/mnt/data1", ORDWR|OCEXEC);
113*7dd7cddfSDavid du Colombier 	unmount(nil, "/mnt");
114*7dd7cddfSDavid du Colombier 	if(*p0<0 || *p1<0)
115*7dd7cddfSDavid du Colombier 		return -1;
116*7dd7cddfSDavid du Colombier 	return 0;
117*7dd7cddfSDavid du Colombier }
118*7dd7cddfSDavid du Colombier 
119*7dd7cddfSDavid du Colombier Filsys*
120*7dd7cddfSDavid du Colombier filsysinit(Channel *cxfidalloc)
121*7dd7cddfSDavid du Colombier {
122*7dd7cddfSDavid du Colombier 	int n, fd, pid, p0;
123*7dd7cddfSDavid du Colombier 	Filsys *fs;
124*7dd7cddfSDavid du Colombier 	Channel *c;
125*7dd7cddfSDavid du Colombier 
126*7dd7cddfSDavid du Colombier 	fs = emalloc(sizeof(Filsys));
127*7dd7cddfSDavid du Colombier 	if(cexecpipe(&fs->cfd, &fs->sfd) < 0)
128*7dd7cddfSDavid du Colombier 		goto Rescue;
129*7dd7cddfSDavid du Colombier 	fmtinstall('F', fcallconv);
130*7dd7cddfSDavid du Colombier 	clockfd = open("/dev/time", OREAD|OCEXEC);
131*7dd7cddfSDavid du Colombier 	fd = open("/dev/user", OREAD);
132*7dd7cddfSDavid du Colombier 	strncpy(fs->user, "Jean-Paul_Belmondo", NAMELEN);
133*7dd7cddfSDavid du Colombier 	if(fd >= 0){
134*7dd7cddfSDavid du Colombier 		n = read(fd, fs->user, NAMELEN);
135*7dd7cddfSDavid du Colombier 		if(n > 0)
136*7dd7cddfSDavid du Colombier 			fs->user[n] = 0;
137*7dd7cddfSDavid du Colombier 		close(fd);
138*7dd7cddfSDavid du Colombier 	}
139*7dd7cddfSDavid du Colombier 	fs->cxfidalloc = cxfidalloc;
140*7dd7cddfSDavid du Colombier 	pid = getpid();
141*7dd7cddfSDavid du Colombier 
142*7dd7cddfSDavid du Colombier 	/*
143*7dd7cddfSDavid du Colombier 	 * Create and post wctl pipe
144*7dd7cddfSDavid du Colombier 	 */
145*7dd7cddfSDavid du Colombier 	if(cexecpipe(&p0, &wctlfd) < 0)
146*7dd7cddfSDavid du Colombier 		goto Rescue;
147*7dd7cddfSDavid du Colombier 	sprint(srvwctl, "/srv/riowctl.%s.%d", fs->user, pid);
148*7dd7cddfSDavid du Colombier 	post(srvwctl, "wctl", p0);
149*7dd7cddfSDavid du Colombier 	close(p0);
150*7dd7cddfSDavid du Colombier 
151*7dd7cddfSDavid du Colombier 	/*
152*7dd7cddfSDavid du Colombier 	 * Post srv pipe
153*7dd7cddfSDavid du Colombier 	 */
154*7dd7cddfSDavid du Colombier 	sprint(srvpipe, "/srv/rio.%s.%d", fs->user, pid);
155*7dd7cddfSDavid du Colombier 	post(srvpipe, "wsys", fs->cfd);
156*7dd7cddfSDavid du Colombier 
157*7dd7cddfSDavid du Colombier 	/*
158*7dd7cddfSDavid du Colombier 	 * Start server processes
159*7dd7cddfSDavid du Colombier 	 */
160*7dd7cddfSDavid du Colombier 	c = chancreate(sizeof(char*), 0);
161*7dd7cddfSDavid du Colombier 	if(c == nil)
162*7dd7cddfSDavid du Colombier 		error("wctl channel");
163*7dd7cddfSDavid du Colombier 	proccreate(wctlproc, c, 4096);
164*7dd7cddfSDavid du Colombier 	threadcreate(wctlthread, c, 4096);
165*7dd7cddfSDavid du Colombier 	proccreate(filsysproc, fs, 10000);
166*7dd7cddfSDavid du Colombier 
167*7dd7cddfSDavid du Colombier 	return fs;
168*7dd7cddfSDavid du Colombier 
169*7dd7cddfSDavid du Colombier Rescue:
170*7dd7cddfSDavid du Colombier 	free(fs);
171*7dd7cddfSDavid du Colombier 	return nil;
172*7dd7cddfSDavid du Colombier }
173*7dd7cddfSDavid du Colombier 
174*7dd7cddfSDavid du Colombier static
175*7dd7cddfSDavid du Colombier void
176*7dd7cddfSDavid du Colombier filsysproc(void *arg)
177*7dd7cddfSDavid du Colombier {
178*7dd7cddfSDavid du Colombier 	int n;
179*7dd7cddfSDavid du Colombier 	Xfid *x;
180*7dd7cddfSDavid du Colombier 	Fid *f;
181*7dd7cddfSDavid du Colombier 	Fcall t;
182*7dd7cddfSDavid du Colombier 	char *buf;
183*7dd7cddfSDavid du Colombier 	Filsys *fs;
184*7dd7cddfSDavid du Colombier 
185*7dd7cddfSDavid du Colombier 	fs = arg;
186*7dd7cddfSDavid du Colombier 	fs->pid = getpid();
187*7dd7cddfSDavid du Colombier 	x = nil;
188*7dd7cddfSDavid du Colombier 	for(;;){
189*7dd7cddfSDavid du Colombier 		buf = malloc(MAXFDATA+MAXMSG);
190*7dd7cddfSDavid du Colombier 		n = read(fs->sfd, buf, MAXFDATA+MAXMSG);
191*7dd7cddfSDavid du Colombier 		if(n < 0)
192*7dd7cddfSDavid du Colombier 			error("i/o error on server channel");
193*7dd7cddfSDavid du Colombier 		if(n == 0)
194*7dd7cddfSDavid du Colombier 			error("eof on server channel");
195*7dd7cddfSDavid du Colombier 		if(x == nil){
196*7dd7cddfSDavid du Colombier 			send(fs->cxfidalloc, nil);
197*7dd7cddfSDavid du Colombier 			recv(fs->cxfidalloc, &x);
198*7dd7cddfSDavid du Colombier 			x->fs = fs;
199*7dd7cddfSDavid du Colombier 		}
200*7dd7cddfSDavid du Colombier 		x->buf = buf;
201*7dd7cddfSDavid du Colombier 		if(convM2S(buf, x, n) != n)
202*7dd7cddfSDavid du Colombier 			error("convert error in convM2S");
203*7dd7cddfSDavid du Colombier 		if(fcall[x->type] == nil)
204*7dd7cddfSDavid du Colombier 			x = filsysrespond(fs, x, &t, Ebadfcall);
205*7dd7cddfSDavid du Colombier 		else{
206*7dd7cddfSDavid du Colombier 			if(x->type==Tnop || x->type==Tsession)
207*7dd7cddfSDavid du Colombier 				f = nil;
208*7dd7cddfSDavid du Colombier 			else
209*7dd7cddfSDavid du Colombier 				f = newfid(fs, x->fid);
210*7dd7cddfSDavid du Colombier 			x->f = f;
211*7dd7cddfSDavid du Colombier 			x  = (*fcall[x->type])(fs, x, f);
212*7dd7cddfSDavid du Colombier 		}
213*7dd7cddfSDavid du Colombier 	}
214*7dd7cddfSDavid du Colombier }
215*7dd7cddfSDavid du Colombier 
216*7dd7cddfSDavid du Colombier void
217*7dd7cddfSDavid du Colombier filsysclose(Filsys *fs)
218*7dd7cddfSDavid du Colombier {
219*7dd7cddfSDavid du Colombier 	if(fs == nil)
220*7dd7cddfSDavid du Colombier 		return;
221*7dd7cddfSDavid du Colombier 	close(fs->sfd);
222*7dd7cddfSDavid du Colombier 	fs->sfd = -1;
223*7dd7cddfSDavid du Colombier 	close(fs->cfd);
224*7dd7cddfSDavid du Colombier 	fs->cfd = -1;
225*7dd7cddfSDavid du Colombier 	remove(srvpipe);
226*7dd7cddfSDavid du Colombier 	remove(srvwctl);
227*7dd7cddfSDavid du Colombier }
228*7dd7cddfSDavid du Colombier 
229*7dd7cddfSDavid du Colombier /*
230*7dd7cddfSDavid du Colombier  * Called only from a different FD group
231*7dd7cddfSDavid du Colombier  */
232*7dd7cddfSDavid du Colombier int
233*7dd7cddfSDavid du Colombier filsysmount(Filsys *fs, int id)
234*7dd7cddfSDavid du Colombier {
235*7dd7cddfSDavid du Colombier 	char buf[3*NAMELEN+CHALLEN+DOMLEN+1];
236*7dd7cddfSDavid du Colombier 
237*7dd7cddfSDavid du Colombier 	close(fs->sfd);	/* close server end so mount won't hang if exiting */
238*7dd7cddfSDavid du Colombier 	if(fsession(fs->cfd, buf) < 0){
239*7dd7cddfSDavid du Colombier 		threadprint(2, "fsession failed: %r\n");
240*7dd7cddfSDavid du Colombier 		return -1;
241*7dd7cddfSDavid du Colombier 	}
242*7dd7cddfSDavid du Colombier 	sprint(buf, "%d", id);
243*7dd7cddfSDavid du Colombier 	if(mount(fs->cfd, "/mnt/wsys", MREPL, buf) < 0){
244*7dd7cddfSDavid du Colombier 		threadprint(2, "mount failed: %r\n");
245*7dd7cddfSDavid du Colombier 		return -1;
246*7dd7cddfSDavid du Colombier 	}
247*7dd7cddfSDavid du Colombier 	if(bind("/mnt/wsys", "/dev", MBEFORE) < 0){
248*7dd7cddfSDavid du Colombier 		threadprint(2, "bind failed: %r\n");
249*7dd7cddfSDavid du Colombier 		return -1;
250*7dd7cddfSDavid du Colombier 	}
251*7dd7cddfSDavid du Colombier 	return 0;
252*7dd7cddfSDavid du Colombier }
253*7dd7cddfSDavid du Colombier 
254*7dd7cddfSDavid du Colombier Xfid*
255*7dd7cddfSDavid du Colombier filsysrespond(Filsys *fs, Xfid *x, Fcall *t, char *err)
256*7dd7cddfSDavid du Colombier {
257*7dd7cddfSDavid du Colombier 	int n;
258*7dd7cddfSDavid du Colombier 
259*7dd7cddfSDavid du Colombier 	if(err){
260*7dd7cddfSDavid du Colombier 		t->type = Rerror;
261*7dd7cddfSDavid du Colombier 		strncpy(t->ename, err, ERRLEN);
262*7dd7cddfSDavid du Colombier 	}else
263*7dd7cddfSDavid du Colombier 		t->type = x->type+1;
264*7dd7cddfSDavid du Colombier 	t->fid = x->fid;
265*7dd7cddfSDavid du Colombier 	t->tag = x->tag;
266*7dd7cddfSDavid du Colombier 	if(x->buf == nil)
267*7dd7cddfSDavid du Colombier 		x->buf = malloc(MAXFDATA+MAXMSG);
268*7dd7cddfSDavid du Colombier 	n = convS2M(t, x->buf);
269*7dd7cddfSDavid du Colombier 	if(n < 0)
270*7dd7cddfSDavid du Colombier 		error("convert error in convS2M");
271*7dd7cddfSDavid du Colombier 	if(write(fs->sfd, x->buf, n) != n)
272*7dd7cddfSDavid du Colombier 		error("write error in respond");
273*7dd7cddfSDavid du Colombier 	free(x->buf);
274*7dd7cddfSDavid du Colombier 	x->buf = nil;
275*7dd7cddfSDavid du Colombier 	return x;
276*7dd7cddfSDavid du Colombier }
277*7dd7cddfSDavid du Colombier 
278*7dd7cddfSDavid du Colombier void
279*7dd7cddfSDavid du Colombier filsyscancel(Xfid *x)
280*7dd7cddfSDavid du Colombier {
281*7dd7cddfSDavid du Colombier 	if(x->buf){
282*7dd7cddfSDavid du Colombier 		free(x->buf);
283*7dd7cddfSDavid du Colombier 		x->buf = nil;
284*7dd7cddfSDavid du Colombier 	}
285*7dd7cddfSDavid du Colombier }
286*7dd7cddfSDavid du Colombier 
287*7dd7cddfSDavid du Colombier static
288*7dd7cddfSDavid du Colombier Xfid*
289*7dd7cddfSDavid du Colombier filsysnop(Filsys *fs, Xfid *x, Fid*)
290*7dd7cddfSDavid du Colombier {
291*7dd7cddfSDavid du Colombier 	Fcall t;
292*7dd7cddfSDavid du Colombier 
293*7dd7cddfSDavid du Colombier 	return filsysrespond(fs, x, &t, nil);
294*7dd7cddfSDavid du Colombier }
295*7dd7cddfSDavid du Colombier 
296*7dd7cddfSDavid du Colombier static
297*7dd7cddfSDavid du Colombier Xfid*
298*7dd7cddfSDavid du Colombier filsyssession(Filsys *fs, Xfid *x, Fid*)
299*7dd7cddfSDavid du Colombier {
300*7dd7cddfSDavid du Colombier 	Fcall t;
301*7dd7cddfSDavid du Colombier 
302*7dd7cddfSDavid du Colombier 	memset(&t, 0, sizeof t);
303*7dd7cddfSDavid du Colombier 	return filsysrespond(fs, x, &t, nil);
304*7dd7cddfSDavid du Colombier }
305*7dd7cddfSDavid du Colombier 
306*7dd7cddfSDavid du Colombier static
307*7dd7cddfSDavid du Colombier Xfid*
308*7dd7cddfSDavid du Colombier filsysflush(Filsys*, Xfid *x, Fid*)
309*7dd7cddfSDavid du Colombier {
310*7dd7cddfSDavid du Colombier 	sendp(x->c, xfidflush);
311*7dd7cddfSDavid du Colombier 	return nil;
312*7dd7cddfSDavid du Colombier }
313*7dd7cddfSDavid du Colombier 
314*7dd7cddfSDavid du Colombier static
315*7dd7cddfSDavid du Colombier Xfid*
316*7dd7cddfSDavid du Colombier filsysattach(Filsys *, Xfid *x, Fid *f)
317*7dd7cddfSDavid du Colombier {
318*7dd7cddfSDavid du Colombier 	Fcall t;
319*7dd7cddfSDavid du Colombier 
320*7dd7cddfSDavid du Colombier 	if(strcmp(x->uname, x->fs->user) != 0)
321*7dd7cddfSDavid du Colombier 		return filsysrespond(x->fs, x, &t, Eperm);
322*7dd7cddfSDavid du Colombier 	f->busy = TRUE;
323*7dd7cddfSDavid du Colombier 	f->open = FALSE;
324*7dd7cddfSDavid du Colombier 	f->qid = (Qid){CHDIR|Qdir, 0};
325*7dd7cddfSDavid du Colombier 	f->dir = dirtab;
326*7dd7cddfSDavid du Colombier 	f->nrpart = 0;
327*7dd7cddfSDavid du Colombier 	sendp(x->c, xfidattach);
328*7dd7cddfSDavid du Colombier 	return nil;
329*7dd7cddfSDavid du Colombier }
330*7dd7cddfSDavid du Colombier 
331*7dd7cddfSDavid du Colombier static
332*7dd7cddfSDavid du Colombier Xfid*
333*7dd7cddfSDavid du Colombier filsysclone(Filsys *fs, Xfid *x, Fid *f)
334*7dd7cddfSDavid du Colombier {
335*7dd7cddfSDavid du Colombier 	Fid *nf;
336*7dd7cddfSDavid du Colombier 	Fcall t;
337*7dd7cddfSDavid du Colombier 
338*7dd7cddfSDavid du Colombier 	if(f->open)
339*7dd7cddfSDavid du Colombier 		return filsysrespond(fs, x, &t, "is open");
340*7dd7cddfSDavid du Colombier 	/* BUG: check exists */
341*7dd7cddfSDavid du Colombier 	nf = newfid(fs, x->newfid);
342*7dd7cddfSDavid du Colombier 	nf->busy = TRUE;
343*7dd7cddfSDavid du Colombier 	nf->open = FALSE;
344*7dd7cddfSDavid du Colombier 	nf->dir = f->dir;
345*7dd7cddfSDavid du Colombier 	nf->qid = f->qid;
346*7dd7cddfSDavid du Colombier 	nf->w = f->w;
347*7dd7cddfSDavid du Colombier 	incref(f->w);
348*7dd7cddfSDavid du Colombier 	nf->nrpart = 0;	/* not open, so must be zero */
349*7dd7cddfSDavid du Colombier 	return filsysrespond(fs, x, &t, nil);
350*7dd7cddfSDavid du Colombier }
351*7dd7cddfSDavid du Colombier 
352*7dd7cddfSDavid du Colombier static
353*7dd7cddfSDavid du Colombier Xfid*
354*7dd7cddfSDavid du Colombier filsyswalk(Filsys *fs, Xfid *x, Fid *f)
355*7dd7cddfSDavid du Colombier {
356*7dd7cddfSDavid du Colombier 	Fcall t;
357*7dd7cddfSDavid du Colombier 	int c, i, id;
358*7dd7cddfSDavid du Colombier 	uint qid;
359*7dd7cddfSDavid du Colombier 	Dirtab *d;
360*7dd7cddfSDavid du Colombier 	Window *w;
361*7dd7cddfSDavid du Colombier 
362*7dd7cddfSDavid du Colombier 	if((f->qid.path & CHDIR) == 0)
363*7dd7cddfSDavid du Colombier 		return filsysrespond(fs, x, &t, Enotdir);
364*7dd7cddfSDavid du Colombier 	if(strcmp(x->name, "..") == 0){
365*7dd7cddfSDavid du Colombier 		qid = Qdir|CHDIR;
366*7dd7cddfSDavid du Colombier 		if(FILE(f->qid) == Qwsysdir)
367*7dd7cddfSDavid du Colombier 			qid = Qwsys|CHDIR;
368*7dd7cddfSDavid du Colombier 		id = 0;
369*7dd7cddfSDavid du Colombier 		goto Found;
370*7dd7cddfSDavid du Colombier 	}
371*7dd7cddfSDavid du Colombier 	if(f->qid.path == (CHDIR|Qwsys)){
372*7dd7cddfSDavid du Colombier 		/* is it a numeric name? */
373*7dd7cddfSDavid du Colombier 		for(i=0; (c=x->name[i]); i++)
374*7dd7cddfSDavid du Colombier 			if(c<'0' || '9'<c)
375*7dd7cddfSDavid du Colombier 				goto Notfound;
376*7dd7cddfSDavid du Colombier 		/* yes: it's a directory */
377*7dd7cddfSDavid du Colombier 		id = atoi(x->name);
378*7dd7cddfSDavid du Colombier 		qlock(&all);
379*7dd7cddfSDavid du Colombier 		w = wlookid(id);
380*7dd7cddfSDavid du Colombier 		if(w == nil){
381*7dd7cddfSDavid du Colombier 			qunlock(&all);
382*7dd7cddfSDavid du Colombier 			goto Notfound;
383*7dd7cddfSDavid du Colombier 		}
384*7dd7cddfSDavid du Colombier 		qid = CHDIR|Qwsysdir;
385*7dd7cddfSDavid du Colombier 		qunlock(&all);
386*7dd7cddfSDavid du Colombier 		incref(w);
387*7dd7cddfSDavid du Colombier 		sendp(winclosechan, f->w);
388*7dd7cddfSDavid du Colombier 		f->w = w;
389*7dd7cddfSDavid du Colombier 		f->dir = dirtab;
390*7dd7cddfSDavid du Colombier 		goto Found;
391*7dd7cddfSDavid du Colombier 	}
392*7dd7cddfSDavid du Colombier 
393*7dd7cddfSDavid du Colombier 	if(snarffd>=0 && strcmp(x->name, "snarf")==0)
394*7dd7cddfSDavid du Colombier 		goto Notfound;
395*7dd7cddfSDavid du Colombier 	id = WIN(f->qid);
396*7dd7cddfSDavid du Colombier 	d = dirtab;
397*7dd7cddfSDavid du Colombier 	d++;	/* skip '.' */
398*7dd7cddfSDavid du Colombier 	for(; d->name; d++)
399*7dd7cddfSDavid du Colombier 		if(strcmp(x->name, d->name) == 0){
400*7dd7cddfSDavid du Colombier 			qid = d->qid;
401*7dd7cddfSDavid du Colombier 			f->dir = d;
402*7dd7cddfSDavid du Colombier 			goto Found;
403*7dd7cddfSDavid du Colombier 		}
404*7dd7cddfSDavid du Colombier 
405*7dd7cddfSDavid du Colombier     Notfound:
406*7dd7cddfSDavid du Colombier 	return filsysrespond(fs, x, &t, Eexist);
407*7dd7cddfSDavid du Colombier 
408*7dd7cddfSDavid du Colombier     Found:
409*7dd7cddfSDavid du Colombier 	f->qid = (Qid){QID(id, qid), 0};
410*7dd7cddfSDavid du Colombier 	t.qid = f->qid;
411*7dd7cddfSDavid du Colombier 	return filsysrespond(fs, x, &t, nil);
412*7dd7cddfSDavid du Colombier }
413*7dd7cddfSDavid du Colombier 
414*7dd7cddfSDavid du Colombier static
415*7dd7cddfSDavid du Colombier Xfid*
416*7dd7cddfSDavid du Colombier filsysclwalk(Filsys *fs, Xfid *x, Fid*)
417*7dd7cddfSDavid du Colombier {
418*7dd7cddfSDavid du Colombier 	Fcall t;
419*7dd7cddfSDavid du Colombier 
420*7dd7cddfSDavid du Colombier 	return filsysrespond(fs, x, &t, "clwalk not implemented");
421*7dd7cddfSDavid du Colombier }
422*7dd7cddfSDavid du Colombier 
423*7dd7cddfSDavid du Colombier static
424*7dd7cddfSDavid du Colombier Xfid*
425*7dd7cddfSDavid du Colombier filsysopen(Filsys *fs, Xfid *x, Fid *f)
426*7dd7cddfSDavid du Colombier {
427*7dd7cddfSDavid du Colombier 	Fcall t;
428*7dd7cddfSDavid du Colombier 	int m;
429*7dd7cddfSDavid du Colombier 
430*7dd7cddfSDavid du Colombier 	/* can't truncate anything, so just disregard */
431*7dd7cddfSDavid du Colombier 	x->mode &= ~(OTRUNC|OCEXEC);
432*7dd7cddfSDavid du Colombier 	/* can't execute or remove anything */
433*7dd7cddfSDavid du Colombier 	if(x->mode==OEXEC || (x->mode&ORCLOSE))
434*7dd7cddfSDavid du Colombier 		goto Deny;
435*7dd7cddfSDavid du Colombier 	switch(x->mode){
436*7dd7cddfSDavid du Colombier 	default:
437*7dd7cddfSDavid du Colombier 		goto Deny;
438*7dd7cddfSDavid du Colombier 	case OREAD:
439*7dd7cddfSDavid du Colombier 		m = 0400;
440*7dd7cddfSDavid du Colombier 		break;
441*7dd7cddfSDavid du Colombier 	case OWRITE:
442*7dd7cddfSDavid du Colombier 		m = 0200;
443*7dd7cddfSDavid du Colombier 		break;
444*7dd7cddfSDavid du Colombier 	case ORDWR:
445*7dd7cddfSDavid du Colombier 		m = 0600;
446*7dd7cddfSDavid du Colombier 		break;
447*7dd7cddfSDavid du Colombier 	}
448*7dd7cddfSDavid du Colombier 	if(((f->dir->perm&~(CHDIR|CHAPPEND))&m) != m)
449*7dd7cddfSDavid du Colombier 		goto Deny;
450*7dd7cddfSDavid du Colombier 
451*7dd7cddfSDavid du Colombier 	sendp(x->c, xfidopen);
452*7dd7cddfSDavid du Colombier 	return nil;
453*7dd7cddfSDavid du Colombier 
454*7dd7cddfSDavid du Colombier     Deny:
455*7dd7cddfSDavid du Colombier 	return filsysrespond(fs, x, &t, Eperm);
456*7dd7cddfSDavid du Colombier }
457*7dd7cddfSDavid du Colombier 
458*7dd7cddfSDavid du Colombier static
459*7dd7cddfSDavid du Colombier Xfid*
460*7dd7cddfSDavid du Colombier filsyscreate(Filsys *fs, Xfid *x, Fid*)
461*7dd7cddfSDavid du Colombier {
462*7dd7cddfSDavid du Colombier 	Fcall t;
463*7dd7cddfSDavid du Colombier 
464*7dd7cddfSDavid du Colombier 	return filsysrespond(fs, x, &t, Eperm);
465*7dd7cddfSDavid du Colombier }
466*7dd7cddfSDavid du Colombier 
467*7dd7cddfSDavid du Colombier static
468*7dd7cddfSDavid du Colombier int
469*7dd7cddfSDavid du Colombier idcmp(void *a, void *b)
470*7dd7cddfSDavid du Colombier {
471*7dd7cddfSDavid du Colombier 	return *(int*)a - *(int*)b;
472*7dd7cddfSDavid du Colombier }
473*7dd7cddfSDavid du Colombier 
474*7dd7cddfSDavid du Colombier static
475*7dd7cddfSDavid du Colombier Xfid*
476*7dd7cddfSDavid du Colombier filsysread(Filsys *fs, Xfid *x, Fid *f)
477*7dd7cddfSDavid du Colombier {
478*7dd7cddfSDavid du Colombier 	Fcall t;
479*7dd7cddfSDavid du Colombier 	char *b;
480*7dd7cddfSDavid du Colombier 	int i, n, o, e, j, k, *ids;
481*7dd7cddfSDavid du Colombier 	Dirtab *d, dt;
482*7dd7cddfSDavid du Colombier 	uint clock;
483*7dd7cddfSDavid du Colombier 	char buf[16];
484*7dd7cddfSDavid du Colombier 
485*7dd7cddfSDavid du Colombier 	if((f->qid.path & CHDIR) == 0){
486*7dd7cddfSDavid du Colombier 		sendp(x->c, xfidread);
487*7dd7cddfSDavid du Colombier 		return nil;
488*7dd7cddfSDavid du Colombier 	}
489*7dd7cddfSDavid du Colombier 	if(x->offset % DIRLEN)
490*7dd7cddfSDavid du Colombier 		return filsysrespond(fs, x, &t, Eoffset);
491*7dd7cddfSDavid du Colombier 	o = x->offset;
492*7dd7cddfSDavid du Colombier 	e = x->offset+x->count;
493*7dd7cddfSDavid du Colombier 	clock = getclock();
494*7dd7cddfSDavid du Colombier 	b = malloc(MAXFDATA+MAXMSG);
495*7dd7cddfSDavid du Colombier 	n = 0;
496*7dd7cddfSDavid du Colombier 	switch(FILE(f->qid)){
497*7dd7cddfSDavid du Colombier 	case Qdir:
498*7dd7cddfSDavid du Colombier 	case Qwsysdir:
499*7dd7cddfSDavid du Colombier 		d = dirtab;
500*7dd7cddfSDavid du Colombier 		d++;	/* first entry is '.' */
501*7dd7cddfSDavid du Colombier 		for(i=0; d->name!=nil && i+DIRLEN<e; i+=DIRLEN){
502*7dd7cddfSDavid du Colombier 			if(i >= o){
503*7dd7cddfSDavid du Colombier 				dostat(fs, WIN(x->f->qid), d, b+n, clock);
504*7dd7cddfSDavid du Colombier 				n += DIRLEN;
505*7dd7cddfSDavid du Colombier 			}
506*7dd7cddfSDavid du Colombier 			d++;
507*7dd7cddfSDavid du Colombier 		}
508*7dd7cddfSDavid du Colombier 		break;
509*7dd7cddfSDavid du Colombier 	case Qwsys:
510*7dd7cddfSDavid du Colombier 		qlock(&all);
511*7dd7cddfSDavid du Colombier 		ids = emalloc(nwindow*sizeof(int));
512*7dd7cddfSDavid du Colombier 		for(j=0; j<nwindow; j++)
513*7dd7cddfSDavid du Colombier 			ids[j] = window[j]->id;
514*7dd7cddfSDavid du Colombier 		qunlock(&all);
515*7dd7cddfSDavid du Colombier 		qsort(ids, nwindow, sizeof ids[0], idcmp);
516*7dd7cddfSDavid du Colombier 		dt.name = buf;
517*7dd7cddfSDavid du Colombier 		for(i=0, j=0; j<nwindow && i+DIRLEN<e; i+=DIRLEN){
518*7dd7cddfSDavid du Colombier 			if(i >= o){
519*7dd7cddfSDavid du Colombier 				k = ids[j];
520*7dd7cddfSDavid du Colombier 				sprint(dt.name, "%d", k);
521*7dd7cddfSDavid du Colombier 				dt.qid = QID(k, CHDIR);
522*7dd7cddfSDavid du Colombier 				dt.perm = CHDIR|0700;
523*7dd7cddfSDavid du Colombier 				dostat(fs, k, &dt, b+n, clock);
524*7dd7cddfSDavid du Colombier 				n += DIRLEN;
525*7dd7cddfSDavid du Colombier 			}
526*7dd7cddfSDavid du Colombier 			j++;
527*7dd7cddfSDavid du Colombier 		}
528*7dd7cddfSDavid du Colombier 		free(ids);
529*7dd7cddfSDavid du Colombier 		break;
530*7dd7cddfSDavid du Colombier 	}
531*7dd7cddfSDavid du Colombier 	t.data = b;
532*7dd7cddfSDavid du Colombier 	t.count = n;
533*7dd7cddfSDavid du Colombier 	filsysrespond(fs, x, &t, nil);
534*7dd7cddfSDavid du Colombier 	free(b);
535*7dd7cddfSDavid du Colombier 	return x;
536*7dd7cddfSDavid du Colombier }
537*7dd7cddfSDavid du Colombier 
538*7dd7cddfSDavid du Colombier static
539*7dd7cddfSDavid du Colombier Xfid*
540*7dd7cddfSDavid du Colombier filsyswrite(Filsys*, Xfid *x, Fid*)
541*7dd7cddfSDavid du Colombier {
542*7dd7cddfSDavid du Colombier 	sendp(x->c, xfidwrite);
543*7dd7cddfSDavid du Colombier 	return nil;
544*7dd7cddfSDavid du Colombier }
545*7dd7cddfSDavid du Colombier 
546*7dd7cddfSDavid du Colombier static
547*7dd7cddfSDavid du Colombier Xfid*
548*7dd7cddfSDavid du Colombier filsysclunk(Filsys *fs, Xfid *x, Fid *f)
549*7dd7cddfSDavid du Colombier {
550*7dd7cddfSDavid du Colombier 	Fcall t;
551*7dd7cddfSDavid du Colombier 
552*7dd7cddfSDavid du Colombier 	if(f->open){
553*7dd7cddfSDavid du Colombier 		f->busy = FALSE;
554*7dd7cddfSDavid du Colombier 		f->open = FALSE;
555*7dd7cddfSDavid du Colombier 		sendp(x->c, xfidclose);
556*7dd7cddfSDavid du Colombier 		return nil;
557*7dd7cddfSDavid du Colombier 	}
558*7dd7cddfSDavid du Colombier 	if(f->w)
559*7dd7cddfSDavid du Colombier 		sendp(winclosechan, f->w);
560*7dd7cddfSDavid du Colombier 	f->busy = FALSE;
561*7dd7cddfSDavid du Colombier 	f->open = FALSE;
562*7dd7cddfSDavid du Colombier 	return filsysrespond(fs, x, &t, nil);
563*7dd7cddfSDavid du Colombier }
564*7dd7cddfSDavid du Colombier 
565*7dd7cddfSDavid du Colombier static
566*7dd7cddfSDavid du Colombier Xfid*
567*7dd7cddfSDavid du Colombier filsysremove(Filsys *fs, Xfid *x, Fid*)
568*7dd7cddfSDavid du Colombier {
569*7dd7cddfSDavid du Colombier 	Fcall t;
570*7dd7cddfSDavid du Colombier 
571*7dd7cddfSDavid du Colombier 	return filsysrespond(fs, x, &t, Eperm);
572*7dd7cddfSDavid du Colombier }
573*7dd7cddfSDavid du Colombier 
574*7dd7cddfSDavid du Colombier static
575*7dd7cddfSDavid du Colombier Xfid*
576*7dd7cddfSDavid du Colombier filsysstat(Filsys *fs, Xfid *x, Fid *f)
577*7dd7cddfSDavid du Colombier {
578*7dd7cddfSDavid du Colombier 	Fcall t;
579*7dd7cddfSDavid du Colombier 
580*7dd7cddfSDavid du Colombier 	dostat(fs, WIN(x->f->qid), f->dir, t.stat, getclock());
581*7dd7cddfSDavid du Colombier 	return filsysrespond(fs, x, &t, nil);
582*7dd7cddfSDavid du Colombier }
583*7dd7cddfSDavid du Colombier 
584*7dd7cddfSDavid du Colombier static
585*7dd7cddfSDavid du Colombier Xfid*
586*7dd7cddfSDavid du Colombier filsyswstat(Filsys *fs, Xfid *x, Fid*)
587*7dd7cddfSDavid du Colombier {
588*7dd7cddfSDavid du Colombier 	Fcall t;
589*7dd7cddfSDavid du Colombier 
590*7dd7cddfSDavid du Colombier 	return filsysrespond(fs, x, &t, Eperm);
591*7dd7cddfSDavid du Colombier }
592*7dd7cddfSDavid du Colombier 
593*7dd7cddfSDavid du Colombier static
594*7dd7cddfSDavid du Colombier Fid*
595*7dd7cddfSDavid du Colombier newfid(Filsys *fs, int fid)
596*7dd7cddfSDavid du Colombier {
597*7dd7cddfSDavid du Colombier 	Fid *f, *ff, **fh;
598*7dd7cddfSDavid du Colombier 
599*7dd7cddfSDavid du Colombier 	ff = nil;
600*7dd7cddfSDavid du Colombier 	fh = &fs->fids[fid&(Nhash-1)];
601*7dd7cddfSDavid du Colombier 	for(f=*fh; f; f=f->next)
602*7dd7cddfSDavid du Colombier 		if(f->fid == fid)
603*7dd7cddfSDavid du Colombier 			return f;
604*7dd7cddfSDavid du Colombier 		else if(ff==nil && f->busy==FALSE)
605*7dd7cddfSDavid du Colombier 			ff = f;
606*7dd7cddfSDavid du Colombier 	if(ff){
607*7dd7cddfSDavid du Colombier 		ff->fid = fid;
608*7dd7cddfSDavid du Colombier 		return ff;
609*7dd7cddfSDavid du Colombier 	}
610*7dd7cddfSDavid du Colombier 	f = emalloc(sizeof *f);
611*7dd7cddfSDavid du Colombier 	f->fid = fid;
612*7dd7cddfSDavid du Colombier 	f->next = *fh;
613*7dd7cddfSDavid du Colombier 	*fh = f;
614*7dd7cddfSDavid du Colombier 	return f;
615*7dd7cddfSDavid du Colombier }
616*7dd7cddfSDavid du Colombier 
617*7dd7cddfSDavid du Colombier static
618*7dd7cddfSDavid du Colombier uint
619*7dd7cddfSDavid du Colombier getclock(void)
620*7dd7cddfSDavid du Colombier {
621*7dd7cddfSDavid du Colombier 	char buf[32];
622*7dd7cddfSDavid du Colombier 
623*7dd7cddfSDavid du Colombier 	seek(clockfd, 0, 0);
624*7dd7cddfSDavid du Colombier 	read(clockfd, buf, sizeof buf);
625*7dd7cddfSDavid du Colombier 	return atoi(buf);
626*7dd7cddfSDavid du Colombier }
627*7dd7cddfSDavid du Colombier 
628*7dd7cddfSDavid du Colombier static
629*7dd7cddfSDavid du Colombier void
630*7dd7cddfSDavid du Colombier dostat(Filsys *fs, int id, Dirtab *dir, char *buf, uint clock)
631*7dd7cddfSDavid du Colombier {
632*7dd7cddfSDavid du Colombier 	Dir d;
633*7dd7cddfSDavid du Colombier 
634*7dd7cddfSDavid du Colombier 	d.qid.path = QID(id, dir->qid);
635*7dd7cddfSDavid du Colombier 	d.qid.vers = 0;
636*7dd7cddfSDavid du Colombier 	d.mode = dir->perm;
637*7dd7cddfSDavid du Colombier 	d.length = 0;	/* would be nice to do better */
638*7dd7cddfSDavid du Colombier 	strncpy(d.name, dir->name, NAMELEN);
639*7dd7cddfSDavid du Colombier 	memmove(d.uid, fs->user, NAMELEN);
640*7dd7cddfSDavid du Colombier 	memmove(d.gid, fs->user, NAMELEN);
641*7dd7cddfSDavid du Colombier 	d.atime = clock;
642*7dd7cddfSDavid du Colombier 	d.mtime = clock;
643*7dd7cddfSDavid du Colombier 	convD2M(&d, buf);
644*7dd7cddfSDavid du Colombier }
645