xref: /plan9/sys/src/cmd/acme/fsys.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
5*9a747e4fSDavid 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*);
28*9a747e4fSDavid du Colombier static	Xfid*	fsysauth(Xfid*, Fid*);
29*9a747e4fSDavid 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,
44*9a747e4fSDavid du Colombier 	[Tversion]	= fsysversion,
45*9a747e4fSDavid 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 {
64*9a747e4fSDavid du Colombier 	{ ".",			QTDIR,	Qdir,		0500|DMDIR },
65*9a747e4fSDavid du Colombier 	{ "acme",		QTDIR,	Qacme,	0500|DMDIR },
66*9a747e4fSDavid du Colombier 	{ "cons",		QTFILE,	Qcons,	0600 },
67*9a747e4fSDavid du Colombier 	{ "consctl",	QTFILE,	Qconsctl,	0000 },
68*9a747e4fSDavid du Colombier 	{ "draw",		QTDIR,	Qdraw,	0000|DMDIR },	/* to suppress graphics progs started in acme */
69*9a747e4fSDavid du Colombier 	{ "editout",	QTFILE,	Qeditout,	0200 },
70*9a747e4fSDavid du Colombier 	{ "index",		QTFILE,	Qindex,	0400 },
71*9a747e4fSDavid du Colombier 	{ "label",		QTFILE,	Qlabel,	0600 },
72*9a747e4fSDavid 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 {
78*9a747e4fSDavid du Colombier 	{ ".",			QTDIR,		Qdir,			0500|DMDIR },
79*9a747e4fSDavid du Colombier 	{ "addr",		QTFILE,		QWaddr,		0600 },
80*9a747e4fSDavid du Colombier 	{ "body",		QTAPPEND,	QWbody,		0600|DMAPPEND },
81*9a747e4fSDavid du Colombier 	{ "ctl",		QTFILE,		QWctl,		0600 },
82*9a747e4fSDavid du Colombier 	{ "data",		QTFILE,		QWdata,		0600 },
83*9a747e4fSDavid du Colombier 	{ "editout",	QTFILE,		QWeditout,	0200 },
84*9a747e4fSDavid du Colombier 	{ "event",		QTFILE,		QWevent,		0600 },
85*9a747e4fSDavid du Colombier 	{ "rdsel",		QTFILE,		QWrdsel,		0400 },
86*9a747e4fSDavid du Colombier 	{ "wrsel",		QTFILE,		QWwrsel,		0200 },
87*9a747e4fSDavid du Colombier 	{ "tag",		QTAPPEND,	QWtag,		0600|DMAPPEND },
887dd7cddfSDavid du Colombier 	{ nil, }
897dd7cddfSDavid du Colombier };
907dd7cddfSDavid du Colombier 
917dd7cddfSDavid du Colombier typedef struct Mnt Mnt;
927dd7cddfSDavid du Colombier struct Mnt
937dd7cddfSDavid du Colombier {
947dd7cddfSDavid du Colombier 	QLock;
957dd7cddfSDavid du Colombier 	int		id;
967dd7cddfSDavid du Colombier 	Mntdir	*md;
977dd7cddfSDavid du Colombier };
987dd7cddfSDavid du Colombier 
997dd7cddfSDavid du Colombier Mnt	mnt;
1007dd7cddfSDavid du Colombier 
1017dd7cddfSDavid du Colombier Xfid*	respond(Xfid*, Fcall*, char*);
102*9a747e4fSDavid du Colombier int		dostat(int, Dirtab*, uchar*, int, uint);
1037dd7cddfSDavid du Colombier uint	getclock(void);
1047dd7cddfSDavid du Colombier 
105*9a747e4fSDavid du Colombier char	*user = "Wile E. Coyote";
1067dd7cddfSDavid du Colombier int	clockfd;
1077dd7cddfSDavid du Colombier static int closing = 0;
108*9a747e4fSDavid du Colombier int	messagesize = Maxblock+IOHDRSZ;	/* good start */
1097dd7cddfSDavid du Colombier 
1107dd7cddfSDavid du Colombier void	fsysproc(void *);
1117dd7cddfSDavid du Colombier 
1127dd7cddfSDavid du Colombier void
1137dd7cddfSDavid du Colombier fsysinit(void)
1147dd7cddfSDavid du Colombier {
1157dd7cddfSDavid du Colombier 	int p[2];
1167dd7cddfSDavid du Colombier 	int n, fd;
117*9a747e4fSDavid du Colombier 	char buf[256];
1187dd7cddfSDavid du Colombier 
1197dd7cddfSDavid du Colombier 	if(pipe(p) < 0)
1207dd7cddfSDavid du Colombier 		error("can't create pipe");
1217dd7cddfSDavid du Colombier 	cfd = p[0];
1227dd7cddfSDavid du Colombier 	sfd = p[1];
123*9a747e4fSDavid du Colombier 	fmtinstall('F', fcallfmt);
1247dd7cddfSDavid du Colombier 	clockfd = open("/dev/time", OREAD|OCEXEC);
1257dd7cddfSDavid du Colombier 	fd = open("/dev/user", OREAD);
1267dd7cddfSDavid du Colombier 	if(fd >= 0){
127*9a747e4fSDavid du Colombier 		n = read(fd, buf, sizeof buf-1);
128*9a747e4fSDavid du Colombier 		if(n > 0){
129*9a747e4fSDavid du Colombier 			buf[n] = 0;
130*9a747e4fSDavid du Colombier 			user = estrdup(buf);
131*9a747e4fSDavid du Colombier 		}
1327dd7cddfSDavid du Colombier 		close(fd);
1337dd7cddfSDavid du Colombier 	}
1347dd7cddfSDavid du Colombier 	proccreate(fsysproc, nil, STACK);
1357dd7cddfSDavid du Colombier }
1367dd7cddfSDavid du Colombier 
1377dd7cddfSDavid du Colombier void
1387dd7cddfSDavid du Colombier fsysproc(void *)
1397dd7cddfSDavid du Colombier {
1407dd7cddfSDavid du Colombier 	int n;
1417dd7cddfSDavid du Colombier 	Xfid *x;
1427dd7cddfSDavid du Colombier 	Fid *f;
1437dd7cddfSDavid du Colombier 	Fcall t;
144*9a747e4fSDavid du Colombier 	uchar *buf;
1457dd7cddfSDavid du Colombier 
1467dd7cddfSDavid du Colombier 	x = nil;
1477dd7cddfSDavid du Colombier 	for(;;){
148*9a747e4fSDavid du Colombier 		buf = emalloc(messagesize+UTFmax);	/* overflow for appending partial rune in xfidwrite */
149*9a747e4fSDavid du Colombier 		n = read9pmsg(sfd, buf, messagesize);
1507dd7cddfSDavid du Colombier 		if(n <= 0){
1517dd7cddfSDavid du Colombier 			if(closing)
1527dd7cddfSDavid du Colombier 				break;
1537dd7cddfSDavid du Colombier 			error("i/o error on server channel");
1547dd7cddfSDavid du Colombier 		}
1557dd7cddfSDavid du Colombier 		if(x == nil){
1567dd7cddfSDavid du Colombier 			sendp(cxfidalloc, nil);
1577dd7cddfSDavid du Colombier 			x = recvp(cxfidalloc);
1587dd7cddfSDavid du Colombier 		}
1597dd7cddfSDavid du Colombier 		x->buf = buf;
160*9a747e4fSDavid du Colombier 		if(convM2S(buf, n, x) != n)
1617dd7cddfSDavid du Colombier 			error("convert error in convM2S");
1627dd7cddfSDavid du Colombier 		if(DEBUG)
1637dd7cddfSDavid du Colombier 			fprint(2, "%F\n", &x->Fcall);
1647dd7cddfSDavid du Colombier 		if(fcall[x->type] == nil)
1657dd7cddfSDavid du Colombier 			x = respond(x, &t, "bad fcall type");
1667dd7cddfSDavid du Colombier 		else{
167*9a747e4fSDavid du Colombier 			if(x->type==Tversion || x->type==Tauth)
1687dd7cddfSDavid du Colombier 				f = nil;
1697dd7cddfSDavid du Colombier 			else
1707dd7cddfSDavid du Colombier 				f = newfid(x->fid);
1717dd7cddfSDavid du Colombier 			x->f = f;
1727dd7cddfSDavid du Colombier 			x  = (*fcall[x->type])(x, f);
1737dd7cddfSDavid du Colombier 		}
1747dd7cddfSDavid du Colombier 	}
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier 
1777dd7cddfSDavid du Colombier Mntdir*
1787dd7cddfSDavid du Colombier fsysaddid(Rune *dir, int ndir, Rune **incl, int nincl)
1797dd7cddfSDavid du Colombier {
1807dd7cddfSDavid du Colombier 	Mntdir *m;
1817dd7cddfSDavid du Colombier 	int id;
1827dd7cddfSDavid du Colombier 
1837dd7cddfSDavid du Colombier 	qlock(&mnt);
1847dd7cddfSDavid du Colombier 	id = ++mnt.id;
1857dd7cddfSDavid du Colombier 	m = emalloc(sizeof *m);
1867dd7cddfSDavid du Colombier 	m->id = id;
1877dd7cddfSDavid du Colombier 	m->dir =  dir;
1887dd7cddfSDavid du Colombier 	m->ref = 1;	/* one for Command, one will be incremented in attach */
1897dd7cddfSDavid du Colombier 	m->ndir = ndir;
1907dd7cddfSDavid du Colombier 	m->next = mnt.md;
1917dd7cddfSDavid du Colombier 	m->incl = incl;
1927dd7cddfSDavid du Colombier 	m->nincl = nincl;
1937dd7cddfSDavid du Colombier 	mnt.md = m;
1947dd7cddfSDavid du Colombier 	qunlock(&mnt);
1957dd7cddfSDavid du Colombier 	return m;
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier 
1987dd7cddfSDavid du Colombier void
1997dd7cddfSDavid du Colombier fsysdelid(Mntdir *idm)
2007dd7cddfSDavid du Colombier {
2017dd7cddfSDavid du Colombier 	Mntdir *m, *prev;
2027dd7cddfSDavid du Colombier 	int i;
2037dd7cddfSDavid du Colombier 	char buf[64];
2047dd7cddfSDavid du Colombier 
2057dd7cddfSDavid du Colombier 	if(idm == nil)
2067dd7cddfSDavid du Colombier 		return;
2077dd7cddfSDavid du Colombier 	qlock(&mnt);
2087dd7cddfSDavid du Colombier 	if(--idm->ref > 0){
2097dd7cddfSDavid du Colombier 		qunlock(&mnt);
2107dd7cddfSDavid du Colombier 		return;
2117dd7cddfSDavid du Colombier 	}
2127dd7cddfSDavid du Colombier 	prev = nil;
2137dd7cddfSDavid du Colombier 	for(m=mnt.md; m; m=m->next){
2147dd7cddfSDavid du Colombier 		if(m == idm){
2157dd7cddfSDavid du Colombier 			if(prev)
2167dd7cddfSDavid du Colombier 				prev->next = m->next;
2177dd7cddfSDavid du Colombier 			else
2187dd7cddfSDavid du Colombier 				mnt.md = m->next;
2197dd7cddfSDavid du Colombier 			for(i=0; i<m->nincl; i++)
2207dd7cddfSDavid du Colombier 				free(m->incl[i]);
2217dd7cddfSDavid du Colombier 			free(m->incl);
2227dd7cddfSDavid du Colombier 			free(m->dir);
2237dd7cddfSDavid du Colombier 			free(m);
2247dd7cddfSDavid du Colombier 			qunlock(&mnt);
2257dd7cddfSDavid du Colombier 			return;
2267dd7cddfSDavid du Colombier 		}
2277dd7cddfSDavid du Colombier 		prev = m;
2287dd7cddfSDavid du Colombier 	}
2297dd7cddfSDavid du Colombier 	qunlock(&mnt);
2307dd7cddfSDavid du Colombier 	sprint(buf, "fsysdelid: can't find id %d\n", idm->id);
23159cc4ca5SDavid du Colombier 	sendp(cerr, estrdup(buf));
2327dd7cddfSDavid du Colombier }
2337dd7cddfSDavid du Colombier 
2347dd7cddfSDavid du Colombier /*
235*9a747e4fSDavid du Colombier  * Called only in exec.c:/^run(), from a different FD group
2367dd7cddfSDavid du Colombier  */
2377dd7cddfSDavid du Colombier Mntdir*
2387dd7cddfSDavid du Colombier fsysmount(Rune *dir, int ndir, Rune **incl, int nincl)
2397dd7cddfSDavid du Colombier {
240*9a747e4fSDavid du Colombier 	char buf[256];
2417dd7cddfSDavid du Colombier 	Mntdir *m;
2427dd7cddfSDavid du Colombier 
2437dd7cddfSDavid du Colombier 	/* close server side so don't hang if acme is half-exited */
2447dd7cddfSDavid du Colombier 	close(sfd);
2457dd7cddfSDavid du Colombier 	m = fsysaddid(dir, ndir, incl, nincl);
2467dd7cddfSDavid du Colombier 	sprint(buf, "%d", m->id);
247*9a747e4fSDavid du Colombier 	if(mount(cfd, -1, "/mnt/acme", MREPL, buf) < 0){
2487dd7cddfSDavid du Colombier 		fsysdelid(m);
2497dd7cddfSDavid du Colombier 		return nil;
2507dd7cddfSDavid du Colombier 	}
2517dd7cddfSDavid du Colombier 	close(cfd);
2527dd7cddfSDavid du Colombier 	bind("/mnt/acme", "/mnt/wsys", MREPL);
2537dd7cddfSDavid du Colombier 	if(bind("/mnt/acme", "/dev", MBEFORE) < 0){
2547dd7cddfSDavid du Colombier 		fsysdelid(m);
2557dd7cddfSDavid du Colombier 		return nil;
2567dd7cddfSDavid du Colombier 	}
2577dd7cddfSDavid du Colombier 	return m;
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier 
2607dd7cddfSDavid du Colombier void
2617dd7cddfSDavid du Colombier fsysclose(void)
2627dd7cddfSDavid du Colombier {
2637dd7cddfSDavid du Colombier 	closing = 1;
2647dd7cddfSDavid du Colombier 	close(cfd);
2657dd7cddfSDavid du Colombier 	close(sfd);
2667dd7cddfSDavid du Colombier }
2677dd7cddfSDavid du Colombier 
2687dd7cddfSDavid du Colombier Xfid*
2697dd7cddfSDavid du Colombier respond(Xfid *x, Fcall *t, char *err)
2707dd7cddfSDavid du Colombier {
2717dd7cddfSDavid du Colombier 	int n;
2727dd7cddfSDavid du Colombier 
2737dd7cddfSDavid du Colombier 	if(err){
2747dd7cddfSDavid du Colombier 		t->type = Rerror;
275*9a747e4fSDavid du Colombier 		t->ename = err;
2767dd7cddfSDavid du Colombier 	}else
2777dd7cddfSDavid du Colombier 		t->type = x->type+1;
2787dd7cddfSDavid du Colombier 	t->fid = x->fid;
2797dd7cddfSDavid du Colombier 	t->tag = x->tag;
2807dd7cddfSDavid du Colombier 	if(x->buf == nil)
281*9a747e4fSDavid du Colombier 		x->buf = emalloc(messagesize);
282*9a747e4fSDavid du Colombier 	n = convS2M(t, x->buf, messagesize);
283*9a747e4fSDavid du Colombier 	if(n <= 0)
2847dd7cddfSDavid du Colombier 		error("convert error in convS2M");
2857dd7cddfSDavid du Colombier 	if(write(sfd, x->buf, n) != n)
2867dd7cddfSDavid du Colombier 		error("write error in respond");
287*9a747e4fSDavid du Colombier 	free(x->buf);
2887dd7cddfSDavid du Colombier 	x->buf = nil;
2897dd7cddfSDavid du Colombier 	if(DEBUG)
2907dd7cddfSDavid du Colombier 		fprint(2, "r: %F\n", t);
2917dd7cddfSDavid du Colombier 	return x;
2927dd7cddfSDavid du Colombier }
2937dd7cddfSDavid du Colombier 
2947dd7cddfSDavid du Colombier static
2957dd7cddfSDavid du Colombier Xfid*
296*9a747e4fSDavid du Colombier fsysversion(Xfid *x, Fid*)
2977dd7cddfSDavid du Colombier {
2987dd7cddfSDavid du Colombier 	Fcall t;
2997dd7cddfSDavid du Colombier 
300*9a747e4fSDavid du Colombier 	if(x->msize < 256)
301*9a747e4fSDavid du Colombier 		return respond(x, &t, "version: message size too small");
302*9a747e4fSDavid du Colombier 	messagesize = x->msize;
303*9a747e4fSDavid du Colombier 	t.msize = messagesize;
304*9a747e4fSDavid du Colombier 	if(strncmp(x->version, "9P2000", 6) != 0)
305*9a747e4fSDavid du Colombier 		return respond(x, &t, "unrecognized 9P version");
306*9a747e4fSDavid du Colombier 	t.version = "9P2000";
3077dd7cddfSDavid du Colombier 	return respond(x, &t, nil);
3087dd7cddfSDavid du Colombier }
3097dd7cddfSDavid du Colombier 
3107dd7cddfSDavid du Colombier static
3117dd7cddfSDavid du Colombier Xfid*
312*9a747e4fSDavid du Colombier fsysauth(Xfid *x, Fid*)
3137dd7cddfSDavid du Colombier {
314*9a747e4fSDavid du Colombier 	return respond(x, nil, "acme: authentication not required");
3157dd7cddfSDavid du Colombier }
3167dd7cddfSDavid du Colombier 
3177dd7cddfSDavid du Colombier static
3187dd7cddfSDavid du Colombier Xfid*
3197dd7cddfSDavid du Colombier fsysflush(Xfid *x, Fid*)
3207dd7cddfSDavid du Colombier {
3217dd7cddfSDavid du Colombier 	sendp(x->c, xfidflush);
3227dd7cddfSDavid du Colombier 	return nil;
3237dd7cddfSDavid du Colombier }
3247dd7cddfSDavid du Colombier 
3257dd7cddfSDavid du Colombier static
3267dd7cddfSDavid du Colombier Xfid*
3277dd7cddfSDavid du Colombier fsysattach(Xfid *x, Fid *f)
3287dd7cddfSDavid du Colombier {
3297dd7cddfSDavid du Colombier 	Fcall t;
3307dd7cddfSDavid du Colombier 	int id;
3317dd7cddfSDavid du Colombier 	Mntdir *m;
3327dd7cddfSDavid du Colombier 
3337dd7cddfSDavid du Colombier 	if(strcmp(x->uname, user) != 0)
3347dd7cddfSDavid du Colombier 		return respond(x, &t, Eperm);
3357dd7cddfSDavid du Colombier 	f->busy = TRUE;
3367dd7cddfSDavid du Colombier 	f->open = FALSE;
337*9a747e4fSDavid du Colombier 	f->qid.path = Qdir;
338*9a747e4fSDavid du Colombier 	f->qid.type = QTDIR;
339*9a747e4fSDavid du Colombier 	f->qid.vers = 0;
3407dd7cddfSDavid du Colombier 	f->dir = dirtab;
3417dd7cddfSDavid du Colombier 	f->nrpart = 0;
3427dd7cddfSDavid du Colombier 	f->w = nil;
3437dd7cddfSDavid du Colombier 	t.qid = f->qid;
3447dd7cddfSDavid du Colombier 	f->mntdir = nil;
3457dd7cddfSDavid du Colombier 	id = atoi(x->aname);
3467dd7cddfSDavid du Colombier 	qlock(&mnt);
3477dd7cddfSDavid du Colombier 	for(m=mnt.md; m; m=m->next)
3487dd7cddfSDavid du Colombier 		if(m->id == id){
3497dd7cddfSDavid du Colombier 			f->mntdir = m;
3507dd7cddfSDavid du Colombier 			m->ref++;
3517dd7cddfSDavid du Colombier 			break;
3527dd7cddfSDavid du Colombier 		}
3537dd7cddfSDavid du Colombier 	if(m == nil)
35459cc4ca5SDavid du Colombier 		sendp(cerr, estrdup("unknown id in attach"));
3557dd7cddfSDavid du Colombier 	qunlock(&mnt);
3567dd7cddfSDavid du Colombier 	return respond(x, &t, nil);
3577dd7cddfSDavid du Colombier }
3587dd7cddfSDavid du Colombier 
3597dd7cddfSDavid du Colombier static
3607dd7cddfSDavid du Colombier Xfid*
361*9a747e4fSDavid du Colombier fsyswalk(Xfid *x, Fid *f)
3627dd7cddfSDavid du Colombier {
3637dd7cddfSDavid du Colombier 	Fcall t;
364*9a747e4fSDavid du Colombier 	int c, i, j, id;
365*9a747e4fSDavid du Colombier 	Qid q;
366*9a747e4fSDavid du Colombier 	uchar type;
367*9a747e4fSDavid du Colombier 	ulong path;
368*9a747e4fSDavid du Colombier 	Fid *nf;
369*9a747e4fSDavid du Colombier 	Dirtab *d, *dir;
370*9a747e4fSDavid du Colombier 	Window *w;
371*9a747e4fSDavid du Colombier 	char *err;
3727dd7cddfSDavid du Colombier 
373*9a747e4fSDavid du Colombier 	nf = nil;
374*9a747e4fSDavid du Colombier 	w = nil;
3757dd7cddfSDavid du Colombier 	if(f->open)
376*9a747e4fSDavid du Colombier 		return respond(x, &t, "walk of open file");
377*9a747e4fSDavid du Colombier 	if(x->fid != x->newfid){
3787dd7cddfSDavid du Colombier 		nf = newfid(x->newfid);
379*9a747e4fSDavid du Colombier 		if(nf->busy)
380*9a747e4fSDavid du Colombier 			return respond(x, &t, "newfid already in use");
3817dd7cddfSDavid du Colombier 		nf->busy = TRUE;
3827dd7cddfSDavid du Colombier 		nf->open = FALSE;
3837dd7cddfSDavid du Colombier 		nf->mntdir = f->mntdir;
3847dd7cddfSDavid du Colombier 		if(f->mntdir)
3857dd7cddfSDavid du Colombier 			f->mntdir->ref++;
3867dd7cddfSDavid du Colombier 		nf->dir = f->dir;
3877dd7cddfSDavid du Colombier 		nf->qid = f->qid;
3887dd7cddfSDavid du Colombier 		nf->w = f->w;
3897dd7cddfSDavid du Colombier 		nf->nrpart = 0;	/* not open, so must be zero */
3907dd7cddfSDavid du Colombier 		if(nf->w)
3917dd7cddfSDavid du Colombier 			incref(nf->w);
392*9a747e4fSDavid du Colombier 		f = nf;	/* walk f */
3937dd7cddfSDavid du Colombier 	}
3947dd7cddfSDavid du Colombier 
395*9a747e4fSDavid du Colombier 	t.nwqid = 0;
396*9a747e4fSDavid du Colombier 	err = nil;
397*9a747e4fSDavid du Colombier 	dir = nil;
398*9a747e4fSDavid du Colombier 	id = WIN(f->qid);
399*9a747e4fSDavid du Colombier 	q = f->qid;
4007dd7cddfSDavid du Colombier 
401*9a747e4fSDavid du Colombier 	if(x->nwname > 0){
402*9a747e4fSDavid du Colombier 		for(i=0; i<x->nwname; i++){
403*9a747e4fSDavid du Colombier 			if((q.type & QTDIR) == 0){
404*9a747e4fSDavid du Colombier 				err = Enotdir;
405*9a747e4fSDavid du Colombier 				break;
406*9a747e4fSDavid du Colombier 			}
407*9a747e4fSDavid du Colombier 
408*9a747e4fSDavid du Colombier 			if(strcmp(x->wname[i], "..") == 0){
409*9a747e4fSDavid du Colombier 				type = QTDIR;
410*9a747e4fSDavid du Colombier 				path = Qdir;
4117dd7cddfSDavid du Colombier 				id = 0;
412*9a747e4fSDavid du Colombier 				if(w){
413*9a747e4fSDavid du Colombier 					winclose(w);
414*9a747e4fSDavid du Colombier 					w = nil;
4157dd7cddfSDavid du Colombier 				}
416*9a747e4fSDavid du Colombier     Accept:
417*9a747e4fSDavid du Colombier 				if(i == MAXWELEM){
418*9a747e4fSDavid du Colombier 					err = "name too long";
419*9a747e4fSDavid du Colombier 					break;
420*9a747e4fSDavid du Colombier 				}
421*9a747e4fSDavid du Colombier 				q.type = type;
422*9a747e4fSDavid du Colombier 				q.vers = 0;
423*9a747e4fSDavid du Colombier 				q.path = QID(id, path);
424*9a747e4fSDavid du Colombier 				t.wqid[t.nwqid++] = q;
425*9a747e4fSDavid du Colombier 				continue;
426*9a747e4fSDavid du Colombier 			}
427*9a747e4fSDavid du Colombier 
4287dd7cddfSDavid du Colombier 			/* is it a numeric name? */
429*9a747e4fSDavid du Colombier 			for(j=0; (c=x->wname[i][j]); j++)
4307dd7cddfSDavid du Colombier 				if(c<'0' || '9'<c)
4317dd7cddfSDavid du Colombier 					goto Regular;
4327dd7cddfSDavid du Colombier 			/* yes: it's a directory */
433*9a747e4fSDavid du Colombier 			if(w)	/* name has form 27/23; get out before losing w */
434*9a747e4fSDavid du Colombier 				break;
435*9a747e4fSDavid du Colombier 			id = atoi(x->wname[i]);
4367dd7cddfSDavid du Colombier 			qlock(&row);
4377dd7cddfSDavid du Colombier 			w = lookid(id, FALSE);
4387dd7cddfSDavid du Colombier 			if(w == nil){
4397dd7cddfSDavid du Colombier 				qunlock(&row);
440*9a747e4fSDavid du Colombier 				break;
4417dd7cddfSDavid du Colombier 			}
442*9a747e4fSDavid du Colombier 			incref(w);	/* we'll drop reference at end if there's an error */
443*9a747e4fSDavid du Colombier 			path = Qdir;
444*9a747e4fSDavid du Colombier 			type = QTDIR;
4457dd7cddfSDavid du Colombier 			qunlock(&row);
446*9a747e4fSDavid du Colombier 			dir = dirtabw;
447*9a747e4fSDavid du Colombier 			goto Accept;
4487dd7cddfSDavid du Colombier 
4497dd7cddfSDavid du Colombier     Regular:
450*9a747e4fSDavid du Colombier //			if(FILE(f->qid) == Qacme)	/* empty directory */
451*9a747e4fSDavid du Colombier //				break;
452*9a747e4fSDavid du Colombier 			if(strcmp(x->wname[i], "new") == 0){
453*9a747e4fSDavid du Colombier 				if(w)
454*9a747e4fSDavid du Colombier 					error("w set in walk to new");
455*9a747e4fSDavid du Colombier 				sendp(cnewwindow, nil);	/* signal newwindowthread */
456*9a747e4fSDavid du Colombier 				w = recvp(cnewwindow);	/* receive new window */
457*9a747e4fSDavid du Colombier 				incref(w);
458*9a747e4fSDavid du Colombier 				type = QTDIR;
459*9a747e4fSDavid du Colombier 				path = QID(w->id, Qdir);
460*9a747e4fSDavid du Colombier 				id = w->id;
461*9a747e4fSDavid du Colombier 				dir = dirtabw;
462*9a747e4fSDavid du Colombier 				goto Accept;
463*9a747e4fSDavid du Colombier 			}
464*9a747e4fSDavid du Colombier 
4657dd7cddfSDavid du Colombier 			if(id == 0)
4667dd7cddfSDavid du Colombier 				d = dirtab;
4677dd7cddfSDavid du Colombier 			else
4687dd7cddfSDavid du Colombier 				d = dirtabw;
4697dd7cddfSDavid du Colombier 			d++;	/* skip '.' */
4707dd7cddfSDavid du Colombier 			for(; d->name; d++)
471*9a747e4fSDavid du Colombier 				if(strcmp(x->wname[i], d->name) == 0){
472*9a747e4fSDavid du Colombier 					path = d->qid;
473*9a747e4fSDavid du Colombier 					type = d->type;
474*9a747e4fSDavid du Colombier 					dir = d;
475*9a747e4fSDavid du Colombier 					goto Accept;
4767dd7cddfSDavid du Colombier 				}
4777dd7cddfSDavid du Colombier 
478*9a747e4fSDavid du Colombier 			break;	/* file not found */
4797dd7cddfSDavid du Colombier 		}
4807dd7cddfSDavid du Colombier 
481*9a747e4fSDavid du Colombier 		if(i==0 && err == nil)
482*9a747e4fSDavid du Colombier 			err = Eexist;
483*9a747e4fSDavid du Colombier 	}
4847dd7cddfSDavid du Colombier 
485*9a747e4fSDavid du Colombier 	if(err!=nil || t.nwqid<x->nwname){
486*9a747e4fSDavid du Colombier 		if(nf){
487*9a747e4fSDavid du Colombier 			nf->busy = FALSE;
488*9a747e4fSDavid du Colombier 			fsysdelid(nf->mntdir);
489*9a747e4fSDavid du Colombier 		}
490*9a747e4fSDavid du Colombier 	}else if(t.nwqid  == x->nwname){
491*9a747e4fSDavid du Colombier 		if(w){
492*9a747e4fSDavid du Colombier 			f->w = w;
493*9a747e4fSDavid du Colombier 			w = nil;	/* don't drop the reference */
494*9a747e4fSDavid du Colombier 		}
495*9a747e4fSDavid du Colombier 		if(dir)
496*9a747e4fSDavid du Colombier 			f->dir = dir;
497*9a747e4fSDavid du Colombier 		f->qid = q;
498*9a747e4fSDavid du Colombier 	}
499*9a747e4fSDavid du Colombier 
500*9a747e4fSDavid du Colombier 	if(w != nil)
501*9a747e4fSDavid du Colombier 		winclose(w);
502*9a747e4fSDavid du Colombier 
503*9a747e4fSDavid du Colombier 	return respond(x, &t, err);
5047dd7cddfSDavid du Colombier }
5057dd7cddfSDavid du Colombier 
5067dd7cddfSDavid du Colombier static
5077dd7cddfSDavid du Colombier Xfid*
5087dd7cddfSDavid du Colombier fsysopen(Xfid *x, Fid *f)
5097dd7cddfSDavid du Colombier {
5107dd7cddfSDavid du Colombier 	Fcall t;
5117dd7cddfSDavid du Colombier 	int m;
5127dd7cddfSDavid du Colombier 
5137dd7cddfSDavid du Colombier 	/* can't truncate anything, so just disregard */
5147dd7cddfSDavid du Colombier 	x->mode &= ~(OTRUNC|OCEXEC);
5157dd7cddfSDavid du Colombier 	/* can't execute or remove anything */
5167dd7cddfSDavid du Colombier 	if(x->mode==OEXEC || (x->mode&ORCLOSE))
5177dd7cddfSDavid du Colombier 		goto Deny;
5187dd7cddfSDavid du Colombier 	switch(x->mode){
5197dd7cddfSDavid du Colombier 	default:
5207dd7cddfSDavid du Colombier 		goto Deny;
5217dd7cddfSDavid du Colombier 	case OREAD:
5227dd7cddfSDavid du Colombier 		m = 0400;
5237dd7cddfSDavid du Colombier 		break;
5247dd7cddfSDavid du Colombier 	case OWRITE:
5257dd7cddfSDavid du Colombier 		m = 0200;
5267dd7cddfSDavid du Colombier 		break;
5277dd7cddfSDavid du Colombier 	case ORDWR:
5287dd7cddfSDavid du Colombier 		m = 0600;
5297dd7cddfSDavid du Colombier 		break;
5307dd7cddfSDavid du Colombier 	}
531*9a747e4fSDavid du Colombier 	if(((f->dir->perm&~(DMDIR|DMAPPEND))&m) != m)
5327dd7cddfSDavid du Colombier 		goto Deny;
5337dd7cddfSDavid du Colombier 
5347dd7cddfSDavid du Colombier 	sendp(x->c, xfidopen);
5357dd7cddfSDavid du Colombier 	return nil;
5367dd7cddfSDavid du Colombier 
5377dd7cddfSDavid du Colombier     Deny:
5387dd7cddfSDavid du Colombier 	return respond(x, &t, Eperm);
5397dd7cddfSDavid du Colombier }
5407dd7cddfSDavid du Colombier 
5417dd7cddfSDavid du Colombier static
5427dd7cddfSDavid du Colombier Xfid*
5437dd7cddfSDavid du Colombier fsyscreate(Xfid *x, Fid*)
5447dd7cddfSDavid du Colombier {
5457dd7cddfSDavid du Colombier 	Fcall t;
5467dd7cddfSDavid du Colombier 
5477dd7cddfSDavid du Colombier 	return respond(x, &t, Eperm);
5487dd7cddfSDavid du Colombier }
5497dd7cddfSDavid du Colombier 
5507dd7cddfSDavid du Colombier static
5517dd7cddfSDavid du Colombier int
5527dd7cddfSDavid du Colombier idcmp(void *a, void *b)
5537dd7cddfSDavid du Colombier {
5547dd7cddfSDavid du Colombier 	return *(int*)a - *(int*)b;
5557dd7cddfSDavid du Colombier }
5567dd7cddfSDavid du Colombier 
5577dd7cddfSDavid du Colombier static
5587dd7cddfSDavid du Colombier Xfid*
5597dd7cddfSDavid du Colombier fsysread(Xfid *x, Fid *f)
5607dd7cddfSDavid du Colombier {
5617dd7cddfSDavid du Colombier 	Fcall t;
562*9a747e4fSDavid du Colombier 	uchar *b;
5637dd7cddfSDavid du Colombier 	int i, id, n, o, e, j, k, *ids, nids;
5647dd7cddfSDavid du Colombier 	Dirtab *d, dt;
5657dd7cddfSDavid du Colombier 	Column *c;
566*9a747e4fSDavid du Colombier 	uint clock, len;
5677dd7cddfSDavid du Colombier 	char buf[16];
5687dd7cddfSDavid du Colombier 
569*9a747e4fSDavid du Colombier 	if(f->qid.type & QTDIR){
5707dd7cddfSDavid du Colombier 		if(FILE(f->qid) == Qacme){	/* empty dir */
5717dd7cddfSDavid du Colombier 			t.data = nil;
5727dd7cddfSDavid du Colombier 			t.count = 0;
5737dd7cddfSDavid du Colombier 			respond(x, &t, nil);
5747dd7cddfSDavid du Colombier 			return x;
5757dd7cddfSDavid du Colombier 		}
5767dd7cddfSDavid du Colombier 		o = x->offset;
5777dd7cddfSDavid du Colombier 		e = x->offset+x->count;
5787dd7cddfSDavid du Colombier 		clock = getclock();
579*9a747e4fSDavid du Colombier 		b = emalloc(messagesize);
5807dd7cddfSDavid du Colombier 		id = WIN(f->qid);
5817dd7cddfSDavid du Colombier 		n = 0;
5827dd7cddfSDavid du Colombier 		if(id > 0)
5837dd7cddfSDavid du Colombier 			d = dirtabw;
5847dd7cddfSDavid du Colombier 		else
5857dd7cddfSDavid du Colombier 			d = dirtab;
5867dd7cddfSDavid du Colombier 		d++;	/* first entry is '.' */
587*9a747e4fSDavid du Colombier 		for(i=0; d->name!=nil && i<e; i+=len){
588*9a747e4fSDavid du Colombier 			len = dostat(WIN(x->f->qid), d, b+n, x->count-n, clock);
589*9a747e4fSDavid du Colombier 			if(len <= BIT16SZ)
590*9a747e4fSDavid du Colombier 				break;
591*9a747e4fSDavid du Colombier 			if(i >= o)
592*9a747e4fSDavid du Colombier 				n += len;
5937dd7cddfSDavid du Colombier 			d++;
5947dd7cddfSDavid du Colombier 		}
5957dd7cddfSDavid du Colombier 		if(id == 0){
5967dd7cddfSDavid du Colombier 			qlock(&row);
5977dd7cddfSDavid du Colombier 			nids = 0;
5987dd7cddfSDavid du Colombier 			ids = nil;
5997dd7cddfSDavid du Colombier 			for(j=0; j<row.ncol; j++){
6007dd7cddfSDavid du Colombier 				c = row.col[j];
6017dd7cddfSDavid du Colombier 				for(k=0; k<c->nw; k++){
6027dd7cddfSDavid du Colombier 					ids = realloc(ids, (nids+1)*sizeof(int));
6037dd7cddfSDavid du Colombier 					ids[nids++] = c->w[k]->id;
6047dd7cddfSDavid du Colombier 				}
6057dd7cddfSDavid du Colombier 			}
6067dd7cddfSDavid du Colombier 			qunlock(&row);
6077dd7cddfSDavid du Colombier 			qsort(ids, nids, sizeof ids[0], idcmp);
6087dd7cddfSDavid du Colombier 			j = 0;
6097dd7cddfSDavid du Colombier 			dt.name = buf;
610*9a747e4fSDavid du Colombier 			for(; j<nids && i<e; i+=len){
6117dd7cddfSDavid du Colombier 				k = ids[j];
6127dd7cddfSDavid du Colombier 				sprint(dt.name, "%d", k);
613*9a747e4fSDavid du Colombier 				dt.qid = QID(k, Qdir);
614*9a747e4fSDavid du Colombier 				dt.type = QTDIR;
615*9a747e4fSDavid du Colombier 				dt.perm = DMDIR|0700;
616*9a747e4fSDavid du Colombier 				len = dostat(k, &dt, b+n, x->count-n, clock);
617*9a747e4fSDavid du Colombier 				if(len == 0)
618*9a747e4fSDavid du Colombier 					break;
619*9a747e4fSDavid du Colombier 				if(i >= o)
620*9a747e4fSDavid du Colombier 					n += len;
6217dd7cddfSDavid du Colombier 				j++;
6227dd7cddfSDavid du Colombier 			}
6237dd7cddfSDavid du Colombier 			free(ids);
6247dd7cddfSDavid du Colombier 		}
625*9a747e4fSDavid du Colombier 		t.data = (char*)b;
6267dd7cddfSDavid du Colombier 		t.count = n;
6277dd7cddfSDavid du Colombier 		respond(x, &t, nil);
628*9a747e4fSDavid du Colombier 		free(b);
6297dd7cddfSDavid du Colombier 		return x;
6307dd7cddfSDavid du Colombier 	}
6317dd7cddfSDavid du Colombier 	sendp(x->c, xfidread);
6327dd7cddfSDavid du Colombier 	return nil;
6337dd7cddfSDavid du Colombier }
6347dd7cddfSDavid du Colombier 
6357dd7cddfSDavid du Colombier static
6367dd7cddfSDavid du Colombier Xfid*
6377dd7cddfSDavid du Colombier fsyswrite(Xfid *x, Fid*)
6387dd7cddfSDavid du Colombier {
6397dd7cddfSDavid du Colombier 	sendp(x->c, xfidwrite);
6407dd7cddfSDavid du Colombier 	return nil;
6417dd7cddfSDavid du Colombier }
6427dd7cddfSDavid du Colombier 
6437dd7cddfSDavid du Colombier static
6447dd7cddfSDavid du Colombier Xfid*
6457dd7cddfSDavid du Colombier fsysclunk(Xfid *x, Fid *f)
6467dd7cddfSDavid du Colombier {
6477dd7cddfSDavid du Colombier 	fsysdelid(f->mntdir);
6487dd7cddfSDavid du Colombier 	sendp(x->c, xfidclose);
6497dd7cddfSDavid du Colombier 	return nil;
6507dd7cddfSDavid du Colombier }
6517dd7cddfSDavid du Colombier 
6527dd7cddfSDavid du Colombier static
6537dd7cddfSDavid du Colombier Xfid*
6547dd7cddfSDavid du Colombier fsysremove(Xfid *x, Fid*)
6557dd7cddfSDavid du Colombier {
6567dd7cddfSDavid du Colombier 	Fcall t;
6577dd7cddfSDavid du Colombier 
6587dd7cddfSDavid du Colombier 	return respond(x, &t, Eperm);
6597dd7cddfSDavid du Colombier }
6607dd7cddfSDavid du Colombier 
6617dd7cddfSDavid du Colombier static
6627dd7cddfSDavid du Colombier Xfid*
6637dd7cddfSDavid du Colombier fsysstat(Xfid *x, Fid *f)
6647dd7cddfSDavid du Colombier {
6657dd7cddfSDavid du Colombier 	Fcall t;
6667dd7cddfSDavid du Colombier 
667*9a747e4fSDavid du Colombier 	t.stat = emalloc(messagesize-IOHDRSZ);
668*9a747e4fSDavid du Colombier 	t.nstat = dostat(WIN(x->f->qid), f->dir, t.stat, messagesize-IOHDRSZ, getclock());
669*9a747e4fSDavid du Colombier 	x = respond(x, &t, nil);
670*9a747e4fSDavid du Colombier 	free(t.stat);
671*9a747e4fSDavid du Colombier 	return x;
6727dd7cddfSDavid du Colombier }
6737dd7cddfSDavid du Colombier 
6747dd7cddfSDavid du Colombier static
6757dd7cddfSDavid du Colombier Xfid*
6767dd7cddfSDavid du Colombier fsyswstat(Xfid *x, Fid*)
6777dd7cddfSDavid du Colombier {
6787dd7cddfSDavid du Colombier 	Fcall t;
6797dd7cddfSDavid du Colombier 
6807dd7cddfSDavid du Colombier 	return respond(x, &t, Eperm);
6817dd7cddfSDavid du Colombier }
6827dd7cddfSDavid du Colombier 
6837dd7cddfSDavid du Colombier Fid*
6847dd7cddfSDavid du Colombier newfid(int fid)
6857dd7cddfSDavid du Colombier {
6867dd7cddfSDavid du Colombier 	Fid *f, *ff, **fh;
6877dd7cddfSDavid du Colombier 
6887dd7cddfSDavid du Colombier 	ff = nil;
6897dd7cddfSDavid du Colombier 	fh = &fids[fid&(Nhash-1)];
6907dd7cddfSDavid du Colombier 	for(f=*fh; f; f=f->next)
6917dd7cddfSDavid du Colombier 		if(f->fid == fid)
6927dd7cddfSDavid du Colombier 			return f;
6937dd7cddfSDavid du Colombier 		else if(ff==nil && f->busy==FALSE)
6947dd7cddfSDavid du Colombier 			ff = f;
6957dd7cddfSDavid du Colombier 	if(ff){
6967dd7cddfSDavid du Colombier 		ff->fid = fid;
6977dd7cddfSDavid du Colombier 		return ff;
6987dd7cddfSDavid du Colombier 	}
6997dd7cddfSDavid du Colombier 	f = emalloc(sizeof *f);
7007dd7cddfSDavid du Colombier 	f->fid = fid;
7017dd7cddfSDavid du Colombier 	f->next = *fh;
7027dd7cddfSDavid du Colombier 	*fh = f;
7037dd7cddfSDavid du Colombier 	return f;
7047dd7cddfSDavid du Colombier }
7057dd7cddfSDavid du Colombier 
7067dd7cddfSDavid du Colombier uint
7077dd7cddfSDavid du Colombier getclock()
7087dd7cddfSDavid du Colombier {
7097dd7cddfSDavid du Colombier 	char buf[32];
7107dd7cddfSDavid du Colombier 
711*9a747e4fSDavid du Colombier 	buf[0] = '\0';
712*9a747e4fSDavid du Colombier 	pread(clockfd, buf, sizeof buf, 0);
7137dd7cddfSDavid du Colombier 	return atoi(buf);
7147dd7cddfSDavid du Colombier }
7157dd7cddfSDavid du Colombier 
716*9a747e4fSDavid du Colombier int
717*9a747e4fSDavid du Colombier dostat(int id, Dirtab *dir, uchar *buf, int nbuf, uint clock)
7187dd7cddfSDavid du Colombier {
7197dd7cddfSDavid du Colombier 	Dir d;
7207dd7cddfSDavid du Colombier 
7217dd7cddfSDavid du Colombier 	d.qid.path = QID(id, dir->qid);
7227dd7cddfSDavid du Colombier 	d.qid.vers = 0;
723*9a747e4fSDavid du Colombier 	d.qid.type = dir->type;
7247dd7cddfSDavid du Colombier 	d.mode = dir->perm;
7257dd7cddfSDavid du Colombier 	d.length = 0;	/* would be nice to do better */
726*9a747e4fSDavid du Colombier 	d.name = dir->name;
727*9a747e4fSDavid du Colombier 	d.uid = user;
728*9a747e4fSDavid du Colombier 	d.gid = user;
729*9a747e4fSDavid du Colombier 	d.muid = user;
7307dd7cddfSDavid du Colombier 	d.atime = clock;
7317dd7cddfSDavid du Colombier 	d.mtime = clock;
732*9a747e4fSDavid du Colombier 	return convD2M(&d, buf, nbuf);
7337dd7cddfSDavid du Colombier }
734