xref: /plan9-contrib/sys/src/9k/port/sysfile.c (revision 9ef1f84b659abcb917c5c090acbce0772e494f21)
1*9ef1f84bSDavid du Colombier #include	"u.h"
2*9ef1f84bSDavid du Colombier #include	"../port/lib.h"
3*9ef1f84bSDavid du Colombier #include	"mem.h"
4*9ef1f84bSDavid du Colombier #include	"dat.h"
5*9ef1f84bSDavid du Colombier #include	"fns.h"
6*9ef1f84bSDavid du Colombier #include	"../port/error.h"
7*9ef1f84bSDavid du Colombier 
8*9ef1f84bSDavid du Colombier /*
9*9ef1f84bSDavid du Colombier  * The sys*() routines needn't poperror() as they return directly to syscall().
10*9ef1f84bSDavid du Colombier  */
11*9ef1f84bSDavid du Colombier 
12*9ef1f84bSDavid du Colombier static void
unlockfgrp(Fgrp * f)13*9ef1f84bSDavid du Colombier unlockfgrp(Fgrp *f)
14*9ef1f84bSDavid du Colombier {
15*9ef1f84bSDavid du Colombier 	int ex;
16*9ef1f84bSDavid du Colombier 
17*9ef1f84bSDavid du Colombier 	ex = f->exceed;
18*9ef1f84bSDavid du Colombier 	f->exceed = 0;
19*9ef1f84bSDavid du Colombier 	unlock(f);
20*9ef1f84bSDavid du Colombier 	if(ex)
21*9ef1f84bSDavid du Colombier 		pprint("warning: process exceeds %d file descriptors\n", ex);
22*9ef1f84bSDavid du Colombier }
23*9ef1f84bSDavid du Colombier 
24*9ef1f84bSDavid du Colombier static int
growfd(Fgrp * f,int fd)25*9ef1f84bSDavid du Colombier growfd(Fgrp *f, int fd)	/* fd is always >= 0 */
26*9ef1f84bSDavid du Colombier {
27*9ef1f84bSDavid du Colombier 	Chan **newfd, **oldfd;
28*9ef1f84bSDavid du Colombier 
29*9ef1f84bSDavid du Colombier 	if(fd < f->nfd)
30*9ef1f84bSDavid du Colombier 		return 0;
31*9ef1f84bSDavid du Colombier 	if(fd >= f->nfd+DELTAFD)
32*9ef1f84bSDavid du Colombier 		return -1;	/* out of range */
33*9ef1f84bSDavid du Colombier 	/*
34*9ef1f84bSDavid du Colombier 	 * Unbounded allocation is unwise.
35*9ef1f84bSDavid du Colombier 	 */
36*9ef1f84bSDavid du Colombier 	if(f->nfd >= 5000){
37*9ef1f84bSDavid du Colombier     Exhausted:
38*9ef1f84bSDavid du Colombier 		print("no free file descriptors\n");
39*9ef1f84bSDavid du Colombier 		return -1;
40*9ef1f84bSDavid du Colombier 	}
41*9ef1f84bSDavid du Colombier 	newfd = malloc((f->nfd+DELTAFD)*sizeof(Chan*));
42*9ef1f84bSDavid du Colombier 	if(newfd == 0)
43*9ef1f84bSDavid du Colombier 		goto Exhausted;
44*9ef1f84bSDavid du Colombier 	oldfd = f->fd;
45*9ef1f84bSDavid du Colombier 	memmove(newfd, oldfd, f->nfd*sizeof(Chan*));
46*9ef1f84bSDavid du Colombier 	f->fd = newfd;
47*9ef1f84bSDavid du Colombier 	free(oldfd);
48*9ef1f84bSDavid du Colombier 	f->nfd += DELTAFD;
49*9ef1f84bSDavid du Colombier 	if(fd > f->maxfd){
50*9ef1f84bSDavid du Colombier 		if(fd/100 > f->maxfd/100)
51*9ef1f84bSDavid du Colombier 			f->exceed = (fd/100)*100;
52*9ef1f84bSDavid du Colombier 		f->maxfd = fd;
53*9ef1f84bSDavid du Colombier 	}
54*9ef1f84bSDavid du Colombier 	return 1;
55*9ef1f84bSDavid du Colombier }
56*9ef1f84bSDavid du Colombier 
57*9ef1f84bSDavid du Colombier /*
58*9ef1f84bSDavid du Colombier  *  this assumes that the fgrp is locked
59*9ef1f84bSDavid du Colombier  */
60*9ef1f84bSDavid du Colombier static int
findfreefd(Fgrp * f,int start)61*9ef1f84bSDavid du Colombier findfreefd(Fgrp *f, int start)
62*9ef1f84bSDavid du Colombier {
63*9ef1f84bSDavid du Colombier 	int fd;
64*9ef1f84bSDavid du Colombier 
65*9ef1f84bSDavid du Colombier 	for(fd=start; fd<f->nfd; fd++)
66*9ef1f84bSDavid du Colombier 		if(f->fd[fd] == 0)
67*9ef1f84bSDavid du Colombier 			break;
68*9ef1f84bSDavid du Colombier 	if(fd >= f->nfd && growfd(f, fd) < 0)
69*9ef1f84bSDavid du Colombier 		return -1;
70*9ef1f84bSDavid du Colombier 	return fd;
71*9ef1f84bSDavid du Colombier }
72*9ef1f84bSDavid du Colombier 
73*9ef1f84bSDavid du Colombier int
newfd(Chan * c)74*9ef1f84bSDavid du Colombier newfd(Chan *c)
75*9ef1f84bSDavid du Colombier {
76*9ef1f84bSDavid du Colombier 	int fd;
77*9ef1f84bSDavid du Colombier 	Fgrp *f;
78*9ef1f84bSDavid du Colombier 
79*9ef1f84bSDavid du Colombier 	f = up->fgrp;
80*9ef1f84bSDavid du Colombier 	lock(f);
81*9ef1f84bSDavid du Colombier 	fd = findfreefd(f, 0);
82*9ef1f84bSDavid du Colombier 	if(fd < 0){
83*9ef1f84bSDavid du Colombier 		unlockfgrp(f);
84*9ef1f84bSDavid du Colombier 		return -1;
85*9ef1f84bSDavid du Colombier 	}
86*9ef1f84bSDavid du Colombier 	if(fd > f->maxfd)
87*9ef1f84bSDavid du Colombier 		f->maxfd = fd;
88*9ef1f84bSDavid du Colombier 	f->fd[fd] = c;
89*9ef1f84bSDavid du Colombier 	unlockfgrp(f);
90*9ef1f84bSDavid du Colombier 	return fd;
91*9ef1f84bSDavid du Colombier }
92*9ef1f84bSDavid du Colombier 
93*9ef1f84bSDavid du Colombier static int
newfd2(int fd[2],Chan * c[2])94*9ef1f84bSDavid du Colombier newfd2(int fd[2], Chan *c[2])
95*9ef1f84bSDavid du Colombier {
96*9ef1f84bSDavid du Colombier 	Fgrp *f;
97*9ef1f84bSDavid du Colombier 
98*9ef1f84bSDavid du Colombier 	f = up->fgrp;
99*9ef1f84bSDavid du Colombier 	lock(f);
100*9ef1f84bSDavid du Colombier 	fd[0] = findfreefd(f, 0);
101*9ef1f84bSDavid du Colombier 	if(fd[0] < 0){
102*9ef1f84bSDavid du Colombier 		unlockfgrp(f);
103*9ef1f84bSDavid du Colombier 		return -1;
104*9ef1f84bSDavid du Colombier 	}
105*9ef1f84bSDavid du Colombier 	fd[1] = findfreefd(f, fd[0]+1);
106*9ef1f84bSDavid du Colombier 	if(fd[1] < 0){
107*9ef1f84bSDavid du Colombier 		unlockfgrp(f);
108*9ef1f84bSDavid du Colombier 		return -1;
109*9ef1f84bSDavid du Colombier 	}
110*9ef1f84bSDavid du Colombier 	if(fd[1] > f->maxfd)
111*9ef1f84bSDavid du Colombier 		f->maxfd = fd[1];
112*9ef1f84bSDavid du Colombier 	f->fd[fd[0]] = c[0];
113*9ef1f84bSDavid du Colombier 	f->fd[fd[1]] = c[1];
114*9ef1f84bSDavid du Colombier 	unlockfgrp(f);
115*9ef1f84bSDavid du Colombier 
116*9ef1f84bSDavid du Colombier 	return 0;
117*9ef1f84bSDavid du Colombier }
118*9ef1f84bSDavid du Colombier 
119*9ef1f84bSDavid du Colombier Chan*
fdtochan(int fd,int mode,int chkmnt,int iref)120*9ef1f84bSDavid du Colombier fdtochan(int fd, int mode, int chkmnt, int iref)
121*9ef1f84bSDavid du Colombier {
122*9ef1f84bSDavid du Colombier 	Chan *c;
123*9ef1f84bSDavid du Colombier 	Fgrp *f;
124*9ef1f84bSDavid du Colombier 
125*9ef1f84bSDavid du Colombier 	c = nil;
126*9ef1f84bSDavid du Colombier 	f = up->fgrp;
127*9ef1f84bSDavid du Colombier 
128*9ef1f84bSDavid du Colombier 	lock(f);
129*9ef1f84bSDavid du Colombier 	if(fd<0 || f->nfd<=fd || (c = f->fd[fd])==0) {
130*9ef1f84bSDavid du Colombier 		unlock(f);
131*9ef1f84bSDavid du Colombier 		error(Ebadfd);
132*9ef1f84bSDavid du Colombier 	}
133*9ef1f84bSDavid du Colombier 	if(iref)
134*9ef1f84bSDavid du Colombier 		incref(c);
135*9ef1f84bSDavid du Colombier 	unlock(f);
136*9ef1f84bSDavid du Colombier 
137*9ef1f84bSDavid du Colombier 	if(chkmnt && (c->flag&CMSG)) {
138*9ef1f84bSDavid du Colombier 		if(iref)
139*9ef1f84bSDavid du Colombier 			cclose(c);
140*9ef1f84bSDavid du Colombier 		error(Ebadusefd);
141*9ef1f84bSDavid du Colombier 	}
142*9ef1f84bSDavid du Colombier 
143*9ef1f84bSDavid du Colombier 	if(mode<0 || c->mode==ORDWR)
144*9ef1f84bSDavid du Colombier 		return c;
145*9ef1f84bSDavid du Colombier 
146*9ef1f84bSDavid du Colombier 	if((mode&OTRUNC) && c->mode==OREAD) {
147*9ef1f84bSDavid du Colombier 		if(iref)
148*9ef1f84bSDavid du Colombier 			cclose(c);
149*9ef1f84bSDavid du Colombier 		error(Ebadusefd);
150*9ef1f84bSDavid du Colombier 	}
151*9ef1f84bSDavid du Colombier 
152*9ef1f84bSDavid du Colombier 	if((mode&~OTRUNC) != c->mode) {
153*9ef1f84bSDavid du Colombier 		if(iref)
154*9ef1f84bSDavid du Colombier 			cclose(c);
155*9ef1f84bSDavid du Colombier 		error(Ebadusefd);
156*9ef1f84bSDavid du Colombier 	}
157*9ef1f84bSDavid du Colombier 
158*9ef1f84bSDavid du Colombier 	return c;
159*9ef1f84bSDavid du Colombier }
160*9ef1f84bSDavid du Colombier 
161*9ef1f84bSDavid du Colombier int
openmode(int omode)162*9ef1f84bSDavid du Colombier openmode(int omode)
163*9ef1f84bSDavid du Colombier {
164*9ef1f84bSDavid du Colombier 	omode &= ~(OTRUNC|OCEXEC|ORCLOSE);
165*9ef1f84bSDavid du Colombier 	if(omode > OEXEC)
166*9ef1f84bSDavid du Colombier 		error(Ebadarg);
167*9ef1f84bSDavid du Colombier 	if(omode == OEXEC)
168*9ef1f84bSDavid du Colombier 		return OREAD;
169*9ef1f84bSDavid du Colombier 	return omode;
170*9ef1f84bSDavid du Colombier }
171*9ef1f84bSDavid du Colombier 
172*9ef1f84bSDavid du Colombier void
sysfd2path(Ar0 * ar0,va_list list)173*9ef1f84bSDavid du Colombier sysfd2path(Ar0* ar0, va_list list)
174*9ef1f84bSDavid du Colombier {
175*9ef1f84bSDavid du Colombier 	Chan *c;
176*9ef1f84bSDavid du Colombier 	char *buf;
177*9ef1f84bSDavid du Colombier 	int fd;
178*9ef1f84bSDavid du Colombier 	usize nbuf;
179*9ef1f84bSDavid du Colombier 
180*9ef1f84bSDavid du Colombier 	/*
181*9ef1f84bSDavid du Colombier 	 * int fd2path(int fd, char* buf, int nbuf);
182*9ef1f84bSDavid du Colombier 	 * should be
183*9ef1f84bSDavid du Colombier 	 * int fd2path(int fd, char* buf, usize nbuf);
184*9ef1f84bSDavid du Colombier 	 */
185*9ef1f84bSDavid du Colombier 	fd = va_arg(list, int);
186*9ef1f84bSDavid du Colombier 	buf = va_arg(list, char*);
187*9ef1f84bSDavid du Colombier 	nbuf = va_arg(list, usize);
188*9ef1f84bSDavid du Colombier 	buf = validaddr(buf, nbuf, 1);
189*9ef1f84bSDavid du Colombier 
190*9ef1f84bSDavid du Colombier 	c = fdtochan(fd, -1, 0, 1);
191*9ef1f84bSDavid du Colombier 	snprint(buf, nbuf, "%s", chanpath(c));
192*9ef1f84bSDavid du Colombier 	cclose(c);
193*9ef1f84bSDavid du Colombier 
194*9ef1f84bSDavid du Colombier 	ar0->i = 0;
195*9ef1f84bSDavid du Colombier }
196*9ef1f84bSDavid du Colombier 
197*9ef1f84bSDavid du Colombier void
syspipe(Ar0 * ar0,va_list list)198*9ef1f84bSDavid du Colombier syspipe(Ar0* ar0, va_list list)
199*9ef1f84bSDavid du Colombier {
200*9ef1f84bSDavid du Colombier 	int *a, fd[2];
201*9ef1f84bSDavid du Colombier 	Chan *c[2];
202*9ef1f84bSDavid du Colombier 	static char *datastr[] = {"data", "data1"};
203*9ef1f84bSDavid du Colombier 
204*9ef1f84bSDavid du Colombier 	/*
205*9ef1f84bSDavid du Colombier 	 * int pipe(int fd[2]);
206*9ef1f84bSDavid du Colombier 	 */
207*9ef1f84bSDavid du Colombier 	a = va_arg(list, int*);
208*9ef1f84bSDavid du Colombier 	a = validaddr(a, sizeof(fd), 1);
209*9ef1f84bSDavid du Colombier 	evenaddr(PTR2UINT(a));
210*9ef1f84bSDavid du Colombier 
211*9ef1f84bSDavid du Colombier 	c[0] = namec("#|", Atodir, 0, 0);
212*9ef1f84bSDavid du Colombier 	c[1] = nil;
213*9ef1f84bSDavid du Colombier 	fd[0] = -1;
214*9ef1f84bSDavid du Colombier 	fd[1] = -1;
215*9ef1f84bSDavid du Colombier 
216*9ef1f84bSDavid du Colombier 	if(waserror()){
217*9ef1f84bSDavid du Colombier 		cclose(c[0]);
218*9ef1f84bSDavid du Colombier 		if(c[1])
219*9ef1f84bSDavid du Colombier 			cclose(c[1]);
220*9ef1f84bSDavid du Colombier 		nexterror();
221*9ef1f84bSDavid du Colombier 	}
222*9ef1f84bSDavid du Colombier 	c[1] = cclone(c[0]);
223*9ef1f84bSDavid du Colombier 	if(walk(&c[0], datastr+0, 1, 1, nil) < 0)
224*9ef1f84bSDavid du Colombier 		error(Egreg);
225*9ef1f84bSDavid du Colombier 	if(walk(&c[1], datastr+1, 1, 1, nil) < 0)
226*9ef1f84bSDavid du Colombier 		error(Egreg);
227*9ef1f84bSDavid du Colombier 	c[0] = c[0]->dev->open(c[0], ORDWR);
228*9ef1f84bSDavid du Colombier 	c[1] = c[1]->dev->open(c[1], ORDWR);
229*9ef1f84bSDavid du Colombier 	if(newfd2(fd, c) < 0)
230*9ef1f84bSDavid du Colombier 		error(Enofd);
231*9ef1f84bSDavid du Colombier 	poperror();
232*9ef1f84bSDavid du Colombier 
233*9ef1f84bSDavid du Colombier 	a[0] = fd[0];
234*9ef1f84bSDavid du Colombier 	a[1] = fd[1];
235*9ef1f84bSDavid du Colombier 
236*9ef1f84bSDavid du Colombier 	ar0->i = 0;
237*9ef1f84bSDavid du Colombier }
238*9ef1f84bSDavid du Colombier 
239*9ef1f84bSDavid du Colombier void
sysdup(Ar0 * ar0,va_list list)240*9ef1f84bSDavid du Colombier sysdup(Ar0* ar0, va_list list)
241*9ef1f84bSDavid du Colombier {
242*9ef1f84bSDavid du Colombier 	int nfd, ofd;
243*9ef1f84bSDavid du Colombier 	Chan *nc, *oc;
244*9ef1f84bSDavid du Colombier 	Fgrp *f;
245*9ef1f84bSDavid du Colombier 
246*9ef1f84bSDavid du Colombier 	/*
247*9ef1f84bSDavid du Colombier 	 * int dup(int oldfd, int newfd);
248*9ef1f84bSDavid du Colombier 	 *
249*9ef1f84bSDavid du Colombier 	 * Close after dup'ing, so date > #d/1 works
250*9ef1f84bSDavid du Colombier 	 */
251*9ef1f84bSDavid du Colombier 	ofd = va_arg(list, int);
252*9ef1f84bSDavid du Colombier 	oc = fdtochan(ofd, -1, 0, 1);
253*9ef1f84bSDavid du Colombier 	nfd = va_arg(list, int);
254*9ef1f84bSDavid du Colombier 
255*9ef1f84bSDavid du Colombier 	if(nfd != -1){
256*9ef1f84bSDavid du Colombier 		f = up->fgrp;
257*9ef1f84bSDavid du Colombier 		lock(f);
258*9ef1f84bSDavid du Colombier 		if(nfd < 0 || growfd(f, nfd) < 0) {
259*9ef1f84bSDavid du Colombier 			unlockfgrp(f);
260*9ef1f84bSDavid du Colombier 			cclose(oc);
261*9ef1f84bSDavid du Colombier 			error(Ebadfd);
262*9ef1f84bSDavid du Colombier 		}
263*9ef1f84bSDavid du Colombier 		if(nfd > f->maxfd)
264*9ef1f84bSDavid du Colombier 			f->maxfd = nfd;
265*9ef1f84bSDavid du Colombier 
266*9ef1f84bSDavid du Colombier 		nc = f->fd[nfd];
267*9ef1f84bSDavid du Colombier 		f->fd[nfd] = oc;
268*9ef1f84bSDavid du Colombier 		unlockfgrp(f);
269*9ef1f84bSDavid du Colombier 		if(nc != nil)
270*9ef1f84bSDavid du Colombier 			cclose(nc);
271*9ef1f84bSDavid du Colombier 	}else{
272*9ef1f84bSDavid du Colombier 		if(waserror()) {
273*9ef1f84bSDavid du Colombier 			cclose(oc);
274*9ef1f84bSDavid du Colombier 			nexterror();
275*9ef1f84bSDavid du Colombier 		}
276*9ef1f84bSDavid du Colombier 		nfd = newfd(oc);
277*9ef1f84bSDavid du Colombier 		if(nfd < 0)
278*9ef1f84bSDavid du Colombier 			error(Enofd);
279*9ef1f84bSDavid du Colombier 		poperror();
280*9ef1f84bSDavid du Colombier 	}
281*9ef1f84bSDavid du Colombier 
282*9ef1f84bSDavid du Colombier 	ar0->i = nfd;
283*9ef1f84bSDavid du Colombier }
284*9ef1f84bSDavid du Colombier 
285*9ef1f84bSDavid du Colombier void
sysopen(Ar0 * ar0,va_list list)286*9ef1f84bSDavid du Colombier sysopen(Ar0* ar0, va_list list)
287*9ef1f84bSDavid du Colombier {
288*9ef1f84bSDavid du Colombier 	char *aname;
289*9ef1f84bSDavid du Colombier 	int fd, omode;
290*9ef1f84bSDavid du Colombier 	Chan *c;
291*9ef1f84bSDavid du Colombier 
292*9ef1f84bSDavid du Colombier 	/*
293*9ef1f84bSDavid du Colombier 	 * int open(char* file, int omode);
294*9ef1f84bSDavid du Colombier 	 */
295*9ef1f84bSDavid du Colombier 	aname = va_arg(list, char*);
296*9ef1f84bSDavid du Colombier 	omode = va_arg(list, int);
297*9ef1f84bSDavid du Colombier 	openmode(omode);	/* error check only */
298*9ef1f84bSDavid du Colombier 
299*9ef1f84bSDavid du Colombier 	c = nil;
300*9ef1f84bSDavid du Colombier 	if(waserror()){
301*9ef1f84bSDavid du Colombier 		if(c != nil)
302*9ef1f84bSDavid du Colombier 			cclose(c);
303*9ef1f84bSDavid du Colombier 		nexterror();
304*9ef1f84bSDavid du Colombier 	}
305*9ef1f84bSDavid du Colombier 	aname = validaddr(aname, 1, 0);
306*9ef1f84bSDavid du Colombier 	c = namec(aname, Aopen, omode, 0);
307*9ef1f84bSDavid du Colombier 	fd = newfd(c);
308*9ef1f84bSDavid du Colombier 	if(fd < 0)
309*9ef1f84bSDavid du Colombier 		error(Enofd);
310*9ef1f84bSDavid du Colombier 	poperror();
311*9ef1f84bSDavid du Colombier 
312*9ef1f84bSDavid du Colombier 	ar0->i = fd;
313*9ef1f84bSDavid du Colombier }
314*9ef1f84bSDavid du Colombier 
315*9ef1f84bSDavid du Colombier void
fdclose(int fd,int flag)316*9ef1f84bSDavid du Colombier fdclose(int fd, int flag)
317*9ef1f84bSDavid du Colombier {
318*9ef1f84bSDavid du Colombier 	int i;
319*9ef1f84bSDavid du Colombier 	Chan *c;
320*9ef1f84bSDavid du Colombier 	Fgrp *f;
321*9ef1f84bSDavid du Colombier 
322*9ef1f84bSDavid du Colombier 	f = up->fgrp;
323*9ef1f84bSDavid du Colombier 	lock(f);
324*9ef1f84bSDavid du Colombier 	c = f->fd[fd];
325*9ef1f84bSDavid du Colombier 	if(c == nil){
326*9ef1f84bSDavid du Colombier 		/* can happen for users with shared fd tables */
327*9ef1f84bSDavid du Colombier 		unlock(f);
328*9ef1f84bSDavid du Colombier 		return;
329*9ef1f84bSDavid du Colombier 	}
330*9ef1f84bSDavid du Colombier 	if(flag){
331*9ef1f84bSDavid du Colombier 		if(c == nil || !(c->flag&flag)){
332*9ef1f84bSDavid du Colombier 			unlock(f);
333*9ef1f84bSDavid du Colombier 			return;
334*9ef1f84bSDavid du Colombier 		}
335*9ef1f84bSDavid du Colombier 	}
336*9ef1f84bSDavid du Colombier 	f->fd[fd] = nil;
337*9ef1f84bSDavid du Colombier 	if(fd == f->maxfd)
338*9ef1f84bSDavid du Colombier 		for(i = fd; --i >= 0 && f->fd[i] == 0; )
339*9ef1f84bSDavid du Colombier 			f->maxfd = i;
340*9ef1f84bSDavid du Colombier 
341*9ef1f84bSDavid du Colombier 	unlock(f);
342*9ef1f84bSDavid du Colombier 	cclose(c);
343*9ef1f84bSDavid du Colombier }
344*9ef1f84bSDavid du Colombier 
345*9ef1f84bSDavid du Colombier void
sysclose(Ar0 * ar0,va_list list)346*9ef1f84bSDavid du Colombier sysclose(Ar0* ar0, va_list list)
347*9ef1f84bSDavid du Colombier {
348*9ef1f84bSDavid du Colombier 	int fd;
349*9ef1f84bSDavid du Colombier 
350*9ef1f84bSDavid du Colombier 	/*
351*9ef1f84bSDavid du Colombier 	 * int close(int fd);
352*9ef1f84bSDavid du Colombier 	 */
353*9ef1f84bSDavid du Colombier 	fd = va_arg(list, int);
354*9ef1f84bSDavid du Colombier 
355*9ef1f84bSDavid du Colombier 	fdtochan(fd, -1, 0, 0);
356*9ef1f84bSDavid du Colombier 	fdclose(fd, 0);
357*9ef1f84bSDavid du Colombier 
358*9ef1f84bSDavid du Colombier 	ar0->i = 0;
359*9ef1f84bSDavid du Colombier }
360*9ef1f84bSDavid du Colombier 
361*9ef1f84bSDavid du Colombier static long
unionread(Chan * c,void * va,long n)362*9ef1f84bSDavid du Colombier unionread(Chan *c, void *va, long n)
363*9ef1f84bSDavid du Colombier {
364*9ef1f84bSDavid du Colombier 	int i;
365*9ef1f84bSDavid du Colombier 	long nr;
366*9ef1f84bSDavid du Colombier 	Mhead *mh;
367*9ef1f84bSDavid du Colombier 	Mount *mount;
368*9ef1f84bSDavid du Colombier 
369*9ef1f84bSDavid du Colombier 	qlock(&c->umqlock);
370*9ef1f84bSDavid du Colombier 	mh = c->umh;
371*9ef1f84bSDavid du Colombier 	rlock(&mh->lock);
372*9ef1f84bSDavid du Colombier 	mount = mh->mount;
373*9ef1f84bSDavid du Colombier 	/* bring mount in sync with c->uri and c->umc */
374*9ef1f84bSDavid du Colombier 	for(i = 0; mount != nil && i < c->uri; i++)
375*9ef1f84bSDavid du Colombier 		mount = mount->next;
376*9ef1f84bSDavid du Colombier 
377*9ef1f84bSDavid du Colombier 	nr = 0;
378*9ef1f84bSDavid du Colombier 	while(mount != nil){
379*9ef1f84bSDavid du Colombier 		/* Error causes component of union to be skipped */
380*9ef1f84bSDavid du Colombier 		if(mount->to && !waserror()){
381*9ef1f84bSDavid du Colombier 			if(c->umc == nil){
382*9ef1f84bSDavid du Colombier 				c->umc = cclone(mount->to);
383*9ef1f84bSDavid du Colombier 				c->umc = c->umc->dev->open(c->umc, OREAD);
384*9ef1f84bSDavid du Colombier 			}
385*9ef1f84bSDavid du Colombier 
386*9ef1f84bSDavid du Colombier 			nr = c->umc->dev->read(c->umc, va, n, c->umc->offset);
387*9ef1f84bSDavid du Colombier 			c->umc->offset += nr;
388*9ef1f84bSDavid du Colombier 			poperror();
389*9ef1f84bSDavid du Colombier 		}
390*9ef1f84bSDavid du Colombier 		if(nr > 0)
391*9ef1f84bSDavid du Colombier 			break;
392*9ef1f84bSDavid du Colombier 
393*9ef1f84bSDavid du Colombier 		/* Advance to next element */
394*9ef1f84bSDavid du Colombier 		c->uri++;
395*9ef1f84bSDavid du Colombier 		if(c->umc){
396*9ef1f84bSDavid du Colombier 			cclose(c->umc);
397*9ef1f84bSDavid du Colombier 			c->umc = nil;
398*9ef1f84bSDavid du Colombier 		}
399*9ef1f84bSDavid du Colombier 		mount = mount->next;
400*9ef1f84bSDavid du Colombier 	}
401*9ef1f84bSDavid du Colombier 	runlock(&mh->lock);
402*9ef1f84bSDavid du Colombier 	qunlock(&c->umqlock);
403*9ef1f84bSDavid du Colombier 	return nr;
404*9ef1f84bSDavid du Colombier }
405*9ef1f84bSDavid du Colombier 
406*9ef1f84bSDavid du Colombier static void
unionrewind(Chan * c)407*9ef1f84bSDavid du Colombier unionrewind(Chan *c)
408*9ef1f84bSDavid du Colombier {
409*9ef1f84bSDavid du Colombier 	qlock(&c->umqlock);
410*9ef1f84bSDavid du Colombier 	c->uri = 0;
411*9ef1f84bSDavid du Colombier 	if(c->umc){
412*9ef1f84bSDavid du Colombier 		cclose(c->umc);
413*9ef1f84bSDavid du Colombier 		c->umc = nil;
414*9ef1f84bSDavid du Colombier 	}
415*9ef1f84bSDavid du Colombier 	qunlock(&c->umqlock);
416*9ef1f84bSDavid du Colombier }
417*9ef1f84bSDavid du Colombier 
418*9ef1f84bSDavid du Colombier static usize
dirfixed(uchar * p,uchar * e,Dir * d)419*9ef1f84bSDavid du Colombier dirfixed(uchar *p, uchar *e, Dir *d)
420*9ef1f84bSDavid du Colombier {
421*9ef1f84bSDavid du Colombier 	int len;
422*9ef1f84bSDavid du Colombier 	Dev *dev;
423*9ef1f84bSDavid du Colombier 
424*9ef1f84bSDavid du Colombier 	len = GBIT16(p)+BIT16SZ;
425*9ef1f84bSDavid du Colombier 	if(p + len > e)
426*9ef1f84bSDavid du Colombier 		return 0;
427*9ef1f84bSDavid du Colombier 
428*9ef1f84bSDavid du Colombier 	p += BIT16SZ;	/* ignore size */
429*9ef1f84bSDavid du Colombier 	dev = devtabget(GBIT16(p), 1);			//XDYNX
430*9ef1f84bSDavid du Colombier 	if(dev != nil){
431*9ef1f84bSDavid du Colombier 		d->type = dev->dc;
432*9ef1f84bSDavid du Colombier 		//devtabdecr(dev);
433*9ef1f84bSDavid du Colombier 	}
434*9ef1f84bSDavid du Colombier 	else
435*9ef1f84bSDavid du Colombier 		d->type = -1;
436*9ef1f84bSDavid du Colombier 	p += BIT16SZ;
437*9ef1f84bSDavid du Colombier 	d->dev = GBIT32(p);
438*9ef1f84bSDavid du Colombier 	p += BIT32SZ;
439*9ef1f84bSDavid du Colombier 	d->qid.type = GBIT8(p);
440*9ef1f84bSDavid du Colombier 	p += BIT8SZ;
441*9ef1f84bSDavid du Colombier 	d->qid.vers = GBIT32(p);
442*9ef1f84bSDavid du Colombier 	p += BIT32SZ;
443*9ef1f84bSDavid du Colombier 	d->qid.path = GBIT64(p);
444*9ef1f84bSDavid du Colombier 	p += BIT64SZ;
445*9ef1f84bSDavid du Colombier 	d->mode = GBIT32(p);
446*9ef1f84bSDavid du Colombier 	p += BIT32SZ;
447*9ef1f84bSDavid du Colombier 	d->atime = GBIT32(p);
448*9ef1f84bSDavid du Colombier 	p += BIT32SZ;
449*9ef1f84bSDavid du Colombier 	d->mtime = GBIT32(p);
450*9ef1f84bSDavid du Colombier 	p += BIT32SZ;
451*9ef1f84bSDavid du Colombier 	d->length = GBIT64(p);
452*9ef1f84bSDavid du Colombier 
453*9ef1f84bSDavid du Colombier 	return len;
454*9ef1f84bSDavid du Colombier }
455*9ef1f84bSDavid du Colombier 
456*9ef1f84bSDavid du Colombier static char*
dirname(uchar * p,usize * n)457*9ef1f84bSDavid du Colombier dirname(uchar *p, usize *n)
458*9ef1f84bSDavid du Colombier {
459*9ef1f84bSDavid du Colombier 	p += BIT16SZ+BIT16SZ+BIT32SZ+BIT8SZ+BIT32SZ+BIT64SZ
460*9ef1f84bSDavid du Colombier 		+ BIT32SZ+BIT32SZ+BIT32SZ+BIT64SZ;
461*9ef1f84bSDavid du Colombier 	*n = GBIT16(p);
462*9ef1f84bSDavid du Colombier 
463*9ef1f84bSDavid du Colombier 	return (char*)p+BIT16SZ;
464*9ef1f84bSDavid du Colombier }
465*9ef1f84bSDavid du Colombier 
466*9ef1f84bSDavid du Colombier static usize
dirsetname(char * name,usize len,uchar * p,usize n,usize maxn)467*9ef1f84bSDavid du Colombier dirsetname(char *name, usize len, uchar *p, usize n, usize maxn)
468*9ef1f84bSDavid du Colombier {
469*9ef1f84bSDavid du Colombier 	char *oname;
470*9ef1f84bSDavid du Colombier 	usize nn, olen;
471*9ef1f84bSDavid du Colombier 
472*9ef1f84bSDavid du Colombier 	if(n == BIT16SZ)
473*9ef1f84bSDavid du Colombier 		return BIT16SZ;
474*9ef1f84bSDavid du Colombier 
475*9ef1f84bSDavid du Colombier 	oname = dirname(p, &olen);
476*9ef1f84bSDavid du Colombier 
477*9ef1f84bSDavid du Colombier 	nn = n+len-olen;
478*9ef1f84bSDavid du Colombier 	PBIT16(p, nn-BIT16SZ);
479*9ef1f84bSDavid du Colombier 	if(nn > maxn)
480*9ef1f84bSDavid du Colombier 		return BIT16SZ;
481*9ef1f84bSDavid du Colombier 
482*9ef1f84bSDavid du Colombier 	if(len != olen)
483*9ef1f84bSDavid du Colombier 		memmove(oname+len, oname+olen, p+n-(uchar*)(oname+olen));
484*9ef1f84bSDavid du Colombier 	PBIT16((uchar*)(oname-2), len);
485*9ef1f84bSDavid du Colombier 	memmove(oname, name, len);
486*9ef1f84bSDavid du Colombier 
487*9ef1f84bSDavid du Colombier 	return nn;
488*9ef1f84bSDavid du Colombier }
489*9ef1f84bSDavid du Colombier 
490*9ef1f84bSDavid du Colombier /*
491*9ef1f84bSDavid du Colombier  * Mountfix might have caused the fixed results of the directory read
492*9ef1f84bSDavid du Colombier  * to overflow the buffer.  Catch the overflow in c->dirrock.
493*9ef1f84bSDavid du Colombier  */
494*9ef1f84bSDavid du Colombier static void
mountrock(Chan * c,uchar * p,uchar ** pe)495*9ef1f84bSDavid du Colombier mountrock(Chan *c, uchar *p, uchar **pe)
496*9ef1f84bSDavid du Colombier {
497*9ef1f84bSDavid du Colombier 	uchar *e, *r;
498*9ef1f84bSDavid du Colombier 	int len, n;
499*9ef1f84bSDavid du Colombier 
500*9ef1f84bSDavid du Colombier 	e = *pe;
501*9ef1f84bSDavid du Colombier 
502*9ef1f84bSDavid du Colombier 	/* find last directory entry */
503*9ef1f84bSDavid du Colombier 	for(;;){
504*9ef1f84bSDavid du Colombier 		len = BIT16SZ+GBIT16(p);
505*9ef1f84bSDavid du Colombier 		if(p+len >= e)
506*9ef1f84bSDavid du Colombier 			break;
507*9ef1f84bSDavid du Colombier 		p += len;
508*9ef1f84bSDavid du Colombier 	}
509*9ef1f84bSDavid du Colombier 
510*9ef1f84bSDavid du Colombier 	/* save it away */
511*9ef1f84bSDavid du Colombier 	qlock(&c->rockqlock);
512*9ef1f84bSDavid du Colombier 	if(c->nrock+len > c->mrock){
513*9ef1f84bSDavid du Colombier 		n = ROUNDUP(c->nrock+len, 1024);
514*9ef1f84bSDavid du Colombier 		r = smalloc(n);
515*9ef1f84bSDavid du Colombier 		memmove(r, c->dirrock, c->nrock);
516*9ef1f84bSDavid du Colombier 		free(c->dirrock);
517*9ef1f84bSDavid du Colombier 		c->dirrock = r;
518*9ef1f84bSDavid du Colombier 		c->mrock = n;
519*9ef1f84bSDavid du Colombier 	}
520*9ef1f84bSDavid du Colombier 	memmove(c->dirrock+c->nrock, p, len);
521*9ef1f84bSDavid du Colombier 	c->nrock += len;
522*9ef1f84bSDavid du Colombier 	qunlock(&c->rockqlock);
523*9ef1f84bSDavid du Colombier 
524*9ef1f84bSDavid du Colombier 	/* drop it */
525*9ef1f84bSDavid du Colombier 	*pe = p;
526*9ef1f84bSDavid du Colombier }
527*9ef1f84bSDavid du Colombier 
528*9ef1f84bSDavid du Colombier /*
529*9ef1f84bSDavid du Colombier  * Satisfy a directory read with the results saved in c->dirrock.
530*9ef1f84bSDavid du Colombier  */
531*9ef1f84bSDavid du Colombier static int
mountrockread(Chan * c,uchar * op,long n,long * nn)532*9ef1f84bSDavid du Colombier mountrockread(Chan *c, uchar *op, long n, long *nn)
533*9ef1f84bSDavid du Colombier {
534*9ef1f84bSDavid du Colombier 	long dirlen;
535*9ef1f84bSDavid du Colombier 	uchar *rp, *erp, *ep, *p;
536*9ef1f84bSDavid du Colombier 
537*9ef1f84bSDavid du Colombier 	/* common case */
538*9ef1f84bSDavid du Colombier 	if(c->nrock == 0)
539*9ef1f84bSDavid du Colombier 		return 0;
540*9ef1f84bSDavid du Colombier 
541*9ef1f84bSDavid du Colombier 	/* copy out what we can */
542*9ef1f84bSDavid du Colombier 	qlock(&c->rockqlock);
543*9ef1f84bSDavid du Colombier 	rp = c->dirrock;
544*9ef1f84bSDavid du Colombier 	erp = rp+c->nrock;
545*9ef1f84bSDavid du Colombier 	p = op;
546*9ef1f84bSDavid du Colombier 	ep = p+n;
547*9ef1f84bSDavid du Colombier 	while(rp+BIT16SZ <= erp){
548*9ef1f84bSDavid du Colombier 		dirlen = BIT16SZ+GBIT16(rp);
549*9ef1f84bSDavid du Colombier 		if(p+dirlen > ep)
550*9ef1f84bSDavid du Colombier 			break;
551*9ef1f84bSDavid du Colombier 		memmove(p, rp, dirlen);
552*9ef1f84bSDavid du Colombier 		p += dirlen;
553*9ef1f84bSDavid du Colombier 		rp += dirlen;
554*9ef1f84bSDavid du Colombier 	}
555*9ef1f84bSDavid du Colombier 
556*9ef1f84bSDavid du Colombier 	if(p == op){
557*9ef1f84bSDavid du Colombier 		qunlock(&c->rockqlock);
558*9ef1f84bSDavid du Colombier 		return 0;
559*9ef1f84bSDavid du Colombier 	}
560*9ef1f84bSDavid du Colombier 
561*9ef1f84bSDavid du Colombier 	/* shift the rest */
562*9ef1f84bSDavid du Colombier 	if(rp != erp)
563*9ef1f84bSDavid du Colombier 		memmove(c->dirrock, rp, erp-rp);
564*9ef1f84bSDavid du Colombier 	c->nrock = erp - rp;
565*9ef1f84bSDavid du Colombier 
566*9ef1f84bSDavid du Colombier 	*nn = p - op;
567*9ef1f84bSDavid du Colombier 	qunlock(&c->rockqlock);
568*9ef1f84bSDavid du Colombier 	return 1;
569*9ef1f84bSDavid du Colombier }
570*9ef1f84bSDavid du Colombier 
571*9ef1f84bSDavid du Colombier static void
mountrewind(Chan * c)572*9ef1f84bSDavid du Colombier mountrewind(Chan *c)
573*9ef1f84bSDavid du Colombier {
574*9ef1f84bSDavid du Colombier 	c->nrock = 0;
575*9ef1f84bSDavid du Colombier }
576*9ef1f84bSDavid du Colombier 
577*9ef1f84bSDavid du Colombier /*
578*9ef1f84bSDavid du Colombier  * Rewrite the results of a directory read to reflect current
579*9ef1f84bSDavid du Colombier  * name space bindings and mounts.  Specifically, replace
580*9ef1f84bSDavid du Colombier  * directory entries for bind and mount points with the results
581*9ef1f84bSDavid du Colombier  * of statting what is mounted there.  Except leave the old names.
582*9ef1f84bSDavid du Colombier  */
583*9ef1f84bSDavid du Colombier static long
mountfix(Chan * c,uchar * op,long n,long maxn)584*9ef1f84bSDavid du Colombier mountfix(Chan *c, uchar *op, long n, long maxn)
585*9ef1f84bSDavid du Colombier {
586*9ef1f84bSDavid du Colombier 	char *name;
587*9ef1f84bSDavid du Colombier 	int nbuf;
588*9ef1f84bSDavid du Colombier 	Chan *nc;
589*9ef1f84bSDavid du Colombier 	Mhead *mh;
590*9ef1f84bSDavid du Colombier 	Mount *mount;
591*9ef1f84bSDavid du Colombier 	usize dirlen, nname, r, rest;
592*9ef1f84bSDavid du Colombier 	long l;
593*9ef1f84bSDavid du Colombier 	uchar *buf, *e, *p;
594*9ef1f84bSDavid du Colombier 	Dir d;
595*9ef1f84bSDavid du Colombier 
596*9ef1f84bSDavid du Colombier 	p = op;
597*9ef1f84bSDavid du Colombier 	buf = nil;
598*9ef1f84bSDavid du Colombier 	nbuf = 0;
599*9ef1f84bSDavid du Colombier 	for(e=&p[n]; p+BIT16SZ<e; p+=dirlen){
600*9ef1f84bSDavid du Colombier 		dirlen = dirfixed(p, e, &d);
601*9ef1f84bSDavid du Colombier 		if(dirlen == 0)
602*9ef1f84bSDavid du Colombier 			break;
603*9ef1f84bSDavid du Colombier 		nc = nil;
604*9ef1f84bSDavid du Colombier 		mh = nil;
605*9ef1f84bSDavid du Colombier 		if(findmount(&nc, &mh, d.type, d.dev, d.qid)){
606*9ef1f84bSDavid du Colombier 			/*
607*9ef1f84bSDavid du Colombier 			 * If it's a union directory and the original is
608*9ef1f84bSDavid du Colombier 			 * in the union, don't rewrite anything.
609*9ef1f84bSDavid du Colombier 			 */
610*9ef1f84bSDavid du Colombier 			for(mount=mh->mount; mount; mount=mount->next)
611*9ef1f84bSDavid du Colombier 				if(eqchanddq(mount->to, d.type, d.dev, d.qid, 1))
612*9ef1f84bSDavid du Colombier 					goto Norewrite;
613*9ef1f84bSDavid du Colombier 
614*9ef1f84bSDavid du Colombier 			name = dirname(p, &nname);
615*9ef1f84bSDavid du Colombier 			/*
616*9ef1f84bSDavid du Colombier 			 * Do the stat but fix the name.  If it fails,
617*9ef1f84bSDavid du Colombier 			 * leave old entry.
618*9ef1f84bSDavid du Colombier 			 * BUG: If it fails because there isn't room for
619*9ef1f84bSDavid du Colombier 			 * the entry, what can we do?  Nothing, really.
620*9ef1f84bSDavid du Colombier 			 * Might as well skip it.
621*9ef1f84bSDavid du Colombier 			 */
622*9ef1f84bSDavid du Colombier 			if(buf == nil){
623*9ef1f84bSDavid du Colombier 				buf = smalloc(4096);
624*9ef1f84bSDavid du Colombier 				nbuf = 4096;
625*9ef1f84bSDavid du Colombier 			}
626*9ef1f84bSDavid du Colombier 			if(waserror())
627*9ef1f84bSDavid du Colombier 				goto Norewrite;
628*9ef1f84bSDavid du Colombier 			l = nc->dev->stat(nc, buf, nbuf);
629*9ef1f84bSDavid du Colombier 			r = dirsetname(name, nname, buf, l, nbuf);
630*9ef1f84bSDavid du Colombier 			if(r == BIT16SZ)
631*9ef1f84bSDavid du Colombier 				error("dirsetname");
632*9ef1f84bSDavid du Colombier 			poperror();
633*9ef1f84bSDavid du Colombier 
634*9ef1f84bSDavid du Colombier 			/*
635*9ef1f84bSDavid du Colombier 			 * Shift data in buffer to accomodate new entry,
636*9ef1f84bSDavid du Colombier 			 * possibly overflowing into rock.
637*9ef1f84bSDavid du Colombier 			 */
638*9ef1f84bSDavid du Colombier 			rest = e - (p+dirlen);
639*9ef1f84bSDavid du Colombier 			if(r > dirlen){
640*9ef1f84bSDavid du Colombier 				while(p+r+rest > op+maxn){
641*9ef1f84bSDavid du Colombier 					mountrock(c, p, &e);
642*9ef1f84bSDavid du Colombier 					if(e == p){
643*9ef1f84bSDavid du Colombier 						dirlen = 0;
644*9ef1f84bSDavid du Colombier 						goto Norewrite;
645*9ef1f84bSDavid du Colombier 					}
646*9ef1f84bSDavid du Colombier 					rest = e - (p+dirlen);
647*9ef1f84bSDavid du Colombier 				}
648*9ef1f84bSDavid du Colombier 			}
649*9ef1f84bSDavid du Colombier 			if(r != dirlen){
650*9ef1f84bSDavid du Colombier 				memmove(p+r, p+dirlen, rest);
651*9ef1f84bSDavid du Colombier 				dirlen = r;
652*9ef1f84bSDavid du Colombier 				e = p+dirlen+rest;
653*9ef1f84bSDavid du Colombier 			}
654*9ef1f84bSDavid du Colombier 
655*9ef1f84bSDavid du Colombier 			/*
656*9ef1f84bSDavid du Colombier 			 * Rewrite directory entry.
657*9ef1f84bSDavid du Colombier 			 */
658*9ef1f84bSDavid du Colombier 			memmove(p, buf, r);
659*9ef1f84bSDavid du Colombier 
660*9ef1f84bSDavid du Colombier 		    Norewrite:
661*9ef1f84bSDavid du Colombier 			cclose(nc);
662*9ef1f84bSDavid du Colombier 			putmhead(mh);
663*9ef1f84bSDavid du Colombier 		}
664*9ef1f84bSDavid du Colombier 	}
665*9ef1f84bSDavid du Colombier 	if(buf)
666*9ef1f84bSDavid du Colombier 		free(buf);
667*9ef1f84bSDavid du Colombier 
668*9ef1f84bSDavid du Colombier 	if(p != e)
669*9ef1f84bSDavid du Colombier 		error("oops in mountfix");
670*9ef1f84bSDavid du Colombier 
671*9ef1f84bSDavid du Colombier 	return e-op;
672*9ef1f84bSDavid du Colombier }
673*9ef1f84bSDavid du Colombier 
674*9ef1f84bSDavid du Colombier static long
read(va_list list,int ispread)675*9ef1f84bSDavid du Colombier read(va_list list, int ispread)
676*9ef1f84bSDavid du Colombier {
677*9ef1f84bSDavid du Colombier 	int fd;
678*9ef1f84bSDavid du Colombier 	long n, nn, nnn;
679*9ef1f84bSDavid du Colombier 	void *p;
680*9ef1f84bSDavid du Colombier 	Chan *c;
681*9ef1f84bSDavid du Colombier 	vlong off;
682*9ef1f84bSDavid du Colombier 
683*9ef1f84bSDavid du Colombier 	fd = va_arg(list, int);
684*9ef1f84bSDavid du Colombier 	p = va_arg(list, void*);
685*9ef1f84bSDavid du Colombier 	n = va_arg(list, long);
686*9ef1f84bSDavid du Colombier 	p = validaddr(p, n, 1);
687*9ef1f84bSDavid du Colombier 
688*9ef1f84bSDavid du Colombier 	c = fdtochan(fd, OREAD, 1, 1);
689*9ef1f84bSDavid du Colombier 
690*9ef1f84bSDavid du Colombier 	if(waserror()){
691*9ef1f84bSDavid du Colombier 		cclose(c);
692*9ef1f84bSDavid du Colombier 		nexterror();
693*9ef1f84bSDavid du Colombier 	}
694*9ef1f84bSDavid du Colombier 
695*9ef1f84bSDavid du Colombier 	/*
696*9ef1f84bSDavid du Colombier 	 * The offset is passed through on directories, normally.
697*9ef1f84bSDavid du Colombier 	 * Sysseek complains, but pread is used by servers like exportfs,
698*9ef1f84bSDavid du Colombier 	 * that shouldn't need to worry about this issue.
699*9ef1f84bSDavid du Colombier 	 *
700*9ef1f84bSDavid du Colombier 	 * Notice that c->devoffset is the offset that c's dev is seeing.
701*9ef1f84bSDavid du Colombier 	 * The number of bytes read on this fd (c->offset) may be different
702*9ef1f84bSDavid du Colombier 	 * due to rewritings in mountfix.
703*9ef1f84bSDavid du Colombier 	 */
704*9ef1f84bSDavid du Colombier 	if(ispread){
705*9ef1f84bSDavid du Colombier 		off = va_arg(list, vlong);
706*9ef1f84bSDavid du Colombier 		if(off == ~0LL){	/* use and maintain channel's offset */
707*9ef1f84bSDavid du Colombier 			off = c->offset;
708*9ef1f84bSDavid du Colombier 			ispread = 0;
709*9ef1f84bSDavid du Colombier 		}
710*9ef1f84bSDavid du Colombier 	}
711*9ef1f84bSDavid du Colombier 	else
712*9ef1f84bSDavid du Colombier 		off = c->offset;
713*9ef1f84bSDavid du Colombier 
714*9ef1f84bSDavid du Colombier 	if(c->qid.type & QTDIR){
715*9ef1f84bSDavid du Colombier 		/*
716*9ef1f84bSDavid du Colombier 		 * Directory read:
717*9ef1f84bSDavid du Colombier 		 * rewind to the beginning of the file if necessary;
718*9ef1f84bSDavid du Colombier 		 * try to fill the buffer via mountrockread;
719*9ef1f84bSDavid du Colombier 		 * clear ispread to always maintain the Chan offset.
720*9ef1f84bSDavid du Colombier 		 */
721*9ef1f84bSDavid du Colombier 		if(off == 0LL){
722*9ef1f84bSDavid du Colombier 			if(!ispread){
723*9ef1f84bSDavid du Colombier 				c->offset = 0;
724*9ef1f84bSDavid du Colombier 				c->devoffset = 0;
725*9ef1f84bSDavid du Colombier 			}
726*9ef1f84bSDavid du Colombier 			mountrewind(c);
727*9ef1f84bSDavid du Colombier 			unionrewind(c);
728*9ef1f84bSDavid du Colombier 		}
729*9ef1f84bSDavid du Colombier 
730*9ef1f84bSDavid du Colombier 		if(!mountrockread(c, p, n, &nn)){
731*9ef1f84bSDavid du Colombier 			if(c->umh)
732*9ef1f84bSDavid du Colombier 				nn = unionread(c, p, n);
733*9ef1f84bSDavid du Colombier 			else{
734*9ef1f84bSDavid du Colombier 				if(off != c->offset)
735*9ef1f84bSDavid du Colombier 					error(Eisdir);
736*9ef1f84bSDavid du Colombier 				nn = c->dev->read(c, p, n, c->devoffset);
737*9ef1f84bSDavid du Colombier 			}
738*9ef1f84bSDavid du Colombier 		}
739*9ef1f84bSDavid du Colombier 		nnn = mountfix(c, p, nn, n);
740*9ef1f84bSDavid du Colombier 
741*9ef1f84bSDavid du Colombier 		ispread = 0;
742*9ef1f84bSDavid du Colombier 	}
743*9ef1f84bSDavid du Colombier 	else
744*9ef1f84bSDavid du Colombier 		nnn = nn = c->dev->read(c, p, n, off);
745*9ef1f84bSDavid du Colombier 
746*9ef1f84bSDavid du Colombier 	if(!ispread){
747*9ef1f84bSDavid du Colombier 		lock(c);
748*9ef1f84bSDavid du Colombier 		c->devoffset += nn;
749*9ef1f84bSDavid du Colombier 		c->offset += nnn;
750*9ef1f84bSDavid du Colombier 		unlock(c);
751*9ef1f84bSDavid du Colombier 	}
752*9ef1f84bSDavid du Colombier 
753*9ef1f84bSDavid du Colombier 	poperror();
754*9ef1f84bSDavid du Colombier 	cclose(c);
755*9ef1f84bSDavid du Colombier 
756*9ef1f84bSDavid du Colombier 	return nnn;
757*9ef1f84bSDavid du Colombier }
758*9ef1f84bSDavid du Colombier 
759*9ef1f84bSDavid du Colombier void
sys_read(Ar0 * ar0,va_list list)760*9ef1f84bSDavid du Colombier sys_read(Ar0* ar0, va_list list)
761*9ef1f84bSDavid du Colombier {
762*9ef1f84bSDavid du Colombier 	/*
763*9ef1f84bSDavid du Colombier 	 * long read(int fd, void* buf, long nbytes);
764*9ef1f84bSDavid du Colombier 	 */
765*9ef1f84bSDavid du Colombier 	ar0->l = read(list, 0);
766*9ef1f84bSDavid du Colombier }
767*9ef1f84bSDavid du Colombier 
768*9ef1f84bSDavid du Colombier void
syspread(Ar0 * ar0,va_list list)769*9ef1f84bSDavid du Colombier syspread(Ar0* ar0, va_list list)
770*9ef1f84bSDavid du Colombier {
771*9ef1f84bSDavid du Colombier 	/*
772*9ef1f84bSDavid du Colombier 	 * long pread(int fd, void* buf, long nbytes, vlong offset);
773*9ef1f84bSDavid du Colombier 	 */
774*9ef1f84bSDavid du Colombier 	ar0->l = read(list, 1);
775*9ef1f84bSDavid du Colombier }
776*9ef1f84bSDavid du Colombier 
777*9ef1f84bSDavid du Colombier static long
write(va_list list,int ispwrite)778*9ef1f84bSDavid du Colombier write(va_list list, int ispwrite)
779*9ef1f84bSDavid du Colombier {
780*9ef1f84bSDavid du Colombier 	int fd;
781*9ef1f84bSDavid du Colombier 	long n, r;
782*9ef1f84bSDavid du Colombier 	void *p;
783*9ef1f84bSDavid du Colombier 	Chan *c;
784*9ef1f84bSDavid du Colombier 	vlong off;
785*9ef1f84bSDavid du Colombier 
786*9ef1f84bSDavid du Colombier 	fd = va_arg(list, int);
787*9ef1f84bSDavid du Colombier 	p = va_arg(list, void*);
788*9ef1f84bSDavid du Colombier 	r = n = va_arg(list, long);
789*9ef1f84bSDavid du Colombier 
790*9ef1f84bSDavid du Colombier 	p = validaddr(p, n, 0);
791*9ef1f84bSDavid du Colombier 	n = 0;
792*9ef1f84bSDavid du Colombier 	c = fdtochan(fd, OWRITE, 1, 1);
793*9ef1f84bSDavid du Colombier 	if(waserror()) {
794*9ef1f84bSDavid du Colombier 		if(!ispwrite){
795*9ef1f84bSDavid du Colombier 			lock(c);
796*9ef1f84bSDavid du Colombier 			c->offset -= n;
797*9ef1f84bSDavid du Colombier 			unlock(c);
798*9ef1f84bSDavid du Colombier 		}
799*9ef1f84bSDavid du Colombier 		cclose(c);
800*9ef1f84bSDavid du Colombier 		nexterror();
801*9ef1f84bSDavid du Colombier 	}
802*9ef1f84bSDavid du Colombier 
803*9ef1f84bSDavid du Colombier 	if(c->qid.type & QTDIR)
804*9ef1f84bSDavid du Colombier 		error(Eisdir);
805*9ef1f84bSDavid du Colombier 
806*9ef1f84bSDavid du Colombier 	n = r;
807*9ef1f84bSDavid du Colombier 
808*9ef1f84bSDavid du Colombier 	off = ~0LL;
809*9ef1f84bSDavid du Colombier 	if(ispwrite)
810*9ef1f84bSDavid du Colombier 		off = va_arg(list, vlong);
811*9ef1f84bSDavid du Colombier 	if(off == ~0LL){	/* use and maintain channel's offset */
812*9ef1f84bSDavid du Colombier 		lock(c);
813*9ef1f84bSDavid du Colombier 		off = c->offset;
814*9ef1f84bSDavid du Colombier 		c->offset += n;
815*9ef1f84bSDavid du Colombier 		unlock(c);
816*9ef1f84bSDavid du Colombier 	}
817*9ef1f84bSDavid du Colombier 
818*9ef1f84bSDavid du Colombier 	r = c->dev->write(c, p, n, off);
819*9ef1f84bSDavid du Colombier 
820*9ef1f84bSDavid du Colombier 	if(!ispwrite && r < n){
821*9ef1f84bSDavid du Colombier 		lock(c);
822*9ef1f84bSDavid du Colombier 		c->offset -= n - r;
823*9ef1f84bSDavid du Colombier 		unlock(c);
824*9ef1f84bSDavid du Colombier 	}
825*9ef1f84bSDavid du Colombier 
826*9ef1f84bSDavid du Colombier 	poperror();
827*9ef1f84bSDavid du Colombier 	cclose(c);
828*9ef1f84bSDavid du Colombier 
829*9ef1f84bSDavid du Colombier 	return r;
830*9ef1f84bSDavid du Colombier }
831*9ef1f84bSDavid du Colombier 
832*9ef1f84bSDavid du Colombier void
sys_write(Ar0 * ar0,va_list list)833*9ef1f84bSDavid du Colombier sys_write(Ar0* ar0, va_list list)
834*9ef1f84bSDavid du Colombier {
835*9ef1f84bSDavid du Colombier 	/*
836*9ef1f84bSDavid du Colombier 	 * long write(int fd, void* buf, long nbytes);
837*9ef1f84bSDavid du Colombier 	 */
838*9ef1f84bSDavid du Colombier 	ar0->l = write(list, 0);
839*9ef1f84bSDavid du Colombier }
840*9ef1f84bSDavid du Colombier 
841*9ef1f84bSDavid du Colombier void
syspwrite(Ar0 * ar0,va_list list)842*9ef1f84bSDavid du Colombier syspwrite(Ar0* ar0, va_list list)
843*9ef1f84bSDavid du Colombier {
844*9ef1f84bSDavid du Colombier 	/*
845*9ef1f84bSDavid du Colombier 	 * long pwrite(int fd, void *buf, long nbytes, vlong offset);
846*9ef1f84bSDavid du Colombier 	 */
847*9ef1f84bSDavid du Colombier 	ar0->l = write(list, 1);
848*9ef1f84bSDavid du Colombier }
849*9ef1f84bSDavid du Colombier 
850*9ef1f84bSDavid du Colombier static vlong
sseek(int fd,vlong offset,int whence)851*9ef1f84bSDavid du Colombier sseek(int fd, vlong offset, int whence)
852*9ef1f84bSDavid du Colombier {
853*9ef1f84bSDavid du Colombier 	Chan *c;
854*9ef1f84bSDavid du Colombier 	uchar buf[sizeof(Dir)+100];
855*9ef1f84bSDavid du Colombier 	Dir dir;
856*9ef1f84bSDavid du Colombier 	int n;
857*9ef1f84bSDavid du Colombier 
858*9ef1f84bSDavid du Colombier 	c = fdtochan(fd, -1, 1, 1);
859*9ef1f84bSDavid du Colombier 	if(waserror()){
860*9ef1f84bSDavid du Colombier 		cclose(c);
861*9ef1f84bSDavid du Colombier 		nexterror();
862*9ef1f84bSDavid du Colombier 	}
863*9ef1f84bSDavid du Colombier 	if(c->dev->dc == '|')
864*9ef1f84bSDavid du Colombier 		error(Eisstream);
865*9ef1f84bSDavid du Colombier 
866*9ef1f84bSDavid du Colombier 	switch(whence){
867*9ef1f84bSDavid du Colombier 	case 0:
868*9ef1f84bSDavid du Colombier 		if((c->qid.type & QTDIR) && offset != 0LL)
869*9ef1f84bSDavid du Colombier 			error(Eisdir);
870*9ef1f84bSDavid du Colombier 		c->offset = offset;
871*9ef1f84bSDavid du Colombier 		break;
872*9ef1f84bSDavid du Colombier 
873*9ef1f84bSDavid du Colombier 	case 1:
874*9ef1f84bSDavid du Colombier 		if(c->qid.type & QTDIR)
875*9ef1f84bSDavid du Colombier 			error(Eisdir);
876*9ef1f84bSDavid du Colombier 		lock(c);	/* lock for read/write update */
877*9ef1f84bSDavid du Colombier 		offset += c->offset;
878*9ef1f84bSDavid du Colombier 		c->offset = offset;
879*9ef1f84bSDavid du Colombier 		unlock(c);
880*9ef1f84bSDavid du Colombier 		break;
881*9ef1f84bSDavid du Colombier 
882*9ef1f84bSDavid du Colombier 	case 2:
883*9ef1f84bSDavid du Colombier 		if(c->qid.type & QTDIR)
884*9ef1f84bSDavid du Colombier 			error(Eisdir);
885*9ef1f84bSDavid du Colombier 		n = c->dev->stat(c, buf, sizeof buf);
886*9ef1f84bSDavid du Colombier 		if(convM2D(buf, n, &dir, nil) == 0)
887*9ef1f84bSDavid du Colombier 			error("internal error: stat error in seek");
888*9ef1f84bSDavid du Colombier 		offset += dir.length;
889*9ef1f84bSDavid du Colombier 		c->offset = offset;
890*9ef1f84bSDavid du Colombier 		break;
891*9ef1f84bSDavid du Colombier 
892*9ef1f84bSDavid du Colombier 	default:
893*9ef1f84bSDavid du Colombier 		error(Ebadarg);
894*9ef1f84bSDavid du Colombier 	}
895*9ef1f84bSDavid du Colombier 	c->uri = 0;
896*9ef1f84bSDavid du Colombier 	c->dri = 0;
897*9ef1f84bSDavid du Colombier 	cclose(c);
898*9ef1f84bSDavid du Colombier 	poperror();
899*9ef1f84bSDavid du Colombier 
900*9ef1f84bSDavid du Colombier 	return offset;
901*9ef1f84bSDavid du Colombier }
902*9ef1f84bSDavid du Colombier 
903*9ef1f84bSDavid du Colombier void
sysseek(Ar0 * ar0,va_list list)904*9ef1f84bSDavid du Colombier sysseek(Ar0* ar0, va_list list)
905*9ef1f84bSDavid du Colombier {
906*9ef1f84bSDavid du Colombier 	int fd, whence;
907*9ef1f84bSDavid du Colombier 	vlong offset, *rv;
908*9ef1f84bSDavid du Colombier 
909*9ef1f84bSDavid du Colombier 	/*
910*9ef1f84bSDavid du Colombier 	 * vlong seek(int fd, vlong n, int type);
911*9ef1f84bSDavid du Colombier 	 *
912*9ef1f84bSDavid du Colombier 	 * The system call actually has 4 arguments,
913*9ef1f84bSDavid du Colombier 	 *	int _seek(vlong*, int, vlong, int);
914*9ef1f84bSDavid du Colombier 	 * and the first argument is where the offset
915*9ef1f84bSDavid du Colombier 	 * is returned. The C library arranges the
916*9ef1f84bSDavid du Colombier 	 * argument/return munging if necessary.
917*9ef1f84bSDavid du Colombier 	 */
918*9ef1f84bSDavid du Colombier 	rv = va_arg(list, vlong*);
919*9ef1f84bSDavid du Colombier 	rv = validaddr(rv, sizeof(vlong), 1);
920*9ef1f84bSDavid du Colombier 
921*9ef1f84bSDavid du Colombier 	fd = va_arg(list, int);
922*9ef1f84bSDavid du Colombier 	offset = va_arg(list, vlong);
923*9ef1f84bSDavid du Colombier 	whence = va_arg(list, int);
924*9ef1f84bSDavid du Colombier 	*rv = sseek(fd, offset, whence);
925*9ef1f84bSDavid du Colombier 
926*9ef1f84bSDavid du Colombier 	ar0->i = 0;
927*9ef1f84bSDavid du Colombier }
928*9ef1f84bSDavid du Colombier 
929*9ef1f84bSDavid du Colombier void
sysoseek(Ar0 * ar0,va_list list)930*9ef1f84bSDavid du Colombier sysoseek(Ar0* ar0, va_list list)
931*9ef1f84bSDavid du Colombier {
932*9ef1f84bSDavid du Colombier 	long offset;
933*9ef1f84bSDavid du Colombier 	int fd, whence;
934*9ef1f84bSDavid du Colombier 
935*9ef1f84bSDavid du Colombier 	/*
936*9ef1f84bSDavid du Colombier 	 * long oseek(int fd, long n, int type);
937*9ef1f84bSDavid du Colombier 	 *
938*9ef1f84bSDavid du Colombier 	 * Deprecated; backwards compatibility only.
939*9ef1f84bSDavid du Colombier 	 */
940*9ef1f84bSDavid du Colombier 	fd = va_arg(list, int);
941*9ef1f84bSDavid du Colombier 	offset = va_arg(list, long);
942*9ef1f84bSDavid du Colombier 	whence = va_arg(list, int);
943*9ef1f84bSDavid du Colombier 
944*9ef1f84bSDavid du Colombier 	ar0->l = sseek(fd, offset, whence);
945*9ef1f84bSDavid du Colombier }
946*9ef1f84bSDavid du Colombier 
947*9ef1f84bSDavid du Colombier void
validstat(uchar * s,usize n)948*9ef1f84bSDavid du Colombier validstat(uchar *s, usize n)
949*9ef1f84bSDavid du Colombier {
950*9ef1f84bSDavid du Colombier 	usize m;
951*9ef1f84bSDavid du Colombier 	char buf[64];
952*9ef1f84bSDavid du Colombier 
953*9ef1f84bSDavid du Colombier 	if(statcheck(s, n) < 0)
954*9ef1f84bSDavid du Colombier 		error(Ebadstat);
955*9ef1f84bSDavid du Colombier 	/* verify that name entry is acceptable */
956*9ef1f84bSDavid du Colombier 	s += STATFIXLEN - 4*BIT16SZ;	/* location of first string */
957*9ef1f84bSDavid du Colombier 	/*
958*9ef1f84bSDavid du Colombier 	 * s now points at count for first string.
959*9ef1f84bSDavid du Colombier 	 * if it's too long, let the server decide; this is
960*9ef1f84bSDavid du Colombier 	 * only for his protection anyway. otherwise
961*9ef1f84bSDavid du Colombier 	 * we'd have to allocate and waserror.
962*9ef1f84bSDavid du Colombier 	 */
963*9ef1f84bSDavid du Colombier 	m = GBIT16(s);
964*9ef1f84bSDavid du Colombier 	s += BIT16SZ;
965*9ef1f84bSDavid du Colombier 	if(m+1 > sizeof buf)
966*9ef1f84bSDavid du Colombier 		return;
967*9ef1f84bSDavid du Colombier 	memmove(buf, s, m);
968*9ef1f84bSDavid du Colombier 	buf[m] = '\0';
969*9ef1f84bSDavid du Colombier 	/* name could be '/' */
970*9ef1f84bSDavid du Colombier 	if(strcmp(buf, "/") != 0)
971*9ef1f84bSDavid du Colombier 		validname(buf, 0);
972*9ef1f84bSDavid du Colombier }
973*9ef1f84bSDavid du Colombier 
974*9ef1f84bSDavid du Colombier static char*
pathlast(Path * p)975*9ef1f84bSDavid du Colombier pathlast(Path *p)
976*9ef1f84bSDavid du Colombier {
977*9ef1f84bSDavid du Colombier 	char *s;
978*9ef1f84bSDavid du Colombier 
979*9ef1f84bSDavid du Colombier 	if(p == nil)
980*9ef1f84bSDavid du Colombier 		return nil;
981*9ef1f84bSDavid du Colombier 	if(p->len == 0)
982*9ef1f84bSDavid du Colombier 		return nil;
983*9ef1f84bSDavid du Colombier 	s = strrchr(p->s, '/');
984*9ef1f84bSDavid du Colombier 	if(s)
985*9ef1f84bSDavid du Colombier 		return s+1;
986*9ef1f84bSDavid du Colombier 	return p->s;
987*9ef1f84bSDavid du Colombier }
988*9ef1f84bSDavid du Colombier 
989*9ef1f84bSDavid du Colombier void
sysfstat(Ar0 * ar0,va_list list)990*9ef1f84bSDavid du Colombier sysfstat(Ar0* ar0, va_list list)
991*9ef1f84bSDavid du Colombier {
992*9ef1f84bSDavid du Colombier 	int fd;
993*9ef1f84bSDavid du Colombier 	Chan *c;
994*9ef1f84bSDavid du Colombier 	usize n;
995*9ef1f84bSDavid du Colombier 	int r;
996*9ef1f84bSDavid du Colombier 	uchar *p;
997*9ef1f84bSDavid du Colombier 
998*9ef1f84bSDavid du Colombier 	/*
999*9ef1f84bSDavid du Colombier 	 * int fstat(int fd, uchar* edir, int nedir);
1000*9ef1f84bSDavid du Colombier 	 * should really be
1001*9ef1f84bSDavid du Colombier 	 * usize fstat(int fd, uchar* edir, usize nedir);
1002*9ef1f84bSDavid du Colombier 	 * but returning an unsigned is probably too
1003*9ef1f84bSDavid du Colombier 	 * radical.
1004*9ef1f84bSDavid du Colombier 	 */
1005*9ef1f84bSDavid du Colombier 	fd = va_arg(list, int);
1006*9ef1f84bSDavid du Colombier 	p = va_arg(list, uchar*);
1007*9ef1f84bSDavid du Colombier 	n = va_arg(list, usize);
1008*9ef1f84bSDavid du Colombier 
1009*9ef1f84bSDavid du Colombier 	p = validaddr(p, n, 1);
1010*9ef1f84bSDavid du Colombier 	c = fdtochan(fd, -1, 0, 1);
1011*9ef1f84bSDavid du Colombier 	if(waserror()) {
1012*9ef1f84bSDavid du Colombier 		cclose(c);
1013*9ef1f84bSDavid du Colombier 		nexterror();
1014*9ef1f84bSDavid du Colombier 	}
1015*9ef1f84bSDavid du Colombier 	r = c->dev->stat(c, p, n);
1016*9ef1f84bSDavid du Colombier 	poperror();
1017*9ef1f84bSDavid du Colombier 	cclose(c);
1018*9ef1f84bSDavid du Colombier 
1019*9ef1f84bSDavid du Colombier 	ar0->i = r;
1020*9ef1f84bSDavid du Colombier }
1021*9ef1f84bSDavid du Colombier 
1022*9ef1f84bSDavid du Colombier void
sysstat(Ar0 * ar0,va_list list)1023*9ef1f84bSDavid du Colombier sysstat(Ar0* ar0, va_list list)
1024*9ef1f84bSDavid du Colombier {
1025*9ef1f84bSDavid du Colombier 	char *aname;
1026*9ef1f84bSDavid du Colombier 	Chan *c;
1027*9ef1f84bSDavid du Colombier 	usize n;
1028*9ef1f84bSDavid du Colombier 	int r;
1029*9ef1f84bSDavid du Colombier 	uchar *p;
1030*9ef1f84bSDavid du Colombier 
1031*9ef1f84bSDavid du Colombier 	/*
1032*9ef1f84bSDavid du Colombier 	 * int stat(char* name, uchar* edir, int nedir);
1033*9ef1f84bSDavid du Colombier 	 * should really be
1034*9ef1f84bSDavid du Colombier 	 * usize stat(char* name, uchar* edir, usize nedir);
1035*9ef1f84bSDavid du Colombier 	 * but returning an unsigned is probably too
1036*9ef1f84bSDavid du Colombier 	 * radical.
1037*9ef1f84bSDavid du Colombier 	 */
1038*9ef1f84bSDavid du Colombier 	aname = va_arg(list, char*);
1039*9ef1f84bSDavid du Colombier 	aname = validaddr(aname, 1, 0);
1040*9ef1f84bSDavid du Colombier 	p = va_arg(list, uchar*);
1041*9ef1f84bSDavid du Colombier 	n = va_arg(list, usize);
1042*9ef1f84bSDavid du Colombier 
1043*9ef1f84bSDavid du Colombier 	p = validaddr(p, n, 1);
1044*9ef1f84bSDavid du Colombier 	c = namec(aname, Aaccess, 0, 0);
1045*9ef1f84bSDavid du Colombier 	if(waserror()){
1046*9ef1f84bSDavid du Colombier 		cclose(c);
1047*9ef1f84bSDavid du Colombier 		nexterror();
1048*9ef1f84bSDavid du Colombier 	}
1049*9ef1f84bSDavid du Colombier 	r = c->dev->stat(c, p, n);
1050*9ef1f84bSDavid du Colombier 	aname = pathlast(c->path);
1051*9ef1f84bSDavid du Colombier 	if(aname)
1052*9ef1f84bSDavid du Colombier 		r = dirsetname(aname, strlen(aname), p, r, n);
1053*9ef1f84bSDavid du Colombier 
1054*9ef1f84bSDavid du Colombier 	poperror();
1055*9ef1f84bSDavid du Colombier 	cclose(c);
1056*9ef1f84bSDavid du Colombier 
1057*9ef1f84bSDavid du Colombier 	ar0->i = r;
1058*9ef1f84bSDavid du Colombier }
1059*9ef1f84bSDavid du Colombier 
1060*9ef1f84bSDavid du Colombier void
syschdir(Ar0 * ar0,va_list list)1061*9ef1f84bSDavid du Colombier syschdir(Ar0* ar0, va_list list)
1062*9ef1f84bSDavid du Colombier {
1063*9ef1f84bSDavid du Colombier 	Chan *c;
1064*9ef1f84bSDavid du Colombier 	char *aname;
1065*9ef1f84bSDavid du Colombier 
1066*9ef1f84bSDavid du Colombier 	/*
1067*9ef1f84bSDavid du Colombier 	 * int chdir(char* dirname);
1068*9ef1f84bSDavid du Colombier 	 */
1069*9ef1f84bSDavid du Colombier 	aname = va_arg(list, char*);
1070*9ef1f84bSDavid du Colombier 	aname = validaddr(aname, 1, 0);
1071*9ef1f84bSDavid du Colombier 
1072*9ef1f84bSDavid du Colombier 	c = namec(aname, Atodir, 0, 0);
1073*9ef1f84bSDavid du Colombier 	cclose(up->dot);
1074*9ef1f84bSDavid du Colombier 	up->dot = c;
1075*9ef1f84bSDavid du Colombier 
1076*9ef1f84bSDavid du Colombier 	ar0->i = 0;
1077*9ef1f84bSDavid du Colombier }
1078*9ef1f84bSDavid du Colombier 
1079*9ef1f84bSDavid du Colombier static int
bindmount(int ismount,int fd,int afd,char * arg0,char * arg1,int flag,char * spec)1080*9ef1f84bSDavid du Colombier bindmount(int ismount, int fd, int afd, char* arg0, char* arg1, int flag, char* spec)
1081*9ef1f84bSDavid du Colombier {
1082*9ef1f84bSDavid du Colombier 	int i;
1083*9ef1f84bSDavid du Colombier 	Dev *dev;
1084*9ef1f84bSDavid du Colombier 	Chan *c0, *c1, *ac, *bc;
1085*9ef1f84bSDavid du Colombier 	struct{
1086*9ef1f84bSDavid du Colombier 		Chan	*chan;
1087*9ef1f84bSDavid du Colombier 		Chan	*authchan;
1088*9ef1f84bSDavid du Colombier 		char	*spec;
1089*9ef1f84bSDavid du Colombier 		int	flags;
1090*9ef1f84bSDavid du Colombier 	}bogus;
1091*9ef1f84bSDavid du Colombier 
1092*9ef1f84bSDavid du Colombier 	if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER))
1093*9ef1f84bSDavid du Colombier 		error(Ebadarg);
1094*9ef1f84bSDavid du Colombier 
1095*9ef1f84bSDavid du Colombier 	bogus.flags = flag & MCACHE;
1096*9ef1f84bSDavid du Colombier 
1097*9ef1f84bSDavid du Colombier 	if(ismount){
1098*9ef1f84bSDavid du Colombier 		if(up->pgrp->noattach)
1099*9ef1f84bSDavid du Colombier 			error(Enoattach);
1100*9ef1f84bSDavid du Colombier 
1101*9ef1f84bSDavid du Colombier 		ac = nil;
1102*9ef1f84bSDavid du Colombier 		bc = fdtochan(fd, ORDWR, 0, 1);
1103*9ef1f84bSDavid du Colombier 		if(waserror()) {
1104*9ef1f84bSDavid du Colombier 			if(ac)
1105*9ef1f84bSDavid du Colombier 				cclose(ac);
1106*9ef1f84bSDavid du Colombier 			cclose(bc);
1107*9ef1f84bSDavid du Colombier 			nexterror();
1108*9ef1f84bSDavid du Colombier 		}
1109*9ef1f84bSDavid du Colombier 
1110*9ef1f84bSDavid du Colombier 		if(afd >= 0)
1111*9ef1f84bSDavid du Colombier 			ac = fdtochan(afd, ORDWR, 0, 1);
1112*9ef1f84bSDavid du Colombier 
1113*9ef1f84bSDavid du Colombier 		bogus.chan = bc;
1114*9ef1f84bSDavid du Colombier 		bogus.authchan = ac;
1115*9ef1f84bSDavid du Colombier 
1116*9ef1f84bSDavid du Colombier 		bogus.spec = validaddr(spec, 1, 0);
1117*9ef1f84bSDavid du Colombier 		if(waserror())
1118*9ef1f84bSDavid du Colombier 			error(Ebadspec);
1119*9ef1f84bSDavid du Colombier 		spec = validnamedup(spec, 1);
1120*9ef1f84bSDavid du Colombier 		poperror();
1121*9ef1f84bSDavid du Colombier 
1122*9ef1f84bSDavid du Colombier 		if(waserror()){
1123*9ef1f84bSDavid du Colombier 			free(spec);
1124*9ef1f84bSDavid du Colombier 			nexterror();
1125*9ef1f84bSDavid du Colombier 		}
1126*9ef1f84bSDavid du Colombier 
1127*9ef1f84bSDavid du Colombier 		dev = devtabget('M', 0);		//XDYNX
1128*9ef1f84bSDavid du Colombier 		if(waserror()){
1129*9ef1f84bSDavid du Colombier 			//devtabdecr(dev);
1130*9ef1f84bSDavid du Colombier 			nexterror();
1131*9ef1f84bSDavid du Colombier 		}
1132*9ef1f84bSDavid du Colombier 		c0 = dev->attach((char*)&bogus);
1133*9ef1f84bSDavid du Colombier 		poperror();
1134*9ef1f84bSDavid du Colombier 		//devtabdecr(dev);
1135*9ef1f84bSDavid du Colombier 
1136*9ef1f84bSDavid du Colombier 		poperror();	/* spec */
1137*9ef1f84bSDavid du Colombier 		free(spec);
1138*9ef1f84bSDavid du Colombier 		poperror();	/* ac bc */
1139*9ef1f84bSDavid du Colombier 		if(ac)
1140*9ef1f84bSDavid du Colombier 			cclose(ac);
1141*9ef1f84bSDavid du Colombier 		cclose(bc);
1142*9ef1f84bSDavid du Colombier 	}else{
1143*9ef1f84bSDavid du Colombier 		bogus.spec = nil;
1144*9ef1f84bSDavid du Colombier 		c0 = namec(validaddr(arg0, 1, 0), Abind, 0, 0);
1145*9ef1f84bSDavid du Colombier 	}
1146*9ef1f84bSDavid du Colombier 
1147*9ef1f84bSDavid du Colombier 	if(waserror()){
1148*9ef1f84bSDavid du Colombier 		cclose(c0);
1149*9ef1f84bSDavid du Colombier 		nexterror();
1150*9ef1f84bSDavid du Colombier 	}
1151*9ef1f84bSDavid du Colombier 
1152*9ef1f84bSDavid du Colombier 	c1 = namec(validaddr(arg1, 1, 0), Amount, 0, 0);
1153*9ef1f84bSDavid du Colombier 	if(waserror()){
1154*9ef1f84bSDavid du Colombier 		cclose(c1);
1155*9ef1f84bSDavid du Colombier 		nexterror();
1156*9ef1f84bSDavid du Colombier 	}
1157*9ef1f84bSDavid du Colombier 
1158*9ef1f84bSDavid du Colombier 	i = cmount(&c0, c1, flag, bogus.spec);
1159*9ef1f84bSDavid du Colombier 
1160*9ef1f84bSDavid du Colombier 	poperror();
1161*9ef1f84bSDavid du Colombier 	cclose(c1);
1162*9ef1f84bSDavid du Colombier 	poperror();
1163*9ef1f84bSDavid du Colombier 	cclose(c0);
1164*9ef1f84bSDavid du Colombier 	if(ismount)
1165*9ef1f84bSDavid du Colombier 		fdclose(fd, 0);
1166*9ef1f84bSDavid du Colombier 
1167*9ef1f84bSDavid du Colombier 	return i;
1168*9ef1f84bSDavid du Colombier }
1169*9ef1f84bSDavid du Colombier 
1170*9ef1f84bSDavid du Colombier void
sysbind(Ar0 * ar0,va_list list)1171*9ef1f84bSDavid du Colombier sysbind(Ar0* ar0, va_list list)
1172*9ef1f84bSDavid du Colombier {
1173*9ef1f84bSDavid du Colombier 	int flag;
1174*9ef1f84bSDavid du Colombier 	char *name, *old;
1175*9ef1f84bSDavid du Colombier 
1176*9ef1f84bSDavid du Colombier 	/*
1177*9ef1f84bSDavid du Colombier 	 * int bind(char* name, char* old, int flag);
1178*9ef1f84bSDavid du Colombier 	 * should be
1179*9ef1f84bSDavid du Colombier 	 * long bind(char* name, char* old, int flag);
1180*9ef1f84bSDavid du Colombier 	 */
1181*9ef1f84bSDavid du Colombier 	name = va_arg(list, char*);
1182*9ef1f84bSDavid du Colombier 	old = va_arg(list, char*);
1183*9ef1f84bSDavid du Colombier 	flag = va_arg(list, int);
1184*9ef1f84bSDavid du Colombier 
1185*9ef1f84bSDavid du Colombier 	ar0->i = bindmount(0, -1, -1, name, old, flag, nil);
1186*9ef1f84bSDavid du Colombier }
1187*9ef1f84bSDavid du Colombier 
1188*9ef1f84bSDavid du Colombier void
sysmount(Ar0 * ar0,va_list list)1189*9ef1f84bSDavid du Colombier sysmount(Ar0* ar0, va_list list)
1190*9ef1f84bSDavid du Colombier {
1191*9ef1f84bSDavid du Colombier 	int afd, fd, flag;
1192*9ef1f84bSDavid du Colombier 	char *aname, *old;
1193*9ef1f84bSDavid du Colombier 
1194*9ef1f84bSDavid du Colombier 	/*
1195*9ef1f84bSDavid du Colombier 	 * int mount(int fd, int afd, char* old, int flag, char* aname);
1196*9ef1f84bSDavid du Colombier 	 * should be
1197*9ef1f84bSDavid du Colombier 	 * long mount(int fd, int afd, char* old, int flag, char* aname);
1198*9ef1f84bSDavid du Colombier 	 */
1199*9ef1f84bSDavid du Colombier 	fd = va_arg(list, int);
1200*9ef1f84bSDavid du Colombier 	afd = va_arg(list, int);
1201*9ef1f84bSDavid du Colombier 	old = va_arg(list, char*);
1202*9ef1f84bSDavid du Colombier 	flag = va_arg(list, int);
1203*9ef1f84bSDavid du Colombier 	aname = va_arg(list, char*);
1204*9ef1f84bSDavid du Colombier 
1205*9ef1f84bSDavid du Colombier 	ar0->i = bindmount(1, fd, afd, nil, old, flag, aname);
1206*9ef1f84bSDavid du Colombier }
1207*9ef1f84bSDavid du Colombier 
1208*9ef1f84bSDavid du Colombier void
sys_mount(Ar0 * ar0,va_list list)1209*9ef1f84bSDavid du Colombier sys_mount(Ar0* ar0, va_list list)
1210*9ef1f84bSDavid du Colombier {
1211*9ef1f84bSDavid du Colombier 	int fd, flag;
1212*9ef1f84bSDavid du Colombier 	char *aname, *old;
1213*9ef1f84bSDavid du Colombier 
1214*9ef1f84bSDavid du Colombier 	/*
1215*9ef1f84bSDavid du Colombier 	 * int mount(int fd, char *old, int flag, char *aname);
1216*9ef1f84bSDavid du Colombier 	 * should be
1217*9ef1f84bSDavid du Colombier 	 * long mount(int fd, char *old, int flag, char *aname);
1218*9ef1f84bSDavid du Colombier 	 *
1219*9ef1f84bSDavid du Colombier 	 * Deprecated; backwards compatibility only.
1220*9ef1f84bSDavid du Colombier 	 */
1221*9ef1f84bSDavid du Colombier 	fd = va_arg(list, int);
1222*9ef1f84bSDavid du Colombier 	old = va_arg(list, char*);
1223*9ef1f84bSDavid du Colombier 	flag = va_arg(list, int);
1224*9ef1f84bSDavid du Colombier 	aname = va_arg(list, char*);
1225*9ef1f84bSDavid du Colombier 
1226*9ef1f84bSDavid du Colombier 	ar0->i = bindmount(1, fd, -1, nil, old, flag, aname);
1227*9ef1f84bSDavid du Colombier }
1228*9ef1f84bSDavid du Colombier 
1229*9ef1f84bSDavid du Colombier void
sysunmount(Ar0 * ar0,va_list list)1230*9ef1f84bSDavid du Colombier sysunmount(Ar0* ar0, va_list list)
1231*9ef1f84bSDavid du Colombier {
1232*9ef1f84bSDavid du Colombier 	char *name, *old;
1233*9ef1f84bSDavid du Colombier 	Chan *cmount, *cmounted;
1234*9ef1f84bSDavid du Colombier 
1235*9ef1f84bSDavid du Colombier 	/*
1236*9ef1f84bSDavid du Colombier 	 * int unmount(char* name, char* old);
1237*9ef1f84bSDavid du Colombier 	 */
1238*9ef1f84bSDavid du Colombier 	name = va_arg(list, char*);
1239*9ef1f84bSDavid du Colombier 	old = va_arg(list, char*);
1240*9ef1f84bSDavid du Colombier 	cmount = namec(validaddr(old, 1, 0), Amount, 0, 0);
1241*9ef1f84bSDavid du Colombier 
1242*9ef1f84bSDavid du Colombier 	cmounted = nil;
1243*9ef1f84bSDavid du Colombier 	if(name != nil) {
1244*9ef1f84bSDavid du Colombier 		if(waserror()) {
1245*9ef1f84bSDavid du Colombier 			cclose(cmount);
1246*9ef1f84bSDavid du Colombier 			nexterror();
1247*9ef1f84bSDavid du Colombier 		}
1248*9ef1f84bSDavid du Colombier 
1249*9ef1f84bSDavid du Colombier 		/*
1250*9ef1f84bSDavid du Colombier 		 * This has to be namec(..., Aopen, ...) because
1251*9ef1f84bSDavid du Colombier 		 * if arg[0] is something like /srv/cs or /fd/0,
1252*9ef1f84bSDavid du Colombier 		 * opening it is the only way to get at the real
1253*9ef1f84bSDavid du Colombier 		 * Chan underneath.
1254*9ef1f84bSDavid du Colombier 		 */
1255*9ef1f84bSDavid du Colombier 		cmounted = namec(validaddr(name, 1, 0), Aopen, OREAD, 0);
1256*9ef1f84bSDavid du Colombier 		poperror();
1257*9ef1f84bSDavid du Colombier 	}
1258*9ef1f84bSDavid du Colombier 
1259*9ef1f84bSDavid du Colombier 	if(waserror()) {
1260*9ef1f84bSDavid du Colombier 		cclose(cmount);
1261*9ef1f84bSDavid du Colombier 		if(cmounted != nil)
1262*9ef1f84bSDavid du Colombier 			cclose(cmounted);
1263*9ef1f84bSDavid du Colombier 		nexterror();
1264*9ef1f84bSDavid du Colombier 	}
1265*9ef1f84bSDavid du Colombier 
1266*9ef1f84bSDavid du Colombier 	cunmount(cmount, cmounted);
1267*9ef1f84bSDavid du Colombier 	cclose(cmount);
1268*9ef1f84bSDavid du Colombier 	if(cmounted != nil)
1269*9ef1f84bSDavid du Colombier 		cclose(cmounted);
1270*9ef1f84bSDavid du Colombier 	poperror();
1271*9ef1f84bSDavid du Colombier 
1272*9ef1f84bSDavid du Colombier 	ar0->i = 0;
1273*9ef1f84bSDavid du Colombier }
1274*9ef1f84bSDavid du Colombier 
1275*9ef1f84bSDavid du Colombier void
syscreate(Ar0 * ar0,va_list list)1276*9ef1f84bSDavid du Colombier syscreate(Ar0* ar0, va_list list)
1277*9ef1f84bSDavid du Colombier {
1278*9ef1f84bSDavid du Colombier 	char *aname;
1279*9ef1f84bSDavid du Colombier 	int fd, omode, perm;
1280*9ef1f84bSDavid du Colombier 	Chan *c;
1281*9ef1f84bSDavid du Colombier 
1282*9ef1f84bSDavid du Colombier 	/*
1283*9ef1f84bSDavid du Colombier 	 * int create(char* file, int omode, ulong perm);
1284*9ef1f84bSDavid du Colombier 	 * should be
1285*9ef1f84bSDavid du Colombier 	 * int create(char* file, int omode, int perm);
1286*9ef1f84bSDavid du Colombier 	 */
1287*9ef1f84bSDavid du Colombier 	aname = va_arg(list, char*);
1288*9ef1f84bSDavid du Colombier 	omode = va_arg(list, int);
1289*9ef1f84bSDavid du Colombier 	perm = va_arg(list, int);
1290*9ef1f84bSDavid du Colombier 
1291*9ef1f84bSDavid du Colombier 	openmode(omode & ~OEXCL);	/* error check only; OEXCL okay here */
1292*9ef1f84bSDavid du Colombier 	c = nil;
1293*9ef1f84bSDavid du Colombier 	if(waserror()) {
1294*9ef1f84bSDavid du Colombier 		if(c != nil)
1295*9ef1f84bSDavid du Colombier 			cclose(c);
1296*9ef1f84bSDavid du Colombier 		nexterror();
1297*9ef1f84bSDavid du Colombier 	}
1298*9ef1f84bSDavid du Colombier 	c = namec(validaddr(aname, 1, 0), Acreate, omode, perm);
1299*9ef1f84bSDavid du Colombier 	fd = newfd(c);
1300*9ef1f84bSDavid du Colombier 	if(fd < 0)
1301*9ef1f84bSDavid du Colombier 		error(Enofd);
1302*9ef1f84bSDavid du Colombier 	poperror();
1303*9ef1f84bSDavid du Colombier 
1304*9ef1f84bSDavid du Colombier 	ar0->i = fd;
1305*9ef1f84bSDavid du Colombier }
1306*9ef1f84bSDavid du Colombier 
1307*9ef1f84bSDavid du Colombier void
sysremove(Ar0 * ar0,va_list list)1308*9ef1f84bSDavid du Colombier sysremove(Ar0* ar0, va_list list)
1309*9ef1f84bSDavid du Colombier {
1310*9ef1f84bSDavid du Colombier 	Chan *c;
1311*9ef1f84bSDavid du Colombier 	char *aname;
1312*9ef1f84bSDavid du Colombier 
1313*9ef1f84bSDavid du Colombier 	/*
1314*9ef1f84bSDavid du Colombier 	 * int remove(char* file);
1315*9ef1f84bSDavid du Colombier 	 */
1316*9ef1f84bSDavid du Colombier 	aname = va_arg(list, char*);
1317*9ef1f84bSDavid du Colombier 	c = namec(validaddr(aname, 1, 0), Aremove, 0, 0);
1318*9ef1f84bSDavid du Colombier 
1319*9ef1f84bSDavid du Colombier 	/*
1320*9ef1f84bSDavid du Colombier 	 * Removing mount points is disallowed to avoid surprises
1321*9ef1f84bSDavid du Colombier 	 * (which should be removed: the mount point or the mounted Chan?).
1322*9ef1f84bSDavid du Colombier 	 */
1323*9ef1f84bSDavid du Colombier 	if(c->ismtpt){
1324*9ef1f84bSDavid du Colombier 		cclose(c);
1325*9ef1f84bSDavid du Colombier 		error(Eismtpt);
1326*9ef1f84bSDavid du Colombier 	}
1327*9ef1f84bSDavid du Colombier 	if(waserror()){
1328*9ef1f84bSDavid du Colombier 		c->dev = nil;	/* see below */
1329*9ef1f84bSDavid du Colombier 		cclose(c);
1330*9ef1f84bSDavid du Colombier 		nexterror();
1331*9ef1f84bSDavid du Colombier 	}
1332*9ef1f84bSDavid du Colombier 	c->dev->remove(c);
1333*9ef1f84bSDavid du Colombier 
1334*9ef1f84bSDavid du Colombier 	/*
1335*9ef1f84bSDavid du Colombier 	 * Remove clunks the fid, but we need to recover the Chan
1336*9ef1f84bSDavid du Colombier 	 * so fake it up.  rootclose() is known to be a nop.
1337*9ef1f84bSDavid du Colombier Not sure this dicking around is right for Dev ref counts.
1338*9ef1f84bSDavid du Colombier 	 */
1339*9ef1f84bSDavid du Colombier 	c->dev = nil;
1340*9ef1f84bSDavid du Colombier 	poperror();
1341*9ef1f84bSDavid du Colombier 	cclose(c);
1342*9ef1f84bSDavid du Colombier 
1343*9ef1f84bSDavid du Colombier 	ar0->i = 0;
1344*9ef1f84bSDavid du Colombier }
1345*9ef1f84bSDavid du Colombier 
1346*9ef1f84bSDavid du Colombier static long
wstat(Chan * c,uchar * p,usize n)1347*9ef1f84bSDavid du Colombier wstat(Chan* c, uchar* p, usize n)
1348*9ef1f84bSDavid du Colombier {
1349*9ef1f84bSDavid du Colombier 	long l;
1350*9ef1f84bSDavid du Colombier 	usize namelen;
1351*9ef1f84bSDavid du Colombier 
1352*9ef1f84bSDavid du Colombier 	if(waserror()){
1353*9ef1f84bSDavid du Colombier 		cclose(c);
1354*9ef1f84bSDavid du Colombier 		nexterror();
1355*9ef1f84bSDavid du Colombier 	}
1356*9ef1f84bSDavid du Colombier 
1357*9ef1f84bSDavid du Colombier 	/*
1358*9ef1f84bSDavid du Colombier 	 * Renaming mount points is disallowed to avoid surprises
1359*9ef1f84bSDavid du Colombier 	 * (which should be renamed? the mount point or the mounted Chan?).
1360*9ef1f84bSDavid du Colombier 	 */
1361*9ef1f84bSDavid du Colombier 	if(c->ismtpt){
1362*9ef1f84bSDavid du Colombier 		dirname(p, &namelen);
1363*9ef1f84bSDavid du Colombier 		if(namelen)
1364*9ef1f84bSDavid du Colombier 			nameerror(chanpath(c), Eismtpt);
1365*9ef1f84bSDavid du Colombier 	}
1366*9ef1f84bSDavid du Colombier 	l = c->dev->wstat(c, p, n);
1367*9ef1f84bSDavid du Colombier 	poperror();
1368*9ef1f84bSDavid du Colombier 	cclose(c);
1369*9ef1f84bSDavid du Colombier 
1370*9ef1f84bSDavid du Colombier 	return l;
1371*9ef1f84bSDavid du Colombier }
1372*9ef1f84bSDavid du Colombier 
1373*9ef1f84bSDavid du Colombier void
syswstat(Ar0 * ar0,va_list list)1374*9ef1f84bSDavid du Colombier syswstat(Ar0* ar0, va_list list)
1375*9ef1f84bSDavid du Colombier {
1376*9ef1f84bSDavid du Colombier 	Chan *c;
1377*9ef1f84bSDavid du Colombier 	char *aname;
1378*9ef1f84bSDavid du Colombier 	uchar *p;
1379*9ef1f84bSDavid du Colombier 	usize n;
1380*9ef1f84bSDavid du Colombier 
1381*9ef1f84bSDavid du Colombier 	/*
1382*9ef1f84bSDavid du Colombier 	 * int wstat(char* name, uchar* edir, int nedir);
1383*9ef1f84bSDavid du Colombier 	 * should really be
1384*9ef1f84bSDavid du Colombier 	 * usize wstat(char* name, uchar* edir, usize nedir);
1385*9ef1f84bSDavid du Colombier 	 * but returning an unsigned is probably too
1386*9ef1f84bSDavid du Colombier 	 * radical.
1387*9ef1f84bSDavid du Colombier 	 */
1388*9ef1f84bSDavid du Colombier 	aname = va_arg(list, char*);
1389*9ef1f84bSDavid du Colombier 	p = va_arg(list, uchar*);
1390*9ef1f84bSDavid du Colombier 	n = va_arg(list, usize);
1391*9ef1f84bSDavid du Colombier 
1392*9ef1f84bSDavid du Colombier 	p = validaddr(p, n, 0);
1393*9ef1f84bSDavid du Colombier 	validstat(p, n);
1394*9ef1f84bSDavid du Colombier 	c = namec(validaddr(aname, 1, 0), Aaccess, 0, 0);
1395*9ef1f84bSDavid du Colombier 
1396*9ef1f84bSDavid du Colombier 	ar0->l = wstat(c, p, n);
1397*9ef1f84bSDavid du Colombier }
1398*9ef1f84bSDavid du Colombier 
1399*9ef1f84bSDavid du Colombier void
sysfwstat(Ar0 * ar0,va_list list)1400*9ef1f84bSDavid du Colombier sysfwstat(Ar0* ar0, va_list list)
1401*9ef1f84bSDavid du Colombier {
1402*9ef1f84bSDavid du Colombier 	Chan *c;
1403*9ef1f84bSDavid du Colombier 	int fd;
1404*9ef1f84bSDavid du Colombier 	uchar *p;
1405*9ef1f84bSDavid du Colombier 	usize n;
1406*9ef1f84bSDavid du Colombier 
1407*9ef1f84bSDavid du Colombier 	/*
1408*9ef1f84bSDavid du Colombier 	 * int fwstat(int fd, uchar* edir, int nedir);
1409*9ef1f84bSDavid du Colombier 	 * should really be
1410*9ef1f84bSDavid du Colombier 	 * usize fwstat(int fd, uchar* edir, usize nedir);
1411*9ef1f84bSDavid du Colombier 	 * but returning an unsigned is probably too
1412*9ef1f84bSDavid du Colombier 	 * radical.
1413*9ef1f84bSDavid du Colombier 	 */
1414*9ef1f84bSDavid du Colombier 	fd = va_arg(list, int);
1415*9ef1f84bSDavid du Colombier 	p = va_arg(list, uchar*);
1416*9ef1f84bSDavid du Colombier 	n = va_arg(list, usize);
1417*9ef1f84bSDavid du Colombier 
1418*9ef1f84bSDavid du Colombier 	p = validaddr(p, n, 0);
1419*9ef1f84bSDavid du Colombier 	validstat(p, n);
1420*9ef1f84bSDavid du Colombier 	c = fdtochan(fd, -1, 1, 1);
1421*9ef1f84bSDavid du Colombier 
1422*9ef1f84bSDavid du Colombier 	ar0->l = wstat(c, p, n);
1423*9ef1f84bSDavid du Colombier }
1424*9ef1f84bSDavid du Colombier 
1425*9ef1f84bSDavid du Colombier void
sys_stat(Ar0 *,va_list)1426*9ef1f84bSDavid du Colombier sys_stat(Ar0*, va_list)
1427*9ef1f84bSDavid du Colombier {
1428*9ef1f84bSDavid du Colombier 	error("old stat system call - recompile");
1429*9ef1f84bSDavid du Colombier }
1430*9ef1f84bSDavid du Colombier 
1431*9ef1f84bSDavid du Colombier void
sys_fstat(Ar0 *,va_list)1432*9ef1f84bSDavid du Colombier sys_fstat(Ar0*, va_list)
1433*9ef1f84bSDavid du Colombier {
1434*9ef1f84bSDavid du Colombier 	error("old fstat system call - recompile");
1435*9ef1f84bSDavid du Colombier }
1436*9ef1f84bSDavid du Colombier 
1437*9ef1f84bSDavid du Colombier void
sys_wstat(Ar0 *,va_list)1438*9ef1f84bSDavid du Colombier sys_wstat(Ar0*, va_list)
1439*9ef1f84bSDavid du Colombier {
1440*9ef1f84bSDavid du Colombier 	error("old wstat system call - recompile");
1441*9ef1f84bSDavid du Colombier }
1442*9ef1f84bSDavid du Colombier 
1443*9ef1f84bSDavid du Colombier void
sys_fwstat(Ar0 *,va_list)1444*9ef1f84bSDavid du Colombier sys_fwstat(Ar0*, va_list)
1445*9ef1f84bSDavid du Colombier {
1446*9ef1f84bSDavid du Colombier 	error("old fwstat system call - recompile");
1447*9ef1f84bSDavid du Colombier }
1448