xref: /plan9/sys/src/cmd/acme/fsys.c (revision 5d9de2d38d2503efca29e12e0e32036368a7a75f)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
59a747e4fSDavid 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 <plumb.h>
117dd7cddfSDavid du Colombier #include "dat.h"
127dd7cddfSDavid du Colombier #include "fns.h"
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier static	int	cfd;
157dd7cddfSDavid du Colombier static	int	sfd;
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier enum
187dd7cddfSDavid du Colombier {
197dd7cddfSDavid du Colombier 	Nhash	= 16,
207dd7cddfSDavid du Colombier 	DEBUG	= 0
217dd7cddfSDavid du Colombier };
227dd7cddfSDavid du Colombier 
237dd7cddfSDavid du Colombier static	Fid	*fids[Nhash];
247dd7cddfSDavid du Colombier 
257dd7cddfSDavid du Colombier Fid	*newfid(int);
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier static	Xfid*	fsysflush(Xfid*, Fid*);
289a747e4fSDavid du Colombier static	Xfid*	fsysauth(Xfid*, Fid*);
299a747e4fSDavid du Colombier static	Xfid*	fsysversion(Xfid*, Fid*);
307dd7cddfSDavid du Colombier static	Xfid*	fsysattach(Xfid*, Fid*);
317dd7cddfSDavid du Colombier static	Xfid*	fsyswalk(Xfid*, Fid*);
327dd7cddfSDavid du Colombier static	Xfid*	fsysopen(Xfid*, Fid*);
337dd7cddfSDavid du Colombier static	Xfid*	fsyscreate(Xfid*, Fid*);
347dd7cddfSDavid du Colombier static	Xfid*	fsysread(Xfid*, Fid*);
357dd7cddfSDavid du Colombier static	Xfid*	fsyswrite(Xfid*, Fid*);
367dd7cddfSDavid du Colombier static	Xfid*	fsysclunk(Xfid*, Fid*);
377dd7cddfSDavid du Colombier static	Xfid*	fsysremove(Xfid*, Fid*);
387dd7cddfSDavid du Colombier static	Xfid*	fsysstat(Xfid*, Fid*);
397dd7cddfSDavid du Colombier static	Xfid*	fsyswstat(Xfid*, Fid*);
407dd7cddfSDavid du Colombier 
417dd7cddfSDavid du Colombier Xfid* 	(*fcall[Tmax])(Xfid*, Fid*) =
427dd7cddfSDavid du Colombier {
437dd7cddfSDavid du Colombier 	[Tflush]	= fsysflush,
449a747e4fSDavid du Colombier 	[Tversion]	= fsysversion,
459a747e4fSDavid du Colombier 	[Tauth]	= fsysauth,
467dd7cddfSDavid du Colombier 	[Tattach]	= fsysattach,
477dd7cddfSDavid du Colombier 	[Twalk]	= fsyswalk,
487dd7cddfSDavid du Colombier 	[Topen]	= fsysopen,
497dd7cddfSDavid du Colombier 	[Tcreate]	= fsyscreate,
507dd7cddfSDavid du Colombier 	[Tread]	= fsysread,
517dd7cddfSDavid du Colombier 	[Twrite]	= fsyswrite,
527dd7cddfSDavid du Colombier 	[Tclunk]	= fsysclunk,
537dd7cddfSDavid du Colombier 	[Tremove]= fsysremove,
547dd7cddfSDavid du Colombier 	[Tstat]	= fsysstat,
557dd7cddfSDavid du Colombier 	[Twstat]	= fsyswstat,
567dd7cddfSDavid du Colombier };
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier char Eperm[] = "permission denied";
597dd7cddfSDavid du Colombier char Eexist[] = "file does not exist";
607dd7cddfSDavid du Colombier char Enotdir[] = "not a directory";
617dd7cddfSDavid du Colombier 
627dd7cddfSDavid du Colombier Dirtab dirtab[]=
637dd7cddfSDavid du Colombier {
649a747e4fSDavid du Colombier 	{ ".",			QTDIR,	Qdir,		0500|DMDIR },
659a747e4fSDavid du Colombier 	{ "acme",		QTDIR,	Qacme,	0500|DMDIR },
669a747e4fSDavid du Colombier 	{ "cons",		QTFILE,	Qcons,	0600 },
679a747e4fSDavid du Colombier 	{ "consctl",	QTFILE,	Qconsctl,	0000 },
689a747e4fSDavid du Colombier 	{ "draw",		QTDIR,	Qdraw,	0000|DMDIR },	/* to suppress graphics progs started in acme */
699a747e4fSDavid du Colombier 	{ "editout",	QTFILE,	Qeditout,	0200 },
709a747e4fSDavid du Colombier 	{ "index",		QTFILE,	Qindex,	0400 },
719a747e4fSDavid du Colombier 	{ "label",		QTFILE,	Qlabel,	0600 },
729a747e4fSDavid du Colombier 	{ "new",		QTDIR,	Qnew,	0500|DMDIR },
737dd7cddfSDavid du Colombier 	{ nil, }
747dd7cddfSDavid du Colombier };
757dd7cddfSDavid du Colombier 
767dd7cddfSDavid du Colombier Dirtab dirtabw[]=
777dd7cddfSDavid du Colombier {
789a747e4fSDavid du Colombier 	{ ".",			QTDIR,		Qdir,			0500|DMDIR },
799a747e4fSDavid du Colombier 	{ "addr",		QTFILE,		QWaddr,		0600 },
809a747e4fSDavid du Colombier 	{ "body",		QTAPPEND,	QWbody,		0600|DMAPPEND },
819a747e4fSDavid du Colombier 	{ "ctl",		QTFILE,		QWctl,		0600 },
829a747e4fSDavid du Colombier 	{ "data",		QTFILE,		QWdata,		0600 },
839a747e4fSDavid du Colombier 	{ "editout",	QTFILE,		QWeditout,	0200 },
84673c3d8aSDavid du Colombier 	{ "errors",		QTFILE,		QWerrors,		0200 },
859a747e4fSDavid du Colombier 	{ "event",		QTFILE,		QWevent,		0600 },
869a747e4fSDavid du Colombier 	{ "rdsel",		QTFILE,		QWrdsel,		0400 },
879a747e4fSDavid du Colombier 	{ "wrsel",		QTFILE,		QWwrsel,		0200 },
889a747e4fSDavid du Colombier 	{ "tag",		QTAPPEND,	QWtag,		0600|DMAPPEND },
89673c3d8aSDavid du Colombier 	{ "xdata",		QTFILE,		QWxdata,		0600 },
907dd7cddfSDavid du Colombier 	{ nil, }
917dd7cddfSDavid du Colombier };
927dd7cddfSDavid du Colombier 
937dd7cddfSDavid du Colombier typedef struct Mnt Mnt;
947dd7cddfSDavid du Colombier struct Mnt
957dd7cddfSDavid du Colombier {
967dd7cddfSDavid du Colombier 	QLock;
977dd7cddfSDavid du Colombier 	int		id;
987dd7cddfSDavid du Colombier 	Mntdir	*md;
997dd7cddfSDavid du Colombier };
1007dd7cddfSDavid du Colombier 
1017dd7cddfSDavid du Colombier Mnt	mnt;
1027dd7cddfSDavid du Colombier 
1037dd7cddfSDavid du Colombier Xfid*	respond(Xfid*, Fcall*, char*);
1049a747e4fSDavid du Colombier int		dostat(int, Dirtab*, uchar*, int, uint);
1057dd7cddfSDavid du Colombier uint	getclock(void);
1067dd7cddfSDavid du Colombier 
1079a747e4fSDavid du Colombier char	*user = "Wile E. Coyote";
1087dd7cddfSDavid du Colombier int	clockfd;
1097dd7cddfSDavid du Colombier static int closing = 0;
1109a747e4fSDavid du Colombier int	messagesize = Maxblock+IOHDRSZ;	/* good start */
1117dd7cddfSDavid du Colombier 
1127dd7cddfSDavid du Colombier void	fsysproc(void *);
1137dd7cddfSDavid du Colombier 
1147dd7cddfSDavid du Colombier void
fsysinit(void)1157dd7cddfSDavid du Colombier fsysinit(void)
1167dd7cddfSDavid du Colombier {
1177dd7cddfSDavid du Colombier 	int p[2];
1187dd7cddfSDavid du Colombier 	int n, fd;
1199a747e4fSDavid du Colombier 	char buf[256];
1207dd7cddfSDavid du Colombier 
1217dd7cddfSDavid du Colombier 	if(pipe(p) < 0)
1227dd7cddfSDavid du Colombier 		error("can't create pipe");
1237dd7cddfSDavid du Colombier 	cfd = p[0];
1247dd7cddfSDavid du Colombier 	sfd = p[1];
1259a747e4fSDavid du Colombier 	fmtinstall('F', fcallfmt);
1267dd7cddfSDavid du Colombier 	clockfd = open("/dev/time", OREAD|OCEXEC);
1277dd7cddfSDavid du Colombier 	fd = open("/dev/user", OREAD);
1287dd7cddfSDavid du Colombier 	if(fd >= 0){
1299a747e4fSDavid du Colombier 		n = read(fd, buf, sizeof buf-1);
1309a747e4fSDavid du Colombier 		if(n > 0){
1319a747e4fSDavid du Colombier 			buf[n] = 0;
1329a747e4fSDavid du Colombier 			user = estrdup(buf);
1339a747e4fSDavid du Colombier 		}
1347dd7cddfSDavid du Colombier 		close(fd);
1357dd7cddfSDavid du Colombier 	}
1367dd7cddfSDavid du Colombier 	proccreate(fsysproc, nil, STACK);
1377dd7cddfSDavid du Colombier }
1387dd7cddfSDavid du Colombier 
1397dd7cddfSDavid du Colombier void
fsysproc(void *)1407dd7cddfSDavid du Colombier fsysproc(void *)
1417dd7cddfSDavid du Colombier {
1427dd7cddfSDavid du Colombier 	int n;
1437dd7cddfSDavid du Colombier 	Xfid *x;
1447dd7cddfSDavid du Colombier 	Fid *f;
1457dd7cddfSDavid du Colombier 	Fcall t;
1469a747e4fSDavid du Colombier 	uchar *buf;
1477dd7cddfSDavid du Colombier 
148*5d9de2d3SDavid du Colombier 	threadsetname("fsysproc");
149*5d9de2d3SDavid du Colombier 
1507dd7cddfSDavid du Colombier 	x = nil;
1517dd7cddfSDavid du Colombier 	for(;;){
1529a747e4fSDavid du Colombier 		buf = emalloc(messagesize+UTFmax);	/* overflow for appending partial rune in xfidwrite */
1539a747e4fSDavid du Colombier 		n = read9pmsg(sfd, buf, messagesize);
1547dd7cddfSDavid du Colombier 		if(n <= 0){
1557dd7cddfSDavid du Colombier 			if(closing)
1567dd7cddfSDavid du Colombier 				break;
1577dd7cddfSDavid du Colombier 			error("i/o error on server channel");
1587dd7cddfSDavid du Colombier 		}
1597dd7cddfSDavid du Colombier 		if(x == nil){
1607dd7cddfSDavid du Colombier 			sendp(cxfidalloc, nil);
1617dd7cddfSDavid du Colombier 			x = recvp(cxfidalloc);
1627dd7cddfSDavid du Colombier 		}
1637dd7cddfSDavid du Colombier 		x->buf = buf;
1649a747e4fSDavid du Colombier 		if(convM2S(buf, n, x) != n)
1657dd7cddfSDavid du Colombier 			error("convert error in convM2S");
1667dd7cddfSDavid du Colombier 		if(DEBUG)
1677dd7cddfSDavid du Colombier 			fprint(2, "%F\n", &x->Fcall);
1687dd7cddfSDavid du Colombier 		if(fcall[x->type] == nil)
1697dd7cddfSDavid du Colombier 			x = respond(x, &t, "bad fcall type");
1707dd7cddfSDavid du Colombier 		else{
171e7d29567SDavid du Colombier 			switch(x->type){
172e7d29567SDavid du Colombier 			case Tversion:
173e7d29567SDavid du Colombier 			case Tauth:
174e7d29567SDavid du Colombier 			case Tflush:
1757dd7cddfSDavid du Colombier 				f = nil;
176e7d29567SDavid du Colombier 				break;
177e7d29567SDavid du Colombier 			case Tattach:
1787dd7cddfSDavid du Colombier 				f = newfid(x->fid);
179e7d29567SDavid du Colombier 				break;
180e7d29567SDavid du Colombier 			default:
181e7d29567SDavid du Colombier 				f = newfid(x->fid);
182e7d29567SDavid du Colombier 				if(!f->busy){
183e7d29567SDavid du Colombier 					x->f = f;
184e7d29567SDavid du Colombier 					x = respond(x, &t, "fid not in use");
185e7d29567SDavid du Colombier 					continue;
186e7d29567SDavid du Colombier 				}
187e7d29567SDavid du Colombier 				break;
188e7d29567SDavid du Colombier 			}
1897dd7cddfSDavid du Colombier 			x->f = f;
1907dd7cddfSDavid du Colombier 			x  = (*fcall[x->type])(x, f);
1917dd7cddfSDavid du Colombier 		}
1927dd7cddfSDavid du Colombier 	}
1937dd7cddfSDavid du Colombier }
1947dd7cddfSDavid du Colombier 
1957dd7cddfSDavid du Colombier Mntdir*
fsysaddid(Rune * dir,int ndir,Rune ** incl,int nincl)1967dd7cddfSDavid du Colombier fsysaddid(Rune *dir, int ndir, Rune **incl, int nincl)
1977dd7cddfSDavid du Colombier {
1987dd7cddfSDavid du Colombier 	Mntdir *m;
1997dd7cddfSDavid du Colombier 	int id;
2007dd7cddfSDavid du Colombier 
2017dd7cddfSDavid du Colombier 	qlock(&mnt);
2027dd7cddfSDavid du Colombier 	id = ++mnt.id;
2037dd7cddfSDavid du Colombier 	m = emalloc(sizeof *m);
2047dd7cddfSDavid du Colombier 	m->id = id;
2057dd7cddfSDavid du Colombier 	m->dir =  dir;
2067dd7cddfSDavid du Colombier 	m->ref = 1;	/* one for Command, one will be incremented in attach */
2077dd7cddfSDavid du Colombier 	m->ndir = ndir;
2087dd7cddfSDavid du Colombier 	m->next = mnt.md;
2097dd7cddfSDavid du Colombier 	m->incl = incl;
2107dd7cddfSDavid du Colombier 	m->nincl = nincl;
2117dd7cddfSDavid du Colombier 	mnt.md = m;
2127dd7cddfSDavid du Colombier 	qunlock(&mnt);
2137dd7cddfSDavid du Colombier 	return m;
2147dd7cddfSDavid du Colombier }
2157dd7cddfSDavid du Colombier 
2167dd7cddfSDavid du Colombier void
fsysincid(Mntdir * m)2173df12bc6SDavid du Colombier fsysincid(Mntdir *m)
2183df12bc6SDavid du Colombier {
2193df12bc6SDavid du Colombier 	qlock(&mnt);
2203df12bc6SDavid du Colombier 	m->ref++;
2213df12bc6SDavid du Colombier 	qunlock(&mnt);
2223df12bc6SDavid du Colombier }
2233df12bc6SDavid du Colombier 
2243df12bc6SDavid du Colombier void
fsysdelid(Mntdir * idm)2257dd7cddfSDavid du Colombier fsysdelid(Mntdir *idm)
2267dd7cddfSDavid du Colombier {
2277dd7cddfSDavid du Colombier 	Mntdir *m, *prev;
2287dd7cddfSDavid du Colombier 	int i;
2297dd7cddfSDavid du Colombier 	char buf[64];
2307dd7cddfSDavid du Colombier 
2317dd7cddfSDavid du Colombier 	if(idm == nil)
2327dd7cddfSDavid du Colombier 		return;
2337dd7cddfSDavid du Colombier 	qlock(&mnt);
2347dd7cddfSDavid du Colombier 	if(--idm->ref > 0){
2357dd7cddfSDavid du Colombier 		qunlock(&mnt);
2367dd7cddfSDavid du Colombier 		return;
2377dd7cddfSDavid du Colombier 	}
2387dd7cddfSDavid du Colombier 	prev = nil;
2397dd7cddfSDavid du Colombier 	for(m=mnt.md; m; m=m->next){
2407dd7cddfSDavid du Colombier 		if(m == idm){
2417dd7cddfSDavid du Colombier 			if(prev)
2427dd7cddfSDavid du Colombier 				prev->next = m->next;
2437dd7cddfSDavid du Colombier 			else
2447dd7cddfSDavid du Colombier 				mnt.md = m->next;
2457dd7cddfSDavid du Colombier 			for(i=0; i<m->nincl; i++)
2467dd7cddfSDavid du Colombier 				free(m->incl[i]);
2477dd7cddfSDavid du Colombier 			free(m->incl);
2487dd7cddfSDavid du Colombier 			free(m->dir);
2497dd7cddfSDavid du Colombier 			free(m);
2507dd7cddfSDavid du Colombier 			qunlock(&mnt);
2517dd7cddfSDavid du Colombier 			return;
2527dd7cddfSDavid du Colombier 		}
2537dd7cddfSDavid du Colombier 		prev = m;
2547dd7cddfSDavid du Colombier 	}
2557dd7cddfSDavid du Colombier 	qunlock(&mnt);
2567dd7cddfSDavid du Colombier 	sprint(buf, "fsysdelid: can't find id %d\n", idm->id);
25759cc4ca5SDavid du Colombier 	sendp(cerr, estrdup(buf));
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier 
2607dd7cddfSDavid du Colombier /*
2619a747e4fSDavid du Colombier  * Called only in exec.c:/^run(), from a different FD group
2627dd7cddfSDavid du Colombier  */
2637dd7cddfSDavid du Colombier Mntdir*
fsysmount(Rune * dir,int ndir,Rune ** incl,int nincl)2647dd7cddfSDavid du Colombier fsysmount(Rune *dir, int ndir, Rune **incl, int nincl)
2657dd7cddfSDavid du Colombier {
2669a747e4fSDavid du Colombier 	char buf[256];
2677dd7cddfSDavid du Colombier 	Mntdir *m;
2687dd7cddfSDavid du Colombier 
2697dd7cddfSDavid du Colombier 	/* close server side so don't hang if acme is half-exited */
2707dd7cddfSDavid du Colombier 	close(sfd);
2717dd7cddfSDavid du Colombier 	m = fsysaddid(dir, ndir, incl, nincl);
2727dd7cddfSDavid du Colombier 	sprint(buf, "%d", m->id);
2739a747e4fSDavid du Colombier 	if(mount(cfd, -1, "/mnt/acme", MREPL, buf) < 0){
2747dd7cddfSDavid du Colombier 		fsysdelid(m);
2757dd7cddfSDavid du Colombier 		return nil;
2767dd7cddfSDavid du Colombier 	}
2777dd7cddfSDavid du Colombier 	close(cfd);
2787dd7cddfSDavid du Colombier 	bind("/mnt/acme", "/mnt/wsys", MREPL);
2797dd7cddfSDavid du Colombier 	if(bind("/mnt/acme", "/dev", MBEFORE) < 0){
2807dd7cddfSDavid du Colombier 		fsysdelid(m);
2817dd7cddfSDavid du Colombier 		return nil;
2827dd7cddfSDavid du Colombier 	}
2837dd7cddfSDavid du Colombier 	return m;
2847dd7cddfSDavid du Colombier }
2857dd7cddfSDavid du Colombier 
2867dd7cddfSDavid du Colombier void
fsysclose(void)2877dd7cddfSDavid du Colombier fsysclose(void)
2887dd7cddfSDavid du Colombier {
2897dd7cddfSDavid du Colombier 	closing = 1;
2907dd7cddfSDavid du Colombier 	close(cfd);
2917dd7cddfSDavid du Colombier 	close(sfd);
2927dd7cddfSDavid du Colombier }
2937dd7cddfSDavid du Colombier 
2947dd7cddfSDavid du Colombier Xfid*
respond(Xfid * x,Fcall * t,char * err)2957dd7cddfSDavid du Colombier respond(Xfid *x, Fcall *t, char *err)
2967dd7cddfSDavid du Colombier {
2977dd7cddfSDavid du Colombier 	int n;
2987dd7cddfSDavid du Colombier 
2997dd7cddfSDavid du Colombier 	if(err){
3007dd7cddfSDavid du Colombier 		t->type = Rerror;
3019a747e4fSDavid du Colombier 		t->ename = err;
3027dd7cddfSDavid du Colombier 	}else
3037dd7cddfSDavid du Colombier 		t->type = x->type+1;
3047dd7cddfSDavid du Colombier 	t->fid = x->fid;
3057dd7cddfSDavid du Colombier 	t->tag = x->tag;
3067dd7cddfSDavid du Colombier 	if(x->buf == nil)
3079a747e4fSDavid du Colombier 		x->buf = emalloc(messagesize);
3089a747e4fSDavid du Colombier 	n = convS2M(t, x->buf, messagesize);
3099a747e4fSDavid du Colombier 	if(n <= 0)
3107dd7cddfSDavid du Colombier 		error("convert error in convS2M");
3117dd7cddfSDavid du Colombier 	if(write(sfd, x->buf, n) != n)
3127dd7cddfSDavid du Colombier 		error("write error in respond");
3139a747e4fSDavid du Colombier 	free(x->buf);
3147dd7cddfSDavid du Colombier 	x->buf = nil;
3157dd7cddfSDavid du Colombier 	if(DEBUG)
3167dd7cddfSDavid du Colombier 		fprint(2, "r: %F\n", t);
3177dd7cddfSDavid du Colombier 	return x;
3187dd7cddfSDavid du Colombier }
3197dd7cddfSDavid du Colombier 
3207dd7cddfSDavid du Colombier static
3217dd7cddfSDavid du Colombier Xfid*
fsysversion(Xfid * x,Fid *)3229a747e4fSDavid du Colombier fsysversion(Xfid *x, Fid*)
3237dd7cddfSDavid du Colombier {
3247dd7cddfSDavid du Colombier 	Fcall t;
3257dd7cddfSDavid du Colombier 
3269a747e4fSDavid du Colombier 	if(x->msize < 256)
3279a747e4fSDavid du Colombier 		return respond(x, &t, "version: message size too small");
328*5d9de2d3SDavid du Colombier 	if(x->msize < messagesize)
3299a747e4fSDavid du Colombier 		messagesize = x->msize;
3309a747e4fSDavid du Colombier 	t.msize = messagesize;
3319a747e4fSDavid du Colombier 	if(strncmp(x->version, "9P2000", 6) != 0)
3329a747e4fSDavid du Colombier 		return respond(x, &t, "unrecognized 9P version");
3339a747e4fSDavid du Colombier 	t.version = "9P2000";
3347dd7cddfSDavid du Colombier 	return respond(x, &t, nil);
3357dd7cddfSDavid du Colombier }
3367dd7cddfSDavid du Colombier 
3377dd7cddfSDavid du Colombier static
3387dd7cddfSDavid du Colombier Xfid*
fsysauth(Xfid * x,Fid *)3399a747e4fSDavid du Colombier fsysauth(Xfid *x, Fid*)
3407dd7cddfSDavid du Colombier {
3410fb3f58eSDavid du Colombier 	Fcall t;
3420fb3f58eSDavid du Colombier 
3430fb3f58eSDavid du Colombier 	return respond(x, &t, "acme: authentication not required");
3447dd7cddfSDavid du Colombier }
3457dd7cddfSDavid du Colombier 
3467dd7cddfSDavid du Colombier static
3477dd7cddfSDavid du Colombier Xfid*
fsysflush(Xfid * x,Fid *)3487dd7cddfSDavid du Colombier fsysflush(Xfid *x, Fid*)
3497dd7cddfSDavid du Colombier {
3507dd7cddfSDavid du Colombier 	sendp(x->c, xfidflush);
3517dd7cddfSDavid du Colombier 	return nil;
3527dd7cddfSDavid du Colombier }
3537dd7cddfSDavid du Colombier 
3547dd7cddfSDavid du Colombier static
3557dd7cddfSDavid du Colombier Xfid*
fsysattach(Xfid * x,Fid * f)3567dd7cddfSDavid du Colombier fsysattach(Xfid *x, Fid *f)
3577dd7cddfSDavid du Colombier {
3587dd7cddfSDavid du Colombier 	Fcall t;
3597dd7cddfSDavid du Colombier 	int id;
3607dd7cddfSDavid du Colombier 	Mntdir *m;
3617dd7cddfSDavid du Colombier 
3627dd7cddfSDavid du Colombier 	if(strcmp(x->uname, user) != 0)
3637dd7cddfSDavid du Colombier 		return respond(x, &t, Eperm);
3647dd7cddfSDavid du Colombier 	f->busy = TRUE;
3657dd7cddfSDavid du Colombier 	f->open = FALSE;
3669a747e4fSDavid du Colombier 	f->qid.path = Qdir;
3679a747e4fSDavid du Colombier 	f->qid.type = QTDIR;
3689a747e4fSDavid du Colombier 	f->qid.vers = 0;
3697dd7cddfSDavid du Colombier 	f->dir = dirtab;
3707dd7cddfSDavid du Colombier 	f->nrpart = 0;
3717dd7cddfSDavid du Colombier 	f->w = nil;
3727dd7cddfSDavid du Colombier 	t.qid = f->qid;
3737dd7cddfSDavid du Colombier 	f->mntdir = nil;
3747dd7cddfSDavid du Colombier 	id = atoi(x->aname);
3757dd7cddfSDavid du Colombier 	qlock(&mnt);
3767dd7cddfSDavid du Colombier 	for(m=mnt.md; m; m=m->next)
3777dd7cddfSDavid du Colombier 		if(m->id == id){
3787dd7cddfSDavid du Colombier 			f->mntdir = m;
3797dd7cddfSDavid du Colombier 			m->ref++;
3807dd7cddfSDavid du Colombier 			break;
3817dd7cddfSDavid du Colombier 		}
3827dd7cddfSDavid du Colombier 	if(m == nil)
38359cc4ca5SDavid du Colombier 		sendp(cerr, estrdup("unknown id in attach"));
3847dd7cddfSDavid du Colombier 	qunlock(&mnt);
3857dd7cddfSDavid du Colombier 	return respond(x, &t, nil);
3867dd7cddfSDavid du Colombier }
3877dd7cddfSDavid du Colombier 
3887dd7cddfSDavid du Colombier static
3897dd7cddfSDavid du Colombier Xfid*
fsyswalk(Xfid * x,Fid * f)3909a747e4fSDavid du Colombier fsyswalk(Xfid *x, Fid *f)
3917dd7cddfSDavid du Colombier {
3927dd7cddfSDavid du Colombier 	Fcall t;
3939a747e4fSDavid du Colombier 	int c, i, j, id;
3949a747e4fSDavid du Colombier 	Qid q;
3959a747e4fSDavid du Colombier 	uchar type;
3969a747e4fSDavid du Colombier 	ulong path;
3979a747e4fSDavid du Colombier 	Fid *nf;
3989a747e4fSDavid du Colombier 	Dirtab *d, *dir;
3999a747e4fSDavid du Colombier 	Window *w;
4009a747e4fSDavid du Colombier 	char *err;
4017dd7cddfSDavid du Colombier 
4029a747e4fSDavid du Colombier 	nf = nil;
4039a747e4fSDavid du Colombier 	w = nil;
4047dd7cddfSDavid du Colombier 	if(f->open)
4059a747e4fSDavid du Colombier 		return respond(x, &t, "walk of open file");
4069a747e4fSDavid du Colombier 	if(x->fid != x->newfid){
4077dd7cddfSDavid du Colombier 		nf = newfid(x->newfid);
4089a747e4fSDavid du Colombier 		if(nf->busy)
4099a747e4fSDavid du Colombier 			return respond(x, &t, "newfid already in use");
4107dd7cddfSDavid du Colombier 		nf->busy = TRUE;
4117dd7cddfSDavid du Colombier 		nf->open = FALSE;
4127dd7cddfSDavid du Colombier 		nf->mntdir = f->mntdir;
4137dd7cddfSDavid du Colombier 		if(f->mntdir)
4147dd7cddfSDavid du Colombier 			f->mntdir->ref++;
4157dd7cddfSDavid du Colombier 		nf->dir = f->dir;
4167dd7cddfSDavid du Colombier 		nf->qid = f->qid;
4177dd7cddfSDavid du Colombier 		nf->w = f->w;
4187dd7cddfSDavid du Colombier 		nf->nrpart = 0;	/* not open, so must be zero */
4197dd7cddfSDavid du Colombier 		if(nf->w)
4207dd7cddfSDavid du Colombier 			incref(nf->w);
4219a747e4fSDavid du Colombier 		f = nf;	/* walk f */
4227dd7cddfSDavid du Colombier 	}
4237dd7cddfSDavid du Colombier 
4249a747e4fSDavid du Colombier 	t.nwqid = 0;
4259a747e4fSDavid du Colombier 	err = nil;
4269a747e4fSDavid du Colombier 	dir = nil;
4279a747e4fSDavid du Colombier 	id = WIN(f->qid);
4289a747e4fSDavid du Colombier 	q = f->qid;
4297dd7cddfSDavid du Colombier 
4309a747e4fSDavid du Colombier 	if(x->nwname > 0){
4319a747e4fSDavid du Colombier 		for(i=0; i<x->nwname; i++){
4329a747e4fSDavid du Colombier 			if((q.type & QTDIR) == 0){
4339a747e4fSDavid du Colombier 				err = Enotdir;
4349a747e4fSDavid du Colombier 				break;
4359a747e4fSDavid du Colombier 			}
4369a747e4fSDavid du Colombier 
4379a747e4fSDavid du Colombier 			if(strcmp(x->wname[i], "..") == 0){
4389a747e4fSDavid du Colombier 				type = QTDIR;
4399a747e4fSDavid du Colombier 				path = Qdir;
4407dd7cddfSDavid du Colombier 				id = 0;
4419a747e4fSDavid du Colombier 				if(w){
4429a747e4fSDavid du Colombier 					winclose(w);
4439a747e4fSDavid du Colombier 					w = nil;
4447dd7cddfSDavid du Colombier 				}
4459a747e4fSDavid du Colombier     Accept:
4469a747e4fSDavid du Colombier 				if(i == MAXWELEM){
4479a747e4fSDavid du Colombier 					err = "name too long";
4489a747e4fSDavid du Colombier 					break;
4499a747e4fSDavid du Colombier 				}
4509a747e4fSDavid du Colombier 				q.type = type;
4519a747e4fSDavid du Colombier 				q.vers = 0;
4529a747e4fSDavid du Colombier 				q.path = QID(id, path);
4539a747e4fSDavid du Colombier 				t.wqid[t.nwqid++] = q;
4549a747e4fSDavid du Colombier 				continue;
4559a747e4fSDavid du Colombier 			}
4569a747e4fSDavid du Colombier 
4577dd7cddfSDavid du Colombier 			/* is it a numeric name? */
4589a747e4fSDavid du Colombier 			for(j=0; (c=x->wname[i][j]); j++)
4597dd7cddfSDavid du Colombier 				if(c<'0' || '9'<c)
4607dd7cddfSDavid du Colombier 					goto Regular;
4617dd7cddfSDavid du Colombier 			/* yes: it's a directory */
4629a747e4fSDavid du Colombier 			if(w)	/* name has form 27/23; get out before losing w */
4639a747e4fSDavid du Colombier 				break;
4649a747e4fSDavid du Colombier 			id = atoi(x->wname[i]);
4657dd7cddfSDavid du Colombier 			qlock(&row);
4667dd7cddfSDavid du Colombier 			w = lookid(id, FALSE);
4677dd7cddfSDavid du Colombier 			if(w == nil){
4687dd7cddfSDavid du Colombier 				qunlock(&row);
4699a747e4fSDavid du Colombier 				break;
4707dd7cddfSDavid du Colombier 			}
4719a747e4fSDavid du Colombier 			incref(w);	/* we'll drop reference at end if there's an error */
4729a747e4fSDavid du Colombier 			path = Qdir;
4739a747e4fSDavid du Colombier 			type = QTDIR;
4747dd7cddfSDavid du Colombier 			qunlock(&row);
4759a747e4fSDavid du Colombier 			dir = dirtabw;
4769a747e4fSDavid du Colombier 			goto Accept;
4777dd7cddfSDavid du Colombier 
4787dd7cddfSDavid du Colombier     Regular:
4799a747e4fSDavid du Colombier //			if(FILE(f->qid) == Qacme)	/* empty directory */
4809a747e4fSDavid du Colombier //				break;
4819a747e4fSDavid du Colombier 			if(strcmp(x->wname[i], "new") == 0){
4829a747e4fSDavid du Colombier 				if(w)
4839a747e4fSDavid du Colombier 					error("w set in walk to new");
4849a747e4fSDavid du Colombier 				sendp(cnewwindow, nil);	/* signal newwindowthread */
4859a747e4fSDavid du Colombier 				w = recvp(cnewwindow);	/* receive new window */
4869a747e4fSDavid du Colombier 				incref(w);
4879a747e4fSDavid du Colombier 				type = QTDIR;
4889a747e4fSDavid du Colombier 				path = QID(w->id, Qdir);
4899a747e4fSDavid du Colombier 				id = w->id;
4909a747e4fSDavid du Colombier 				dir = dirtabw;
4919a747e4fSDavid du Colombier 				goto Accept;
4929a747e4fSDavid du Colombier 			}
4939a747e4fSDavid du Colombier 
4947dd7cddfSDavid du Colombier 			if(id == 0)
4957dd7cddfSDavid du Colombier 				d = dirtab;
4967dd7cddfSDavid du Colombier 			else
4977dd7cddfSDavid du Colombier 				d = dirtabw;
4987dd7cddfSDavid du Colombier 			d++;	/* skip '.' */
4997dd7cddfSDavid du Colombier 			for(; d->name; d++)
5009a747e4fSDavid du Colombier 				if(strcmp(x->wname[i], d->name) == 0){
5019a747e4fSDavid du Colombier 					path = d->qid;
5029a747e4fSDavid du Colombier 					type = d->type;
5039a747e4fSDavid du Colombier 					dir = d;
5049a747e4fSDavid du Colombier 					goto Accept;
5057dd7cddfSDavid du Colombier 				}
5067dd7cddfSDavid du Colombier 
5079a747e4fSDavid du Colombier 			break;	/* file not found */
5087dd7cddfSDavid du Colombier 		}
5097dd7cddfSDavid du Colombier 
5109a747e4fSDavid du Colombier 		if(i==0 && err == nil)
5119a747e4fSDavid du Colombier 			err = Eexist;
5129a747e4fSDavid du Colombier 	}
5137dd7cddfSDavid du Colombier 
5149a747e4fSDavid du Colombier 	if(err!=nil || t.nwqid<x->nwname){
5159a747e4fSDavid du Colombier 		if(nf){
5169a747e4fSDavid du Colombier 			nf->busy = FALSE;
5179a747e4fSDavid du Colombier 			fsysdelid(nf->mntdir);
5189a747e4fSDavid du Colombier 		}
5199a747e4fSDavid du Colombier 	}else if(t.nwqid  == x->nwname){
5209a747e4fSDavid du Colombier 		if(w){
5219a747e4fSDavid du Colombier 			f->w = w;
5229a747e4fSDavid du Colombier 			w = nil;	/* don't drop the reference */
5239a747e4fSDavid du Colombier 		}
5249a747e4fSDavid du Colombier 		if(dir)
5259a747e4fSDavid du Colombier 			f->dir = dir;
5269a747e4fSDavid du Colombier 		f->qid = q;
5279a747e4fSDavid du Colombier 	}
5289a747e4fSDavid du Colombier 
5299a747e4fSDavid du Colombier 	if(w != nil)
5309a747e4fSDavid du Colombier 		winclose(w);
5319a747e4fSDavid du Colombier 
5329a747e4fSDavid du Colombier 	return respond(x, &t, err);
5337dd7cddfSDavid du Colombier }
5347dd7cddfSDavid du Colombier 
5357dd7cddfSDavid du Colombier static
5367dd7cddfSDavid du Colombier Xfid*
fsysopen(Xfid * x,Fid * f)5377dd7cddfSDavid du Colombier fsysopen(Xfid *x, Fid *f)
5387dd7cddfSDavid du Colombier {
5397dd7cddfSDavid du Colombier 	Fcall t;
5407dd7cddfSDavid du Colombier 	int m;
5417dd7cddfSDavid du Colombier 
5427dd7cddfSDavid du Colombier 	/* can't truncate anything, so just disregard */
5437dd7cddfSDavid du Colombier 	x->mode &= ~(OTRUNC|OCEXEC);
5447dd7cddfSDavid du Colombier 	/* can't execute or remove anything */
5457dd7cddfSDavid du Colombier 	if(x->mode==OEXEC || (x->mode&ORCLOSE))
5467dd7cddfSDavid du Colombier 		goto Deny;
5477dd7cddfSDavid du Colombier 	switch(x->mode){
5487dd7cddfSDavid du Colombier 	default:
5497dd7cddfSDavid du Colombier 		goto Deny;
5507dd7cddfSDavid du Colombier 	case OREAD:
5517dd7cddfSDavid du Colombier 		m = 0400;
5527dd7cddfSDavid du Colombier 		break;
5537dd7cddfSDavid du Colombier 	case OWRITE:
5547dd7cddfSDavid du Colombier 		m = 0200;
5557dd7cddfSDavid du Colombier 		break;
5567dd7cddfSDavid du Colombier 	case ORDWR:
5577dd7cddfSDavid du Colombier 		m = 0600;
5587dd7cddfSDavid du Colombier 		break;
5597dd7cddfSDavid du Colombier 	}
5609a747e4fSDavid du Colombier 	if(((f->dir->perm&~(DMDIR|DMAPPEND))&m) != m)
5617dd7cddfSDavid du Colombier 		goto Deny;
5627dd7cddfSDavid du Colombier 
5637dd7cddfSDavid du Colombier 	sendp(x->c, xfidopen);
5647dd7cddfSDavid du Colombier 	return nil;
5657dd7cddfSDavid du Colombier 
5667dd7cddfSDavid du Colombier     Deny:
5677dd7cddfSDavid du Colombier 	return respond(x, &t, Eperm);
5687dd7cddfSDavid du Colombier }
5697dd7cddfSDavid du Colombier 
5707dd7cddfSDavid du Colombier static
5717dd7cddfSDavid du Colombier Xfid*
fsyscreate(Xfid * x,Fid *)5727dd7cddfSDavid du Colombier fsyscreate(Xfid *x, Fid*)
5737dd7cddfSDavid du Colombier {
5747dd7cddfSDavid du Colombier 	Fcall t;
5757dd7cddfSDavid du Colombier 
5767dd7cddfSDavid du Colombier 	return respond(x, &t, Eperm);
5777dd7cddfSDavid du Colombier }
5787dd7cddfSDavid du Colombier 
5797dd7cddfSDavid du Colombier static
5807dd7cddfSDavid du Colombier int
idcmp(void * a,void * b)5817dd7cddfSDavid du Colombier idcmp(void *a, void *b)
5827dd7cddfSDavid du Colombier {
5837dd7cddfSDavid du Colombier 	return *(int*)a - *(int*)b;
5847dd7cddfSDavid du Colombier }
5857dd7cddfSDavid du Colombier 
5867dd7cddfSDavid du Colombier static
5877dd7cddfSDavid du Colombier Xfid*
fsysread(Xfid * x,Fid * f)5887dd7cddfSDavid du Colombier fsysread(Xfid *x, Fid *f)
5897dd7cddfSDavid du Colombier {
5907dd7cddfSDavid du Colombier 	Fcall t;
5919a747e4fSDavid du Colombier 	uchar *b;
5927dd7cddfSDavid du Colombier 	int i, id, n, o, e, j, k, *ids, nids;
5937dd7cddfSDavid du Colombier 	Dirtab *d, dt;
5947dd7cddfSDavid du Colombier 	Column *c;
5959a747e4fSDavid du Colombier 	uint clock, len;
5967dd7cddfSDavid du Colombier 	char buf[16];
5977dd7cddfSDavid du Colombier 
5989a747e4fSDavid du Colombier 	if(f->qid.type & QTDIR){
5997dd7cddfSDavid du Colombier 		if(FILE(f->qid) == Qacme){	/* empty dir */
6007dd7cddfSDavid du Colombier 			t.data = nil;
6017dd7cddfSDavid du Colombier 			t.count = 0;
6027dd7cddfSDavid du Colombier 			respond(x, &t, nil);
6037dd7cddfSDavid du Colombier 			return x;
6047dd7cddfSDavid du Colombier 		}
6057dd7cddfSDavid du Colombier 		o = x->offset;
6067dd7cddfSDavid du Colombier 		e = x->offset+x->count;
6077dd7cddfSDavid du Colombier 		clock = getclock();
6089a747e4fSDavid du Colombier 		b = emalloc(messagesize);
6097dd7cddfSDavid du Colombier 		id = WIN(f->qid);
6107dd7cddfSDavid du Colombier 		n = 0;
6117dd7cddfSDavid du Colombier 		if(id > 0)
6127dd7cddfSDavid du Colombier 			d = dirtabw;
6137dd7cddfSDavid du Colombier 		else
6147dd7cddfSDavid du Colombier 			d = dirtab;
6157dd7cddfSDavid du Colombier 		d++;	/* first entry is '.' */
6169a747e4fSDavid du Colombier 		for(i=0; d->name!=nil && i<e; i+=len){
6179a747e4fSDavid du Colombier 			len = dostat(WIN(x->f->qid), d, b+n, x->count-n, clock);
6189a747e4fSDavid du Colombier 			if(len <= BIT16SZ)
6199a747e4fSDavid du Colombier 				break;
6209a747e4fSDavid du Colombier 			if(i >= o)
6219a747e4fSDavid du Colombier 				n += len;
6227dd7cddfSDavid du Colombier 			d++;
6237dd7cddfSDavid du Colombier 		}
6247dd7cddfSDavid du Colombier 		if(id == 0){
6257dd7cddfSDavid du Colombier 			qlock(&row);
6267dd7cddfSDavid du Colombier 			nids = 0;
6277dd7cddfSDavid du Colombier 			ids = nil;
6287dd7cddfSDavid du Colombier 			for(j=0; j<row.ncol; j++){
6297dd7cddfSDavid du Colombier 				c = row.col[j];
6307dd7cddfSDavid du Colombier 				for(k=0; k<c->nw; k++){
631*5d9de2d3SDavid du Colombier 					ids = erealloc(ids, (nids+1)*sizeof(int));
6327dd7cddfSDavid du Colombier 					ids[nids++] = c->w[k]->id;
6337dd7cddfSDavid du Colombier 				}
6347dd7cddfSDavid du Colombier 			}
6357dd7cddfSDavid du Colombier 			qunlock(&row);
6367dd7cddfSDavid du Colombier 			qsort(ids, nids, sizeof ids[0], idcmp);
6377dd7cddfSDavid du Colombier 			j = 0;
6387dd7cddfSDavid du Colombier 			dt.name = buf;
6399a747e4fSDavid du Colombier 			for(; j<nids && i<e; i+=len){
6407dd7cddfSDavid du Colombier 				k = ids[j];
6417dd7cddfSDavid du Colombier 				sprint(dt.name, "%d", k);
6429a747e4fSDavid du Colombier 				dt.qid = QID(k, Qdir);
6439a747e4fSDavid du Colombier 				dt.type = QTDIR;
6449a747e4fSDavid du Colombier 				dt.perm = DMDIR|0700;
6459a747e4fSDavid du Colombier 				len = dostat(k, &dt, b+n, x->count-n, clock);
6469a747e4fSDavid du Colombier 				if(len == 0)
6479a747e4fSDavid du Colombier 					break;
6489a747e4fSDavid du Colombier 				if(i >= o)
6499a747e4fSDavid du Colombier 					n += len;
6507dd7cddfSDavid du Colombier 				j++;
6517dd7cddfSDavid du Colombier 			}
6527dd7cddfSDavid du Colombier 			free(ids);
6537dd7cddfSDavid du Colombier 		}
6549a747e4fSDavid du Colombier 		t.data = (char*)b;
6557dd7cddfSDavid du Colombier 		t.count = n;
6567dd7cddfSDavid du Colombier 		respond(x, &t, nil);
6579a747e4fSDavid du Colombier 		free(b);
6587dd7cddfSDavid du Colombier 		return x;
6597dd7cddfSDavid du Colombier 	}
6607dd7cddfSDavid du Colombier 	sendp(x->c, xfidread);
6617dd7cddfSDavid du Colombier 	return nil;
6627dd7cddfSDavid du Colombier }
6637dd7cddfSDavid du Colombier 
6647dd7cddfSDavid du Colombier static
6657dd7cddfSDavid du Colombier Xfid*
fsyswrite(Xfid * x,Fid *)6667dd7cddfSDavid du Colombier fsyswrite(Xfid *x, Fid*)
6677dd7cddfSDavid du Colombier {
6687dd7cddfSDavid du Colombier 	sendp(x->c, xfidwrite);
6697dd7cddfSDavid du Colombier 	return nil;
6707dd7cddfSDavid du Colombier }
6717dd7cddfSDavid du Colombier 
6727dd7cddfSDavid du Colombier static
6737dd7cddfSDavid du Colombier Xfid*
fsysclunk(Xfid * x,Fid * f)6747dd7cddfSDavid du Colombier fsysclunk(Xfid *x, Fid *f)
6757dd7cddfSDavid du Colombier {
6767dd7cddfSDavid du Colombier 	fsysdelid(f->mntdir);
6777dd7cddfSDavid du Colombier 	sendp(x->c, xfidclose);
6787dd7cddfSDavid du Colombier 	return nil;
6797dd7cddfSDavid du Colombier }
6807dd7cddfSDavid du Colombier 
6817dd7cddfSDavid du Colombier static
6827dd7cddfSDavid du Colombier Xfid*
fsysremove(Xfid * x,Fid *)6837dd7cddfSDavid du Colombier fsysremove(Xfid *x, Fid*)
6847dd7cddfSDavid du Colombier {
6857dd7cddfSDavid du Colombier 	Fcall t;
6867dd7cddfSDavid du Colombier 
6877dd7cddfSDavid du Colombier 	return respond(x, &t, Eperm);
6887dd7cddfSDavid du Colombier }
6897dd7cddfSDavid du Colombier 
6907dd7cddfSDavid du Colombier static
6917dd7cddfSDavid du Colombier Xfid*
fsysstat(Xfid * x,Fid * f)6927dd7cddfSDavid du Colombier fsysstat(Xfid *x, Fid *f)
6937dd7cddfSDavid du Colombier {
6947dd7cddfSDavid du Colombier 	Fcall t;
6957dd7cddfSDavid du Colombier 
6969a747e4fSDavid du Colombier 	t.stat = emalloc(messagesize-IOHDRSZ);
6979a747e4fSDavid du Colombier 	t.nstat = dostat(WIN(x->f->qid), f->dir, t.stat, messagesize-IOHDRSZ, getclock());
6989a747e4fSDavid du Colombier 	x = respond(x, &t, nil);
6999a747e4fSDavid du Colombier 	free(t.stat);
7009a747e4fSDavid du Colombier 	return x;
7017dd7cddfSDavid du Colombier }
7027dd7cddfSDavid du Colombier 
7037dd7cddfSDavid du Colombier static
7047dd7cddfSDavid du Colombier Xfid*
fsyswstat(Xfid * x,Fid *)7057dd7cddfSDavid du Colombier fsyswstat(Xfid *x, Fid*)
7067dd7cddfSDavid du Colombier {
7077dd7cddfSDavid du Colombier 	Fcall t;
7087dd7cddfSDavid du Colombier 
7097dd7cddfSDavid du Colombier 	return respond(x, &t, Eperm);
7107dd7cddfSDavid du Colombier }
7117dd7cddfSDavid du Colombier 
7127dd7cddfSDavid du Colombier Fid*
newfid(int fid)7137dd7cddfSDavid du Colombier newfid(int fid)
7147dd7cddfSDavid du Colombier {
7157dd7cddfSDavid du Colombier 	Fid *f, *ff, **fh;
7167dd7cddfSDavid du Colombier 
7177dd7cddfSDavid du Colombier 	ff = nil;
7187dd7cddfSDavid du Colombier 	fh = &fids[fid&(Nhash-1)];
7197dd7cddfSDavid du Colombier 	for(f=*fh; f; f=f->next)
7207dd7cddfSDavid du Colombier 		if(f->fid == fid)
7217dd7cddfSDavid du Colombier 			return f;
7227dd7cddfSDavid du Colombier 		else if(ff==nil && f->busy==FALSE)
7237dd7cddfSDavid du Colombier 			ff = f;
7247dd7cddfSDavid du Colombier 	if(ff){
7257dd7cddfSDavid du Colombier 		ff->fid = fid;
7267dd7cddfSDavid du Colombier 		return ff;
7277dd7cddfSDavid du Colombier 	}
7287dd7cddfSDavid du Colombier 	f = emalloc(sizeof *f);
7297dd7cddfSDavid du Colombier 	f->fid = fid;
7307dd7cddfSDavid du Colombier 	f->next = *fh;
7317dd7cddfSDavid du Colombier 	*fh = f;
7327dd7cddfSDavid du Colombier 	return f;
7337dd7cddfSDavid du Colombier }
7347dd7cddfSDavid du Colombier 
7357dd7cddfSDavid du Colombier uint
getclock()7367dd7cddfSDavid du Colombier getclock()
7377dd7cddfSDavid du Colombier {
7387dd7cddfSDavid du Colombier 	char buf[32];
7397dd7cddfSDavid du Colombier 
7409a747e4fSDavid du Colombier 	buf[0] = '\0';
7419a747e4fSDavid du Colombier 	pread(clockfd, buf, sizeof buf, 0);
7427dd7cddfSDavid du Colombier 	return atoi(buf);
7437dd7cddfSDavid du Colombier }
7447dd7cddfSDavid du Colombier 
7459a747e4fSDavid du Colombier int
dostat(int id,Dirtab * dir,uchar * buf,int nbuf,uint clock)7469a747e4fSDavid du Colombier dostat(int id, Dirtab *dir, uchar *buf, int nbuf, uint clock)
7477dd7cddfSDavid du Colombier {
7487dd7cddfSDavid du Colombier 	Dir d;
7497dd7cddfSDavid du Colombier 
7507dd7cddfSDavid du Colombier 	d.qid.path = QID(id, dir->qid);
7517dd7cddfSDavid du Colombier 	d.qid.vers = 0;
7529a747e4fSDavid du Colombier 	d.qid.type = dir->type;
7537dd7cddfSDavid du Colombier 	d.mode = dir->perm;
7547dd7cddfSDavid du Colombier 	d.length = 0;	/* would be nice to do better */
7559a747e4fSDavid du Colombier 	d.name = dir->name;
7569a747e4fSDavid du Colombier 	d.uid = user;
7579a747e4fSDavid du Colombier 	d.gid = user;
7589a747e4fSDavid du Colombier 	d.muid = user;
7597dd7cddfSDavid du Colombier 	d.atime = clock;
7607dd7cddfSDavid du Colombier 	d.mtime = clock;
7619a747e4fSDavid du Colombier 	return convD2M(&d, buf, nbuf);
7627dd7cddfSDavid du Colombier }
763