xref: /plan9-contrib/sys/src/cmd/unix/drawterm/kern/sysfile.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include	"u.h"
2*8ccd4a63SDavid du Colombier #include	"lib.h"
3*8ccd4a63SDavid du Colombier #include	"dat.h"
4*8ccd4a63SDavid du Colombier #include	"fns.h"
5*8ccd4a63SDavid du Colombier #include	"error.h"
6*8ccd4a63SDavid du Colombier 
7*8ccd4a63SDavid du Colombier #include	"user.h"
8*8ccd4a63SDavid du Colombier #undef open
9*8ccd4a63SDavid du Colombier #undef mount
10*8ccd4a63SDavid du Colombier #undef read
11*8ccd4a63SDavid du Colombier #undef write
12*8ccd4a63SDavid du Colombier #undef seek
13*8ccd4a63SDavid du Colombier #undef stat
14*8ccd4a63SDavid du Colombier #undef wstat
15*8ccd4a63SDavid du Colombier #undef remove
16*8ccd4a63SDavid du Colombier #undef close
17*8ccd4a63SDavid du Colombier #undef fstat
18*8ccd4a63SDavid du Colombier #undef fwstat
19*8ccd4a63SDavid du Colombier 
20*8ccd4a63SDavid du Colombier /*
21*8ccd4a63SDavid du Colombier  * The sys*() routines needn't poperror() as they return directly to syscall().
22*8ccd4a63SDavid du Colombier  */
23*8ccd4a63SDavid du Colombier 
24*8ccd4a63SDavid du Colombier static void
25*8ccd4a63SDavid du Colombier unlockfgrp(Fgrp *f)
26*8ccd4a63SDavid du Colombier {
27*8ccd4a63SDavid du Colombier 	int ex;
28*8ccd4a63SDavid du Colombier 
29*8ccd4a63SDavid du Colombier 	ex = f->exceed;
30*8ccd4a63SDavid du Colombier 	f->exceed = 0;
31*8ccd4a63SDavid du Colombier 	unlock(&f->ref.lk);
32*8ccd4a63SDavid du Colombier 	if(ex)
33*8ccd4a63SDavid du Colombier 		pprint("warning: process exceeds %d file descriptors\n", ex);
34*8ccd4a63SDavid du Colombier }
35*8ccd4a63SDavid du Colombier 
36*8ccd4a63SDavid du Colombier int
37*8ccd4a63SDavid du Colombier growfd(Fgrp *f, int fd)	/* fd is always >= 0 */
38*8ccd4a63SDavid du Colombier {
39*8ccd4a63SDavid du Colombier 	Chan **newfd, **oldfd;
40*8ccd4a63SDavid du Colombier 
41*8ccd4a63SDavid du Colombier 	if(fd < f->nfd)
42*8ccd4a63SDavid du Colombier 		return 0;
43*8ccd4a63SDavid du Colombier 	if(fd >= f->nfd+DELTAFD)
44*8ccd4a63SDavid du Colombier 		return -1;	/* out of range */
45*8ccd4a63SDavid du Colombier 	/*
46*8ccd4a63SDavid du Colombier 	 * Unbounded allocation is unwise; besides, there are only 16 bits
47*8ccd4a63SDavid du Colombier 	 * of fid in 9P
48*8ccd4a63SDavid du Colombier 	 */
49*8ccd4a63SDavid du Colombier 	if(f->nfd >= 5000){
50*8ccd4a63SDavid du Colombier     Exhausted:
51*8ccd4a63SDavid du Colombier 		print("no free file descriptors\n");
52*8ccd4a63SDavid du Colombier 		return -1;
53*8ccd4a63SDavid du Colombier 	}
54*8ccd4a63SDavid du Colombier 	newfd = malloc((f->nfd+DELTAFD)*sizeof(Chan*));
55*8ccd4a63SDavid du Colombier 	if(newfd == 0)
56*8ccd4a63SDavid du Colombier 		goto Exhausted;
57*8ccd4a63SDavid du Colombier 	oldfd = f->fd;
58*8ccd4a63SDavid du Colombier 	memmove(newfd, oldfd, f->nfd*sizeof(Chan*));
59*8ccd4a63SDavid du Colombier 	f->fd = newfd;
60*8ccd4a63SDavid du Colombier 	free(oldfd);
61*8ccd4a63SDavid du Colombier 	f->nfd += DELTAFD;
62*8ccd4a63SDavid du Colombier 	if(fd > f->maxfd){
63*8ccd4a63SDavid du Colombier 		if(fd/100 > f->maxfd/100)
64*8ccd4a63SDavid du Colombier 			f->exceed = (fd/100)*100;
65*8ccd4a63SDavid du Colombier 		f->maxfd = fd;
66*8ccd4a63SDavid du Colombier 	}
67*8ccd4a63SDavid du Colombier 	return 1;
68*8ccd4a63SDavid du Colombier }
69*8ccd4a63SDavid du Colombier 
70*8ccd4a63SDavid du Colombier /*
71*8ccd4a63SDavid du Colombier  *  this assumes that the fgrp is locked
72*8ccd4a63SDavid du Colombier  */
73*8ccd4a63SDavid du Colombier int
74*8ccd4a63SDavid du Colombier findfreefd(Fgrp *f, int start)
75*8ccd4a63SDavid du Colombier {
76*8ccd4a63SDavid du Colombier 	int fd;
77*8ccd4a63SDavid du Colombier 
78*8ccd4a63SDavid du Colombier 	for(fd=start; fd<f->nfd; fd++)
79*8ccd4a63SDavid du Colombier 		if(f->fd[fd] == 0)
80*8ccd4a63SDavid du Colombier 			break;
81*8ccd4a63SDavid du Colombier 	if(fd >= f->nfd && growfd(f, fd) < 0)
82*8ccd4a63SDavid du Colombier 		return -1;
83*8ccd4a63SDavid du Colombier 	return fd;
84*8ccd4a63SDavid du Colombier }
85*8ccd4a63SDavid du Colombier 
86*8ccd4a63SDavid du Colombier int
87*8ccd4a63SDavid du Colombier newfd(Chan *c)
88*8ccd4a63SDavid du Colombier {
89*8ccd4a63SDavid du Colombier 	int fd;
90*8ccd4a63SDavid du Colombier 	Fgrp *f;
91*8ccd4a63SDavid du Colombier 
92*8ccd4a63SDavid du Colombier 	f = up->fgrp;
93*8ccd4a63SDavid du Colombier 	lock(&f->ref.lk);
94*8ccd4a63SDavid du Colombier 	fd = findfreefd(f, 0);
95*8ccd4a63SDavid du Colombier 	if(fd < 0){
96*8ccd4a63SDavid du Colombier 		unlockfgrp(f);
97*8ccd4a63SDavid du Colombier 		return -1;
98*8ccd4a63SDavid du Colombier 	}
99*8ccd4a63SDavid du Colombier 	if(fd > f->maxfd)
100*8ccd4a63SDavid du Colombier 		f->maxfd = fd;
101*8ccd4a63SDavid du Colombier 	f->fd[fd] = c;
102*8ccd4a63SDavid du Colombier 	unlockfgrp(f);
103*8ccd4a63SDavid du Colombier 	return fd;
104*8ccd4a63SDavid du Colombier }
105*8ccd4a63SDavid du Colombier 
106*8ccd4a63SDavid du Colombier int
107*8ccd4a63SDavid du Colombier newfd2(int fd[2], Chan *c[2])
108*8ccd4a63SDavid du Colombier {
109*8ccd4a63SDavid du Colombier 	Fgrp *f;
110*8ccd4a63SDavid du Colombier 
111*8ccd4a63SDavid du Colombier 	f = up->fgrp;
112*8ccd4a63SDavid du Colombier 	lock(&f->ref.lk);
113*8ccd4a63SDavid du Colombier 	fd[0] = findfreefd(f, 0);
114*8ccd4a63SDavid du Colombier 	if(fd[0] < 0){
115*8ccd4a63SDavid du Colombier 		unlockfgrp(f);
116*8ccd4a63SDavid du Colombier 		return -1;
117*8ccd4a63SDavid du Colombier 	}
118*8ccd4a63SDavid du Colombier 	fd[1] = findfreefd(f, fd[0]+1);
119*8ccd4a63SDavid du Colombier 	if(fd[1] < 0){
120*8ccd4a63SDavid du Colombier 		unlockfgrp(f);
121*8ccd4a63SDavid du Colombier 		return -1;
122*8ccd4a63SDavid du Colombier 	}
123*8ccd4a63SDavid du Colombier 	if(fd[1] > f->maxfd)
124*8ccd4a63SDavid du Colombier 		f->maxfd = fd[1];
125*8ccd4a63SDavid du Colombier 	f->fd[fd[0]] = c[0];
126*8ccd4a63SDavid du Colombier 	f->fd[fd[1]] = c[1];
127*8ccd4a63SDavid du Colombier 	unlockfgrp(f);
128*8ccd4a63SDavid du Colombier 
129*8ccd4a63SDavid du Colombier 	return 0;
130*8ccd4a63SDavid du Colombier }
131*8ccd4a63SDavid du Colombier 
132*8ccd4a63SDavid du Colombier Chan*
133*8ccd4a63SDavid du Colombier fdtochan(int fd, int mode, int chkmnt, int iref)
134*8ccd4a63SDavid du Colombier {
135*8ccd4a63SDavid du Colombier 	Chan *c;
136*8ccd4a63SDavid du Colombier 	Fgrp *f;
137*8ccd4a63SDavid du Colombier 
138*8ccd4a63SDavid du Colombier 	c = 0;
139*8ccd4a63SDavid du Colombier 	f = up->fgrp;
140*8ccd4a63SDavid du Colombier 
141*8ccd4a63SDavid du Colombier 	lock(&f->ref.lk);
142*8ccd4a63SDavid du Colombier 	if(fd<0 || f->nfd<=fd || (c = f->fd[fd])==0) {
143*8ccd4a63SDavid du Colombier 		unlock(&f->ref.lk);
144*8ccd4a63SDavid du Colombier 		error(Ebadfd);
145*8ccd4a63SDavid du Colombier 	}
146*8ccd4a63SDavid du Colombier 	if(iref)
147*8ccd4a63SDavid du Colombier 		incref(&c->ref);
148*8ccd4a63SDavid du Colombier 	unlock(&f->ref.lk);
149*8ccd4a63SDavid du Colombier 
150*8ccd4a63SDavid du Colombier 	if(chkmnt && (c->flag&CMSG)) {
151*8ccd4a63SDavid du Colombier 		if(iref)
152*8ccd4a63SDavid du Colombier 			cclose(c);
153*8ccd4a63SDavid du Colombier 		error(Ebadusefd);
154*8ccd4a63SDavid du Colombier 	}
155*8ccd4a63SDavid du Colombier 
156*8ccd4a63SDavid du Colombier 	if(mode<0 || c->mode==ORDWR)
157*8ccd4a63SDavid du Colombier 		return c;
158*8ccd4a63SDavid du Colombier 
159*8ccd4a63SDavid du Colombier 	if((mode&OTRUNC) && c->mode==OREAD) {
160*8ccd4a63SDavid du Colombier 		if(iref)
161*8ccd4a63SDavid du Colombier 			cclose(c);
162*8ccd4a63SDavid du Colombier 		error(Ebadusefd);
163*8ccd4a63SDavid du Colombier 	}
164*8ccd4a63SDavid du Colombier 
165*8ccd4a63SDavid du Colombier 	if((mode&~OTRUNC) != c->mode) {
166*8ccd4a63SDavid du Colombier 		if(iref)
167*8ccd4a63SDavid du Colombier 			cclose(c);
168*8ccd4a63SDavid du Colombier 		error(Ebadusefd);
169*8ccd4a63SDavid du Colombier 	}
170*8ccd4a63SDavid du Colombier 
171*8ccd4a63SDavid du Colombier 	return c;
172*8ccd4a63SDavid du Colombier }
173*8ccd4a63SDavid du Colombier 
174*8ccd4a63SDavid du Colombier int
175*8ccd4a63SDavid du Colombier openmode(ulong o)
176*8ccd4a63SDavid du Colombier {
177*8ccd4a63SDavid du Colombier 	o &= ~(OTRUNC|OCEXEC|ORCLOSE);
178*8ccd4a63SDavid du Colombier 	if(o > OEXEC)
179*8ccd4a63SDavid du Colombier 		error(Ebadarg);
180*8ccd4a63SDavid du Colombier 	if(o == OEXEC)
181*8ccd4a63SDavid du Colombier 		return OREAD;
182*8ccd4a63SDavid du Colombier 	return o;
183*8ccd4a63SDavid du Colombier }
184*8ccd4a63SDavid du Colombier 
185*8ccd4a63SDavid du Colombier long
186*8ccd4a63SDavid du Colombier _sysfd2path(int fd, char *buf, uint nbuf)
187*8ccd4a63SDavid du Colombier {
188*8ccd4a63SDavid du Colombier 	Chan *c;
189*8ccd4a63SDavid du Colombier 
190*8ccd4a63SDavid du Colombier 	c = fdtochan(fd, -1, 0, 1);
191*8ccd4a63SDavid du Colombier 
192*8ccd4a63SDavid du Colombier 	if(c->name == nil)
193*8ccd4a63SDavid du Colombier 		snprint(buf, nbuf, "<null>");
194*8ccd4a63SDavid du Colombier 	else
195*8ccd4a63SDavid du Colombier 		snprint(buf, nbuf, "%s", c->name->s);
196*8ccd4a63SDavid du Colombier 	cclose(c);
197*8ccd4a63SDavid du Colombier 	return 0;
198*8ccd4a63SDavid du Colombier }
199*8ccd4a63SDavid du Colombier 
200*8ccd4a63SDavid du Colombier long
201*8ccd4a63SDavid du Colombier _syspipe(int fd[2])
202*8ccd4a63SDavid du Colombier {
203*8ccd4a63SDavid du Colombier 	Chan *c[2];
204*8ccd4a63SDavid du Colombier 	Dev *d;
205*8ccd4a63SDavid du Colombier 	static char *datastr[] = {"data", "data1"};
206*8ccd4a63SDavid du Colombier 
207*8ccd4a63SDavid du Colombier 	d = devtab[devno('|', 0)];
208*8ccd4a63SDavid du Colombier 	c[0] = namec("#|", Atodir, 0, 0);
209*8ccd4a63SDavid du Colombier 	c[1] = 0;
210*8ccd4a63SDavid du Colombier 	fd[0] = -1;
211*8ccd4a63SDavid du Colombier 	fd[1] = -1;
212*8ccd4a63SDavid du Colombier 
213*8ccd4a63SDavid du Colombier 	if(waserror()){
214*8ccd4a63SDavid du Colombier 		cclose(c[0]);
215*8ccd4a63SDavid du Colombier 		if(c[1])
216*8ccd4a63SDavid du Colombier 			cclose(c[1]);
217*8ccd4a63SDavid du Colombier 		nexterror();
218*8ccd4a63SDavid du Colombier 	}
219*8ccd4a63SDavid du Colombier 	c[1] = cclone(c[0]);
220*8ccd4a63SDavid du Colombier 	if(walk(&c[0], datastr+0, 1, 1, nil) < 0)
221*8ccd4a63SDavid du Colombier 		error(Egreg);
222*8ccd4a63SDavid du Colombier 	if(walk(&c[1], datastr+1, 1, 1, nil) < 0)
223*8ccd4a63SDavid du Colombier 		error(Egreg);
224*8ccd4a63SDavid du Colombier 	c[0] = d->open(c[0], ORDWR);
225*8ccd4a63SDavid du Colombier 	c[1] = d->open(c[1], ORDWR);
226*8ccd4a63SDavid du Colombier 	if(newfd2(fd, c) < 0)
227*8ccd4a63SDavid du Colombier 		error(Enofd);
228*8ccd4a63SDavid du Colombier 	poperror();
229*8ccd4a63SDavid du Colombier 
230*8ccd4a63SDavid du Colombier 	return 0;
231*8ccd4a63SDavid du Colombier }
232*8ccd4a63SDavid du Colombier 
233*8ccd4a63SDavid du Colombier long
234*8ccd4a63SDavid du Colombier _sysdup(int fd0, int fd1)
235*8ccd4a63SDavid du Colombier {
236*8ccd4a63SDavid du Colombier 	int fd;
237*8ccd4a63SDavid du Colombier 	Chan *c, *oc;
238*8ccd4a63SDavid du Colombier 	Fgrp *f = up->fgrp;
239*8ccd4a63SDavid du Colombier 
240*8ccd4a63SDavid du Colombier 	/*
241*8ccd4a63SDavid du Colombier 	 * Close after dup'ing, so date > #d/1 works
242*8ccd4a63SDavid du Colombier 	 */
243*8ccd4a63SDavid du Colombier 	c = fdtochan(fd0, -1, 0, 1);
244*8ccd4a63SDavid du Colombier 	fd = fd1;
245*8ccd4a63SDavid du Colombier 	if(fd != -1){
246*8ccd4a63SDavid du Colombier 		lock(&f->ref.lk);
247*8ccd4a63SDavid du Colombier 		if(fd<0 || growfd(f, fd)<0) {
248*8ccd4a63SDavid du Colombier 			unlockfgrp(f);
249*8ccd4a63SDavid du Colombier 			cclose(c);
250*8ccd4a63SDavid du Colombier 			error(Ebadfd);
251*8ccd4a63SDavid du Colombier 		}
252*8ccd4a63SDavid du Colombier 		if(fd > f->maxfd)
253*8ccd4a63SDavid du Colombier 			f->maxfd = fd;
254*8ccd4a63SDavid du Colombier 
255*8ccd4a63SDavid du Colombier 		oc = f->fd[fd];
256*8ccd4a63SDavid du Colombier 		f->fd[fd] = c;
257*8ccd4a63SDavid du Colombier 		unlockfgrp(f);
258*8ccd4a63SDavid du Colombier 		if(oc)
259*8ccd4a63SDavid du Colombier 			cclose(oc);
260*8ccd4a63SDavid du Colombier 	}else{
261*8ccd4a63SDavid du Colombier 		if(waserror()) {
262*8ccd4a63SDavid du Colombier 			cclose(c);
263*8ccd4a63SDavid du Colombier 			nexterror();
264*8ccd4a63SDavid du Colombier 		}
265*8ccd4a63SDavid du Colombier 		fd = newfd(c);
266*8ccd4a63SDavid du Colombier 		if(fd < 0)
267*8ccd4a63SDavid du Colombier 			error(Enofd);
268*8ccd4a63SDavid du Colombier 		poperror();
269*8ccd4a63SDavid du Colombier 	}
270*8ccd4a63SDavid du Colombier 
271*8ccd4a63SDavid du Colombier 	return fd;
272*8ccd4a63SDavid du Colombier }
273*8ccd4a63SDavid du Colombier 
274*8ccd4a63SDavid du Colombier long
275*8ccd4a63SDavid du Colombier _sysopen(char *name, int mode)
276*8ccd4a63SDavid du Colombier {
277*8ccd4a63SDavid du Colombier 	int fd;
278*8ccd4a63SDavid du Colombier 	Chan *c = 0;
279*8ccd4a63SDavid du Colombier 
280*8ccd4a63SDavid du Colombier 	openmode(mode);	/* error check only */
281*8ccd4a63SDavid du Colombier 	if(waserror()){
282*8ccd4a63SDavid du Colombier 		if(c)
283*8ccd4a63SDavid du Colombier 			cclose(c);
284*8ccd4a63SDavid du Colombier 		nexterror();
285*8ccd4a63SDavid du Colombier 	}
286*8ccd4a63SDavid du Colombier 	c = namec(name, Aopen, mode, 0);
287*8ccd4a63SDavid du Colombier 	fd = newfd(c);
288*8ccd4a63SDavid du Colombier 	if(fd < 0)
289*8ccd4a63SDavid du Colombier 		error(Enofd);
290*8ccd4a63SDavid du Colombier 	poperror();
291*8ccd4a63SDavid du Colombier 	return fd;
292*8ccd4a63SDavid du Colombier }
293*8ccd4a63SDavid du Colombier 
294*8ccd4a63SDavid du Colombier void
295*8ccd4a63SDavid du Colombier fdclose(int fd, int flag)
296*8ccd4a63SDavid du Colombier {
297*8ccd4a63SDavid du Colombier 	int i;
298*8ccd4a63SDavid du Colombier 	Chan *c;
299*8ccd4a63SDavid du Colombier 	Fgrp *f = up->fgrp;
300*8ccd4a63SDavid du Colombier 
301*8ccd4a63SDavid du Colombier 	lock(&f->ref.lk);
302*8ccd4a63SDavid du Colombier 	c = f->fd[fd];
303*8ccd4a63SDavid du Colombier 	if(c == 0){
304*8ccd4a63SDavid du Colombier 		/* can happen for users with shared fd tables */
305*8ccd4a63SDavid du Colombier 		unlock(&f->ref.lk);
306*8ccd4a63SDavid du Colombier 		return;
307*8ccd4a63SDavid du Colombier 	}
308*8ccd4a63SDavid du Colombier 	if(flag){
309*8ccd4a63SDavid du Colombier 		if(c==0 || !(c->flag&flag)){
310*8ccd4a63SDavid du Colombier 			unlock(&f->ref.lk);
311*8ccd4a63SDavid du Colombier 			return;
312*8ccd4a63SDavid du Colombier 		}
313*8ccd4a63SDavid du Colombier 	}
314*8ccd4a63SDavid du Colombier 	f->fd[fd] = 0;
315*8ccd4a63SDavid du Colombier 	if(fd == f->maxfd)
316*8ccd4a63SDavid du Colombier 		for(i=fd; --i>=0 && f->fd[i]==0; )
317*8ccd4a63SDavid du Colombier 			f->maxfd = i;
318*8ccd4a63SDavid du Colombier 
319*8ccd4a63SDavid du Colombier 	unlock(&f->ref.lk);
320*8ccd4a63SDavid du Colombier 	cclose(c);
321*8ccd4a63SDavid du Colombier }
322*8ccd4a63SDavid du Colombier 
323*8ccd4a63SDavid du Colombier long
324*8ccd4a63SDavid du Colombier _sysclose(int fd)
325*8ccd4a63SDavid du Colombier {
326*8ccd4a63SDavid du Colombier 	fdtochan(fd, -1, 0, 0);
327*8ccd4a63SDavid du Colombier 	fdclose(fd, 0);
328*8ccd4a63SDavid du Colombier 
329*8ccd4a63SDavid du Colombier 	return 0;
330*8ccd4a63SDavid du Colombier }
331*8ccd4a63SDavid du Colombier 
332*8ccd4a63SDavid du Colombier long
333*8ccd4a63SDavid du Colombier unionread(Chan *c, void *va, long n)
334*8ccd4a63SDavid du Colombier {
335*8ccd4a63SDavid du Colombier 	int i;
336*8ccd4a63SDavid du Colombier 	long nr;
337*8ccd4a63SDavid du Colombier 	Mhead *m;
338*8ccd4a63SDavid du Colombier 	Mount *mount;
339*8ccd4a63SDavid du Colombier 
340*8ccd4a63SDavid du Colombier 	qlock(&c->umqlock);
341*8ccd4a63SDavid du Colombier 	m = c->umh;
342*8ccd4a63SDavid du Colombier 	rlock(&m->lock);
343*8ccd4a63SDavid du Colombier 	mount = m->mount;
344*8ccd4a63SDavid du Colombier 	/* bring mount in sync with c->uri and c->umc */
345*8ccd4a63SDavid du Colombier 	for(i = 0; mount != nil && i < c->uri; i++)
346*8ccd4a63SDavid du Colombier 		mount = mount->next;
347*8ccd4a63SDavid du Colombier 
348*8ccd4a63SDavid du Colombier 	nr = 0;
349*8ccd4a63SDavid du Colombier 	while(mount != nil) {
350*8ccd4a63SDavid du Colombier 		/* Error causes component of union to be skipped */
351*8ccd4a63SDavid du Colombier 		if(mount->to && !waserror()) {
352*8ccd4a63SDavid du Colombier 			if(c->umc == nil){
353*8ccd4a63SDavid du Colombier 				c->umc = cclone(mount->to);
354*8ccd4a63SDavid du Colombier 				c->umc = devtab[c->umc->type]->open(c->umc, OREAD);
355*8ccd4a63SDavid du Colombier 			}
356*8ccd4a63SDavid du Colombier 
357*8ccd4a63SDavid du Colombier 			nr = devtab[c->umc->type]->read(c->umc, va, n, c->umc->offset);
358*8ccd4a63SDavid du Colombier 			c->umc->offset += nr;
359*8ccd4a63SDavid du Colombier 			poperror();
360*8ccd4a63SDavid du Colombier 		}
361*8ccd4a63SDavid du Colombier 		if(nr > 0)
362*8ccd4a63SDavid du Colombier 			break;
363*8ccd4a63SDavid du Colombier 
364*8ccd4a63SDavid du Colombier 		/* Advance to next element */
365*8ccd4a63SDavid du Colombier 		c->uri++;
366*8ccd4a63SDavid du Colombier 		if(c->umc) {
367*8ccd4a63SDavid du Colombier 			cclose(c->umc);
368*8ccd4a63SDavid du Colombier 			c->umc = nil;
369*8ccd4a63SDavid du Colombier 		}
370*8ccd4a63SDavid du Colombier 		mount = mount->next;
371*8ccd4a63SDavid du Colombier 	}
372*8ccd4a63SDavid du Colombier 	runlock(&m->lock);
373*8ccd4a63SDavid du Colombier 	qunlock(&c->umqlock);
374*8ccd4a63SDavid du Colombier 	return nr;
375*8ccd4a63SDavid du Colombier }
376*8ccd4a63SDavid du Colombier 
377*8ccd4a63SDavid du Colombier static long
378*8ccd4a63SDavid du Colombier kread(int fd, void *buf, long n, vlong *offp)
379*8ccd4a63SDavid du Colombier {
380*8ccd4a63SDavid du Colombier 	int dir;
381*8ccd4a63SDavid du Colombier 	Chan *c;
382*8ccd4a63SDavid du Colombier 	vlong off;
383*8ccd4a63SDavid du Colombier 
384*8ccd4a63SDavid du Colombier 	c = fdtochan(fd, OREAD, 1, 1);
385*8ccd4a63SDavid du Colombier 
386*8ccd4a63SDavid du Colombier 	if(waserror()) {
387*8ccd4a63SDavid du Colombier 		cclose(c);
388*8ccd4a63SDavid du Colombier 		nexterror();
389*8ccd4a63SDavid du Colombier 	}
390*8ccd4a63SDavid du Colombier 
391*8ccd4a63SDavid du Colombier 	dir = c->qid.type&QTDIR;
392*8ccd4a63SDavid du Colombier 	/*
393*8ccd4a63SDavid du Colombier 	 * The offset is passed through on directories, normally. sysseek complains but
394*8ccd4a63SDavid du Colombier 	 * pread is used by servers and e.g. exportfs that shouldn't need to worry about this issue.
395*8ccd4a63SDavid du Colombier 	 */
396*8ccd4a63SDavid du Colombier 
397*8ccd4a63SDavid du Colombier 	if(offp == nil)	/* use and maintain channel's offset */
398*8ccd4a63SDavid du Colombier 		off = c->offset;
399*8ccd4a63SDavid du Colombier 	else
400*8ccd4a63SDavid du Colombier 		off = *offp;
401*8ccd4a63SDavid du Colombier 
402*8ccd4a63SDavid du Colombier 	if(off < 0)
403*8ccd4a63SDavid du Colombier 		error(Enegoff);
404*8ccd4a63SDavid du Colombier 
405*8ccd4a63SDavid du Colombier 	if(dir && c->umh)
406*8ccd4a63SDavid du Colombier 		n = unionread(c, buf, n);
407*8ccd4a63SDavid du Colombier 	else
408*8ccd4a63SDavid du Colombier 		n = devtab[c->type]->read(c, buf, n, off);
409*8ccd4a63SDavid du Colombier 
410*8ccd4a63SDavid du Colombier 	if(offp == nil){
411*8ccd4a63SDavid du Colombier 		lock(&c->ref.lk);
412*8ccd4a63SDavid du Colombier 		c->offset += n;
413*8ccd4a63SDavid du Colombier 		unlock(&c->ref.lk);
414*8ccd4a63SDavid du Colombier 	}
415*8ccd4a63SDavid du Colombier 
416*8ccd4a63SDavid du Colombier 	poperror();
417*8ccd4a63SDavid du Colombier 	cclose(c);
418*8ccd4a63SDavid du Colombier 
419*8ccd4a63SDavid du Colombier 	return n;
420*8ccd4a63SDavid du Colombier }
421*8ccd4a63SDavid du Colombier 
422*8ccd4a63SDavid du Colombier /* name conflicts with netbsd
423*8ccd4a63SDavid du Colombier long
424*8ccd4a63SDavid du Colombier _sys_read(int fd, void *buf, long n)
425*8ccd4a63SDavid du Colombier {
426*8ccd4a63SDavid du Colombier 	return kread(fd, buf, n, nil);
427*8ccd4a63SDavid du Colombier }
428*8ccd4a63SDavid du Colombier */
429*8ccd4a63SDavid du Colombier 
430*8ccd4a63SDavid du Colombier long
431*8ccd4a63SDavid du Colombier _syspread(int fd, void *buf, long n, vlong off)
432*8ccd4a63SDavid du Colombier {
433*8ccd4a63SDavid du Colombier 	if(off == ((uvlong) ~0))
434*8ccd4a63SDavid du Colombier 		return kread(fd, buf, n, nil);
435*8ccd4a63SDavid du Colombier 	return kread(fd, buf, n, &off);
436*8ccd4a63SDavid du Colombier }
437*8ccd4a63SDavid du Colombier 
438*8ccd4a63SDavid du Colombier static long
439*8ccd4a63SDavid du Colombier kwrite(int fd, void *buf, long nn, vlong *offp)
440*8ccd4a63SDavid du Colombier {
441*8ccd4a63SDavid du Colombier 	Chan *c;
442*8ccd4a63SDavid du Colombier 	long m, n;
443*8ccd4a63SDavid du Colombier 	vlong off;
444*8ccd4a63SDavid du Colombier 
445*8ccd4a63SDavid du Colombier 	n = 0;
446*8ccd4a63SDavid du Colombier 	c = fdtochan(fd, OWRITE, 1, 1);
447*8ccd4a63SDavid du Colombier 	if(waserror()) {
448*8ccd4a63SDavid du Colombier 		if(offp == nil){
449*8ccd4a63SDavid du Colombier 			lock(&c->ref.lk);
450*8ccd4a63SDavid du Colombier 			c->offset -= n;
451*8ccd4a63SDavid du Colombier 			unlock(&c->ref.lk);
452*8ccd4a63SDavid du Colombier 		}
453*8ccd4a63SDavid du Colombier 		cclose(c);
454*8ccd4a63SDavid du Colombier 		nexterror();
455*8ccd4a63SDavid du Colombier 	}
456*8ccd4a63SDavid du Colombier 
457*8ccd4a63SDavid du Colombier 	if(c->qid.type & QTDIR)
458*8ccd4a63SDavid du Colombier 		error(Eisdir);
459*8ccd4a63SDavid du Colombier 
460*8ccd4a63SDavid du Colombier 	n = nn;
461*8ccd4a63SDavid du Colombier 
462*8ccd4a63SDavid du Colombier 	if(offp == nil){	/* use and maintain channel's offset */
463*8ccd4a63SDavid du Colombier 		lock(&c->ref.lk);
464*8ccd4a63SDavid du Colombier 		off = c->offset;
465*8ccd4a63SDavid du Colombier 		c->offset += n;
466*8ccd4a63SDavid du Colombier 		unlock(&c->ref.lk);
467*8ccd4a63SDavid du Colombier 	}else
468*8ccd4a63SDavid du Colombier 		off = *offp;
469*8ccd4a63SDavid du Colombier 
470*8ccd4a63SDavid du Colombier 	if(off < 0)
471*8ccd4a63SDavid du Colombier 		error(Enegoff);
472*8ccd4a63SDavid du Colombier 
473*8ccd4a63SDavid du Colombier 	m = devtab[c->type]->write(c, buf, n, off);
474*8ccd4a63SDavid du Colombier 
475*8ccd4a63SDavid du Colombier 	if(offp == nil && m < n){
476*8ccd4a63SDavid du Colombier 		lock(&c->ref.lk);
477*8ccd4a63SDavid du Colombier 		c->offset -= n - m;
478*8ccd4a63SDavid du Colombier 		unlock(&c->ref.lk);
479*8ccd4a63SDavid du Colombier 	}
480*8ccd4a63SDavid du Colombier 
481*8ccd4a63SDavid du Colombier 	poperror();
482*8ccd4a63SDavid du Colombier 	cclose(c);
483*8ccd4a63SDavid du Colombier 
484*8ccd4a63SDavid du Colombier 	return m;
485*8ccd4a63SDavid du Colombier }
486*8ccd4a63SDavid du Colombier 
487*8ccd4a63SDavid du Colombier long
488*8ccd4a63SDavid du Colombier sys_write(int fd, void *buf, long n)
489*8ccd4a63SDavid du Colombier {
490*8ccd4a63SDavid du Colombier 	return kwrite(fd, buf, n, nil);
491*8ccd4a63SDavid du Colombier }
492*8ccd4a63SDavid du Colombier 
493*8ccd4a63SDavid du Colombier long
494*8ccd4a63SDavid du Colombier _syspwrite(int fd, void *buf, long n, vlong off)
495*8ccd4a63SDavid du Colombier {
496*8ccd4a63SDavid du Colombier 	if(off == ((uvlong) ~0))
497*8ccd4a63SDavid du Colombier 		return kwrite(fd, buf, n, nil);
498*8ccd4a63SDavid du Colombier 	return kwrite(fd, buf, n, &off);
499*8ccd4a63SDavid du Colombier }
500*8ccd4a63SDavid du Colombier 
501*8ccd4a63SDavid du Colombier static vlong
502*8ccd4a63SDavid du Colombier _sysseek(int fd, vlong off, int whence)
503*8ccd4a63SDavid du Colombier {
504*8ccd4a63SDavid du Colombier 	Chan *c;
505*8ccd4a63SDavid du Colombier 	uchar buf[sizeof(Dir)+100];
506*8ccd4a63SDavid du Colombier 	Dir dir;
507*8ccd4a63SDavid du Colombier 	int n;
508*8ccd4a63SDavid du Colombier 
509*8ccd4a63SDavid du Colombier 	c = fdtochan(fd, -1, 1, 1);
510*8ccd4a63SDavid du Colombier 	if(waserror()){
511*8ccd4a63SDavid du Colombier 		cclose(c);
512*8ccd4a63SDavid du Colombier 		nexterror();
513*8ccd4a63SDavid du Colombier 	}
514*8ccd4a63SDavid du Colombier 	if(devtab[c->type]->dc == '|')
515*8ccd4a63SDavid du Colombier 		error(Eisstream);
516*8ccd4a63SDavid du Colombier 
517*8ccd4a63SDavid du Colombier 	switch(whence){
518*8ccd4a63SDavid du Colombier 	case 0:
519*8ccd4a63SDavid du Colombier 		if((c->qid.type & QTDIR) && off != 0)
520*8ccd4a63SDavid du Colombier 			error(Eisdir);
521*8ccd4a63SDavid du Colombier 		if(off < 0)
522*8ccd4a63SDavid du Colombier 			error(Enegoff);
523*8ccd4a63SDavid du Colombier 		c->offset = off;
524*8ccd4a63SDavid du Colombier 		break;
525*8ccd4a63SDavid du Colombier 
526*8ccd4a63SDavid du Colombier 	case 1:
527*8ccd4a63SDavid du Colombier 		if(c->qid.type & QTDIR)
528*8ccd4a63SDavid du Colombier 			error(Eisdir);
529*8ccd4a63SDavid du Colombier 		lock(&c->ref.lk);	/* lock for read/write update */
530*8ccd4a63SDavid du Colombier 		off = off + c->offset;
531*8ccd4a63SDavid du Colombier 		if(off < 0)
532*8ccd4a63SDavid du Colombier 			error(Enegoff);
533*8ccd4a63SDavid du Colombier 		c->offset = off;
534*8ccd4a63SDavid du Colombier 		unlock(&c->ref.lk);
535*8ccd4a63SDavid du Colombier 		break;
536*8ccd4a63SDavid du Colombier 
537*8ccd4a63SDavid du Colombier 	case 2:
538*8ccd4a63SDavid du Colombier 		if(c->qid.type & QTDIR)
539*8ccd4a63SDavid du Colombier 			error(Eisdir);
540*8ccd4a63SDavid du Colombier 		n = devtab[c->type]->stat(c, buf, sizeof buf);
541*8ccd4a63SDavid du Colombier 		if(convM2D(buf, n, &dir, nil) == 0)
542*8ccd4a63SDavid du Colombier 			error("internal error: stat error in seek");
543*8ccd4a63SDavid du Colombier 		off = dir.length + off;
544*8ccd4a63SDavid du Colombier 		if(off < 0)
545*8ccd4a63SDavid du Colombier 			error(Enegoff);
546*8ccd4a63SDavid du Colombier 		c->offset = off;
547*8ccd4a63SDavid du Colombier 		break;
548*8ccd4a63SDavid du Colombier 
549*8ccd4a63SDavid du Colombier 	default:
550*8ccd4a63SDavid du Colombier 		error(Ebadarg);
551*8ccd4a63SDavid du Colombier 	}
552*8ccd4a63SDavid du Colombier 	c->uri = 0;
553*8ccd4a63SDavid du Colombier 	c->dri = 0;
554*8ccd4a63SDavid du Colombier 	cclose(c);
555*8ccd4a63SDavid du Colombier 	poperror();
556*8ccd4a63SDavid du Colombier 	return off;
557*8ccd4a63SDavid du Colombier }
558*8ccd4a63SDavid du Colombier 
559*8ccd4a63SDavid du Colombier void
560*8ccd4a63SDavid du Colombier validstat(uchar *s, int n)
561*8ccd4a63SDavid du Colombier {
562*8ccd4a63SDavid du Colombier 	int m;
563*8ccd4a63SDavid du Colombier 	char buf[64];
564*8ccd4a63SDavid du Colombier 
565*8ccd4a63SDavid du Colombier 	if(statcheck(s, n) < 0)
566*8ccd4a63SDavid du Colombier 		error(Ebadstat);
567*8ccd4a63SDavid du Colombier 	/* verify that name entry is acceptable */
568*8ccd4a63SDavid du Colombier 	s += STATFIXLEN - 4*BIT16SZ;	/* location of first string */
569*8ccd4a63SDavid du Colombier 	/*
570*8ccd4a63SDavid du Colombier 	 * s now points at count for first string.
571*8ccd4a63SDavid du Colombier 	 * if it's too long, let the server decide; this is
572*8ccd4a63SDavid du Colombier 	 * only for his protection anyway. otherwise
573*8ccd4a63SDavid du Colombier 	 * we'd have to allocate and waserror.
574*8ccd4a63SDavid du Colombier 	 */
575*8ccd4a63SDavid du Colombier 	m = GBIT16(s);
576*8ccd4a63SDavid du Colombier 	s += BIT16SZ;
577*8ccd4a63SDavid du Colombier 	if(m+1 > sizeof buf)
578*8ccd4a63SDavid du Colombier 		return;
579*8ccd4a63SDavid du Colombier 	memmove(buf, s, m);
580*8ccd4a63SDavid du Colombier 	buf[m] = '\0';
581*8ccd4a63SDavid du Colombier 	/* name could be '/' */
582*8ccd4a63SDavid du Colombier 	if(strcmp(buf, "/") != 0)
583*8ccd4a63SDavid du Colombier 		validname(buf, 0);
584*8ccd4a63SDavid du Colombier }
585*8ccd4a63SDavid du Colombier 
586*8ccd4a63SDavid du Colombier long
587*8ccd4a63SDavid du Colombier _sysfstat(int fd, void *buf, long n)
588*8ccd4a63SDavid du Colombier {
589*8ccd4a63SDavid du Colombier 	Chan *c;
590*8ccd4a63SDavid du Colombier 	uint l;
591*8ccd4a63SDavid du Colombier 
592*8ccd4a63SDavid du Colombier 	l = n;
593*8ccd4a63SDavid du Colombier 	validaddr(buf, l, 1);
594*8ccd4a63SDavid du Colombier 	c = fdtochan(fd, -1, 0, 1);
595*8ccd4a63SDavid du Colombier 	if(waserror()) {
596*8ccd4a63SDavid du Colombier 		cclose(c);
597*8ccd4a63SDavid du Colombier 		nexterror();
598*8ccd4a63SDavid du Colombier 	}
599*8ccd4a63SDavid du Colombier 	l = devtab[c->type]->stat(c, buf, l);
600*8ccd4a63SDavid du Colombier 	poperror();
601*8ccd4a63SDavid du Colombier 	cclose(c);
602*8ccd4a63SDavid du Colombier 	return l;
603*8ccd4a63SDavid du Colombier }
604*8ccd4a63SDavid du Colombier 
605*8ccd4a63SDavid du Colombier long
606*8ccd4a63SDavid du Colombier _sysstat(char *name, void *buf, long n)
607*8ccd4a63SDavid du Colombier {
608*8ccd4a63SDavid du Colombier 	Chan *c;
609*8ccd4a63SDavid du Colombier 	uint l;
610*8ccd4a63SDavid du Colombier 
611*8ccd4a63SDavid du Colombier 	l = n;
612*8ccd4a63SDavid du Colombier 	validaddr(buf, l, 1);
613*8ccd4a63SDavid du Colombier 	validaddr(name, 1, 0);
614*8ccd4a63SDavid du Colombier 	c = namec(name, Aaccess, 0, 0);
615*8ccd4a63SDavid du Colombier 	if(waserror()){
616*8ccd4a63SDavid du Colombier 		cclose(c);
617*8ccd4a63SDavid du Colombier 		nexterror();
618*8ccd4a63SDavid du Colombier 	}
619*8ccd4a63SDavid du Colombier 	l = devtab[c->type]->stat(c, buf, l);
620*8ccd4a63SDavid du Colombier 	poperror();
621*8ccd4a63SDavid du Colombier 	cclose(c);
622*8ccd4a63SDavid du Colombier 	return l;
623*8ccd4a63SDavid du Colombier }
624*8ccd4a63SDavid du Colombier 
625*8ccd4a63SDavid du Colombier long
626*8ccd4a63SDavid du Colombier _syschdir(char *name)
627*8ccd4a63SDavid du Colombier {
628*8ccd4a63SDavid du Colombier 	Chan *c;
629*8ccd4a63SDavid du Colombier 
630*8ccd4a63SDavid du Colombier 	validaddr(name, 1, 0);
631*8ccd4a63SDavid du Colombier 
632*8ccd4a63SDavid du Colombier 	c = namec(name, Atodir, 0, 0);
633*8ccd4a63SDavid du Colombier 	cclose(up->dot);
634*8ccd4a63SDavid du Colombier 	up->dot = c;
635*8ccd4a63SDavid du Colombier 	return 0;
636*8ccd4a63SDavid du Colombier }
637*8ccd4a63SDavid du Colombier 
638*8ccd4a63SDavid du Colombier long
639*8ccd4a63SDavid du Colombier bindmount(int ismount, int fd, int afd, char* arg0, char* arg1, ulong flag, char* spec)
640*8ccd4a63SDavid du Colombier {
641*8ccd4a63SDavid du Colombier 	int ret;
642*8ccd4a63SDavid du Colombier 	Chan *c0, *c1, *ac, *bc;
643*8ccd4a63SDavid du Colombier 	struct{
644*8ccd4a63SDavid du Colombier 		Chan	*chan;
645*8ccd4a63SDavid du Colombier 		Chan	*authchan;
646*8ccd4a63SDavid du Colombier 		char	*spec;
647*8ccd4a63SDavid du Colombier 		int	flags;
648*8ccd4a63SDavid du Colombier 	}bogus;
649*8ccd4a63SDavid du Colombier 
650*8ccd4a63SDavid du Colombier 	if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER))
651*8ccd4a63SDavid du Colombier 		error(Ebadarg);
652*8ccd4a63SDavid du Colombier 
653*8ccd4a63SDavid du Colombier 	bogus.flags = flag & MCACHE;
654*8ccd4a63SDavid du Colombier 
655*8ccd4a63SDavid du Colombier 	if(ismount){
656*8ccd4a63SDavid du Colombier 		if(up->pgrp->noattach)
657*8ccd4a63SDavid du Colombier 			error(Enoattach);
658*8ccd4a63SDavid du Colombier 
659*8ccd4a63SDavid du Colombier 		ac = nil;
660*8ccd4a63SDavid du Colombier 		bc = fdtochan(fd, ORDWR, 0, 1);
661*8ccd4a63SDavid du Colombier 		if(waserror()) {
662*8ccd4a63SDavid du Colombier 			if(ac)
663*8ccd4a63SDavid du Colombier 				cclose(ac);
664*8ccd4a63SDavid du Colombier 			cclose(bc);
665*8ccd4a63SDavid du Colombier 			nexterror();
666*8ccd4a63SDavid du Colombier 		}
667*8ccd4a63SDavid du Colombier 
668*8ccd4a63SDavid du Colombier 		if(afd >= 0)
669*8ccd4a63SDavid du Colombier 			ac = fdtochan(afd, ORDWR, 0, 1);
670*8ccd4a63SDavid du Colombier 
671*8ccd4a63SDavid du Colombier 		bogus.chan = bc;
672*8ccd4a63SDavid du Colombier 		bogus.authchan = ac;
673*8ccd4a63SDavid du Colombier 
674*8ccd4a63SDavid du Colombier 		validaddr((ulong)spec, 1, 0);
675*8ccd4a63SDavid du Colombier 		bogus.spec = spec;
676*8ccd4a63SDavid du Colombier 		if(waserror())
677*8ccd4a63SDavid du Colombier 			error(Ebadspec);
678*8ccd4a63SDavid du Colombier 		validname(spec, 1);
679*8ccd4a63SDavid du Colombier 		poperror();
680*8ccd4a63SDavid du Colombier 
681*8ccd4a63SDavid du Colombier 		ret = devno('M', 0);
682*8ccd4a63SDavid du Colombier 		c0 = devtab[ret]->attach((char*)&bogus);
683*8ccd4a63SDavid du Colombier 
684*8ccd4a63SDavid du Colombier 		poperror();
685*8ccd4a63SDavid du Colombier 		if(ac)
686*8ccd4a63SDavid du Colombier 			cclose(ac);
687*8ccd4a63SDavid du Colombier 		cclose(bc);
688*8ccd4a63SDavid du Colombier 	}else{
689*8ccd4a63SDavid du Colombier 		bogus.spec = 0;
690*8ccd4a63SDavid du Colombier 		validaddr((ulong)arg0, 1, 0);
691*8ccd4a63SDavid du Colombier 		c0 = namec(arg0, Abind, 0, 0);
692*8ccd4a63SDavid du Colombier 	}
693*8ccd4a63SDavid du Colombier 
694*8ccd4a63SDavid du Colombier 	if(waserror()){
695*8ccd4a63SDavid du Colombier 		cclose(c0);
696*8ccd4a63SDavid du Colombier 		nexterror();
697*8ccd4a63SDavid du Colombier 	}
698*8ccd4a63SDavid du Colombier 
699*8ccd4a63SDavid du Colombier 	validaddr((ulong)arg1, 1, 0);
700*8ccd4a63SDavid du Colombier 	c1 = namec(arg1, Amount, 0, 0);
701*8ccd4a63SDavid du Colombier 	if(waserror()){
702*8ccd4a63SDavid du Colombier 		cclose(c1);
703*8ccd4a63SDavid du Colombier 		nexterror();
704*8ccd4a63SDavid du Colombier 	}
705*8ccd4a63SDavid du Colombier 
706*8ccd4a63SDavid du Colombier 	ret = cmount(&c0, c1, flag, bogus.spec);
707*8ccd4a63SDavid du Colombier 
708*8ccd4a63SDavid du Colombier 	poperror();
709*8ccd4a63SDavid du Colombier 	cclose(c1);
710*8ccd4a63SDavid du Colombier 	poperror();
711*8ccd4a63SDavid du Colombier 	cclose(c0);
712*8ccd4a63SDavid du Colombier 	if(ismount)
713*8ccd4a63SDavid du Colombier 		fdclose(fd, 0);
714*8ccd4a63SDavid du Colombier 
715*8ccd4a63SDavid du Colombier 	return ret;
716*8ccd4a63SDavid du Colombier }
717*8ccd4a63SDavid du Colombier 
718*8ccd4a63SDavid du Colombier long
719*8ccd4a63SDavid du Colombier _sysbind(char *old, char *new, int flag)
720*8ccd4a63SDavid du Colombier {
721*8ccd4a63SDavid du Colombier 	return bindmount(0, -1, -1, old, new, flag, nil);
722*8ccd4a63SDavid du Colombier }
723*8ccd4a63SDavid du Colombier 
724*8ccd4a63SDavid du Colombier long
725*8ccd4a63SDavid du Colombier _sysmount(int fd, int afd, char *new, int flag, char *spec)
726*8ccd4a63SDavid du Colombier {
727*8ccd4a63SDavid du Colombier 	return bindmount(1, fd, afd, nil, new, flag, spec);
728*8ccd4a63SDavid du Colombier }
729*8ccd4a63SDavid du Colombier 
730*8ccd4a63SDavid du Colombier long
731*8ccd4a63SDavid du Colombier _sysunmount(char *old, char *new)
732*8ccd4a63SDavid du Colombier {
733*8ccd4a63SDavid du Colombier 	Chan *cmount, *cmounted;
734*8ccd4a63SDavid du Colombier 
735*8ccd4a63SDavid du Colombier 	cmounted = 0;
736*8ccd4a63SDavid du Colombier 
737*8ccd4a63SDavid du Colombier 	cmount = namec(new, Amount, 0, 0);
738*8ccd4a63SDavid du Colombier 
739*8ccd4a63SDavid du Colombier 	if(old) {
740*8ccd4a63SDavid du Colombier 		if(waserror()) {
741*8ccd4a63SDavid du Colombier 			cclose(cmount);
742*8ccd4a63SDavid du Colombier 			nexterror();
743*8ccd4a63SDavid du Colombier 		}
744*8ccd4a63SDavid du Colombier 		validaddr(old, 1, 0);
745*8ccd4a63SDavid du Colombier 		/*
746*8ccd4a63SDavid du Colombier 		 * This has to be namec(..., Aopen, ...) because
747*8ccd4a63SDavid du Colombier 		 * if arg[0] is something like /srv/cs or /fd/0,
748*8ccd4a63SDavid du Colombier 		 * opening it is the only way to get at the real
749*8ccd4a63SDavid du Colombier 		 * Chan underneath.
750*8ccd4a63SDavid du Colombier 		 */
751*8ccd4a63SDavid du Colombier 		cmounted = namec(old, Aopen, OREAD, 0);
752*8ccd4a63SDavid du Colombier 		poperror();
753*8ccd4a63SDavid du Colombier 	}
754*8ccd4a63SDavid du Colombier 
755*8ccd4a63SDavid du Colombier 	if(waserror()) {
756*8ccd4a63SDavid du Colombier 		cclose(cmount);
757*8ccd4a63SDavid du Colombier 		if(cmounted)
758*8ccd4a63SDavid du Colombier 			cclose(cmounted);
759*8ccd4a63SDavid du Colombier 		nexterror();
760*8ccd4a63SDavid du Colombier 	}
761*8ccd4a63SDavid du Colombier 
762*8ccd4a63SDavid du Colombier 	cunmount(cmount, cmounted);
763*8ccd4a63SDavid du Colombier 	cclose(cmount);
764*8ccd4a63SDavid du Colombier 	if(cmounted)
765*8ccd4a63SDavid du Colombier 		cclose(cmounted);
766*8ccd4a63SDavid du Colombier 	poperror();
767*8ccd4a63SDavid du Colombier 	return 0;
768*8ccd4a63SDavid du Colombier }
769*8ccd4a63SDavid du Colombier 
770*8ccd4a63SDavid du Colombier long
771*8ccd4a63SDavid du Colombier _syscreate(char *name, int mode, ulong perm)
772*8ccd4a63SDavid du Colombier {
773*8ccd4a63SDavid du Colombier 	int fd;
774*8ccd4a63SDavid du Colombier 	Chan *c = 0;
775*8ccd4a63SDavid du Colombier 
776*8ccd4a63SDavid du Colombier 	openmode(mode&~OEXCL);	/* error check only; OEXCL okay here */
777*8ccd4a63SDavid du Colombier 	if(waserror()) {
778*8ccd4a63SDavid du Colombier 		if(c)
779*8ccd4a63SDavid du Colombier 			cclose(c);
780*8ccd4a63SDavid du Colombier 		nexterror();
781*8ccd4a63SDavid du Colombier 	}
782*8ccd4a63SDavid du Colombier 	validaddr(name, 1, 0);
783*8ccd4a63SDavid du Colombier 	c = namec(name, Acreate, mode, perm);
784*8ccd4a63SDavid du Colombier 	fd = newfd(c);
785*8ccd4a63SDavid du Colombier 	if(fd < 0)
786*8ccd4a63SDavid du Colombier 		error(Enofd);
787*8ccd4a63SDavid du Colombier 	poperror();
788*8ccd4a63SDavid du Colombier 	return fd;
789*8ccd4a63SDavid du Colombier }
790*8ccd4a63SDavid du Colombier 
791*8ccd4a63SDavid du Colombier long
792*8ccd4a63SDavid du Colombier _sysremove(char *name)
793*8ccd4a63SDavid du Colombier {
794*8ccd4a63SDavid du Colombier 	Chan *c;
795*8ccd4a63SDavid du Colombier 
796*8ccd4a63SDavid du Colombier 	c = namec(name, Aremove, 0, 0);
797*8ccd4a63SDavid du Colombier 	if(waserror()){
798*8ccd4a63SDavid du Colombier 		c->type = 0;	/* see below */
799*8ccd4a63SDavid du Colombier 		cclose(c);
800*8ccd4a63SDavid du Colombier 		nexterror();
801*8ccd4a63SDavid du Colombier 	}
802*8ccd4a63SDavid du Colombier 	devtab[c->type]->remove(c);
803*8ccd4a63SDavid du Colombier 	/*
804*8ccd4a63SDavid du Colombier 	 * Remove clunks the fid, but we need to recover the Chan
805*8ccd4a63SDavid du Colombier 	 * so fake it up.  rootclose() is known to be a nop.
806*8ccd4a63SDavid du Colombier 	 */
807*8ccd4a63SDavid du Colombier 	c->type = 0;
808*8ccd4a63SDavid du Colombier 	poperror();
809*8ccd4a63SDavid du Colombier 	cclose(c);
810*8ccd4a63SDavid du Colombier 	return 0;
811*8ccd4a63SDavid du Colombier }
812*8ccd4a63SDavid du Colombier 
813*8ccd4a63SDavid du Colombier long
814*8ccd4a63SDavid du Colombier _syswstat(char *name, void *buf, long n)
815*8ccd4a63SDavid du Colombier {
816*8ccd4a63SDavid du Colombier 	Chan *c;
817*8ccd4a63SDavid du Colombier 	uint l;
818*8ccd4a63SDavid du Colombier 
819*8ccd4a63SDavid du Colombier 	l = n;
820*8ccd4a63SDavid du Colombier 	validstat(buf, l);
821*8ccd4a63SDavid du Colombier 	validaddr(name, 1, 0);
822*8ccd4a63SDavid du Colombier 	c = namec(name, Aaccess, 0, 0);
823*8ccd4a63SDavid du Colombier 	if(waserror()){
824*8ccd4a63SDavid du Colombier 		cclose(c);
825*8ccd4a63SDavid du Colombier 		nexterror();
826*8ccd4a63SDavid du Colombier 	}
827*8ccd4a63SDavid du Colombier 	l = devtab[c->type]->wstat(c, buf, l);
828*8ccd4a63SDavid du Colombier 	poperror();
829*8ccd4a63SDavid du Colombier 	cclose(c);
830*8ccd4a63SDavid du Colombier 	return l;
831*8ccd4a63SDavid du Colombier }
832*8ccd4a63SDavid du Colombier 
833*8ccd4a63SDavid du Colombier long
834*8ccd4a63SDavid du Colombier _sysfwstat(int fd, void *buf, long n)
835*8ccd4a63SDavid du Colombier {
836*8ccd4a63SDavid du Colombier 	Chan *c;
837*8ccd4a63SDavid du Colombier 	uint l;
838*8ccd4a63SDavid du Colombier 
839*8ccd4a63SDavid du Colombier 	l = n;
840*8ccd4a63SDavid du Colombier 	validaddr(buf, l, 0);
841*8ccd4a63SDavid du Colombier 	validstat(buf, l);
842*8ccd4a63SDavid du Colombier 	c = fdtochan(fd, -1, 1, 1);
843*8ccd4a63SDavid du Colombier 	if(waserror()) {
844*8ccd4a63SDavid du Colombier 		cclose(c);
845*8ccd4a63SDavid du Colombier 		nexterror();
846*8ccd4a63SDavid du Colombier 	}
847*8ccd4a63SDavid du Colombier 	l = devtab[c->type]->wstat(c, buf, l);
848*8ccd4a63SDavid du Colombier 	poperror();
849*8ccd4a63SDavid du Colombier 	cclose(c);
850*8ccd4a63SDavid du Colombier 	return l;
851*8ccd4a63SDavid du Colombier }
852*8ccd4a63SDavid du Colombier 
853*8ccd4a63SDavid du Colombier 
854*8ccd4a63SDavid du Colombier static void
855*8ccd4a63SDavid du Colombier starterror(void)
856*8ccd4a63SDavid du Colombier {
857*8ccd4a63SDavid du Colombier 	assert(up->nerrlab == 0);
858*8ccd4a63SDavid du Colombier }
859*8ccd4a63SDavid du Colombier 
860*8ccd4a63SDavid du Colombier static void
861*8ccd4a63SDavid du Colombier _syserror(void)
862*8ccd4a63SDavid du Colombier {
863*8ccd4a63SDavid du Colombier 	char *p;
864*8ccd4a63SDavid du Colombier 
865*8ccd4a63SDavid du Colombier 	p = up->syserrstr;
866*8ccd4a63SDavid du Colombier 	up->syserrstr = up->errstr;
867*8ccd4a63SDavid du Colombier 	up->errstr = p;
868*8ccd4a63SDavid du Colombier }
869*8ccd4a63SDavid du Colombier 
870*8ccd4a63SDavid du Colombier static void
871*8ccd4a63SDavid du Colombier enderror(void)
872*8ccd4a63SDavid du Colombier {
873*8ccd4a63SDavid du Colombier 	assert(up->nerrlab == 1);
874*8ccd4a63SDavid du Colombier 	poperror();
875*8ccd4a63SDavid du Colombier }
876*8ccd4a63SDavid du Colombier 
877*8ccd4a63SDavid du Colombier int
878*8ccd4a63SDavid du Colombier sysbind(char *old, char *new, int flag)
879*8ccd4a63SDavid du Colombier {
880*8ccd4a63SDavid du Colombier 	int n;
881*8ccd4a63SDavid du Colombier 
882*8ccd4a63SDavid du Colombier 	starterror();
883*8ccd4a63SDavid du Colombier 	if(waserror()){
884*8ccd4a63SDavid du Colombier 		_syserror();
885*8ccd4a63SDavid du Colombier 		return -1;
886*8ccd4a63SDavid du Colombier 	}
887*8ccd4a63SDavid du Colombier 	n = _sysbind(old, new, flag);
888*8ccd4a63SDavid du Colombier 	enderror();
889*8ccd4a63SDavid du Colombier 	return n;
890*8ccd4a63SDavid du Colombier }
891*8ccd4a63SDavid du Colombier 
892*8ccd4a63SDavid du Colombier int
893*8ccd4a63SDavid du Colombier syschdir(char *path)
894*8ccd4a63SDavid du Colombier {
895*8ccd4a63SDavid du Colombier 	int n;
896*8ccd4a63SDavid du Colombier 
897*8ccd4a63SDavid du Colombier 	starterror();
898*8ccd4a63SDavid du Colombier 	if(waserror()){
899*8ccd4a63SDavid du Colombier 		_syserror();
900*8ccd4a63SDavid du Colombier 		return -1;
901*8ccd4a63SDavid du Colombier 	}
902*8ccd4a63SDavid du Colombier 	n = _syschdir(path);
903*8ccd4a63SDavid du Colombier 	enderror();
904*8ccd4a63SDavid du Colombier 	return n;
905*8ccd4a63SDavid du Colombier }
906*8ccd4a63SDavid du Colombier 
907*8ccd4a63SDavid du Colombier int
908*8ccd4a63SDavid du Colombier sysclose(int fd)
909*8ccd4a63SDavid du Colombier {
910*8ccd4a63SDavid du Colombier 	int n;
911*8ccd4a63SDavid du Colombier 
912*8ccd4a63SDavid du Colombier 	starterror();
913*8ccd4a63SDavid du Colombier 	if(waserror()){
914*8ccd4a63SDavid du Colombier 		_syserror();
915*8ccd4a63SDavid du Colombier 		return -1;
916*8ccd4a63SDavid du Colombier 	}
917*8ccd4a63SDavid du Colombier 	n = _sysclose(fd);
918*8ccd4a63SDavid du Colombier 	enderror();
919*8ccd4a63SDavid du Colombier 	return n;
920*8ccd4a63SDavid du Colombier }
921*8ccd4a63SDavid du Colombier 
922*8ccd4a63SDavid du Colombier int
923*8ccd4a63SDavid du Colombier syscreate(char *name, int mode, ulong perm)
924*8ccd4a63SDavid du Colombier {
925*8ccd4a63SDavid du Colombier 	int n;
926*8ccd4a63SDavid du Colombier 
927*8ccd4a63SDavid du Colombier 	starterror();
928*8ccd4a63SDavid du Colombier 	if(waserror()){
929*8ccd4a63SDavid du Colombier 		_syserror();
930*8ccd4a63SDavid du Colombier 		return -1;
931*8ccd4a63SDavid du Colombier 	}
932*8ccd4a63SDavid du Colombier 	n = _syscreate(name, mode, perm);
933*8ccd4a63SDavid du Colombier 	enderror();
934*8ccd4a63SDavid du Colombier 	return n;
935*8ccd4a63SDavid du Colombier }
936*8ccd4a63SDavid du Colombier 
937*8ccd4a63SDavid du Colombier int
938*8ccd4a63SDavid du Colombier sysdup(int fd0, int fd1)
939*8ccd4a63SDavid du Colombier {
940*8ccd4a63SDavid du Colombier 	int n;
941*8ccd4a63SDavid du Colombier 
942*8ccd4a63SDavid du Colombier 	starterror();
943*8ccd4a63SDavid du Colombier 	if(waserror()){
944*8ccd4a63SDavid du Colombier 		_syserror();
945*8ccd4a63SDavid du Colombier 		return -1;
946*8ccd4a63SDavid du Colombier 	}
947*8ccd4a63SDavid du Colombier 	n = _sysdup(fd0, fd1);
948*8ccd4a63SDavid du Colombier 	enderror();
949*8ccd4a63SDavid du Colombier 	return n;
950*8ccd4a63SDavid du Colombier }
951*8ccd4a63SDavid du Colombier 
952*8ccd4a63SDavid du Colombier int
953*8ccd4a63SDavid du Colombier sysfstat(int fd, uchar *buf, int n)
954*8ccd4a63SDavid du Colombier {
955*8ccd4a63SDavid du Colombier 	starterror();
956*8ccd4a63SDavid du Colombier 	if(waserror()){
957*8ccd4a63SDavid du Colombier 		_syserror();
958*8ccd4a63SDavid du Colombier 		return -1;
959*8ccd4a63SDavid du Colombier 	}
960*8ccd4a63SDavid du Colombier 	n = _sysfstat(fd, buf, n);
961*8ccd4a63SDavid du Colombier 	enderror();
962*8ccd4a63SDavid du Colombier 	return n;
963*8ccd4a63SDavid du Colombier }
964*8ccd4a63SDavid du Colombier 
965*8ccd4a63SDavid du Colombier int
966*8ccd4a63SDavid du Colombier sysfwstat(int fd, uchar *buf, int n)
967*8ccd4a63SDavid du Colombier {
968*8ccd4a63SDavid du Colombier 	starterror();
969*8ccd4a63SDavid du Colombier 	if(waserror()){
970*8ccd4a63SDavid du Colombier 		_syserror();
971*8ccd4a63SDavid du Colombier 		return -1;
972*8ccd4a63SDavid du Colombier 	}
973*8ccd4a63SDavid du Colombier 	n = _sysfwstat(fd, buf, n);
974*8ccd4a63SDavid du Colombier 	enderror();
975*8ccd4a63SDavid du Colombier 	return n;
976*8ccd4a63SDavid du Colombier }
977*8ccd4a63SDavid du Colombier 
978*8ccd4a63SDavid du Colombier int
979*8ccd4a63SDavid du Colombier sysmount(int fd, int afd, char *new, int flag, char *spec)
980*8ccd4a63SDavid du Colombier {
981*8ccd4a63SDavid du Colombier 	int n;
982*8ccd4a63SDavid du Colombier 
983*8ccd4a63SDavid du Colombier 	starterror();
984*8ccd4a63SDavid du Colombier 	if(waserror()){
985*8ccd4a63SDavid du Colombier 		_syserror();
986*8ccd4a63SDavid du Colombier 		return -1;
987*8ccd4a63SDavid du Colombier 	}
988*8ccd4a63SDavid du Colombier 	n = _sysmount(fd, afd, new, flag, spec);
989*8ccd4a63SDavid du Colombier 	enderror();
990*8ccd4a63SDavid du Colombier 	return n;
991*8ccd4a63SDavid du Colombier }
992*8ccd4a63SDavid du Colombier 
993*8ccd4a63SDavid du Colombier int
994*8ccd4a63SDavid du Colombier sysunmount(char *old, char *new)
995*8ccd4a63SDavid du Colombier {
996*8ccd4a63SDavid du Colombier 	int n;
997*8ccd4a63SDavid du Colombier 
998*8ccd4a63SDavid du Colombier 	starterror();
999*8ccd4a63SDavid du Colombier 	if(waserror()){
1000*8ccd4a63SDavid du Colombier 		_syserror();
1001*8ccd4a63SDavid du Colombier 		return -1;
1002*8ccd4a63SDavid du Colombier 	}
1003*8ccd4a63SDavid du Colombier 	n = _sysunmount(old, new);
1004*8ccd4a63SDavid du Colombier 	enderror();
1005*8ccd4a63SDavid du Colombier 	return n;
1006*8ccd4a63SDavid du Colombier }
1007*8ccd4a63SDavid du Colombier 
1008*8ccd4a63SDavid du Colombier int
1009*8ccd4a63SDavid du Colombier sysopen(char *name, int mode)
1010*8ccd4a63SDavid du Colombier {
1011*8ccd4a63SDavid du Colombier 	int n;
1012*8ccd4a63SDavid du Colombier 
1013*8ccd4a63SDavid du Colombier 	starterror();
1014*8ccd4a63SDavid du Colombier 	if(waserror()){
1015*8ccd4a63SDavid du Colombier 		_syserror();
1016*8ccd4a63SDavid du Colombier 		return -1;
1017*8ccd4a63SDavid du Colombier 	}
1018*8ccd4a63SDavid du Colombier 	n = _sysopen(name, mode);
1019*8ccd4a63SDavid du Colombier 	enderror();
1020*8ccd4a63SDavid du Colombier 	return n;
1021*8ccd4a63SDavid du Colombier }
1022*8ccd4a63SDavid du Colombier 
1023*8ccd4a63SDavid du Colombier int
1024*8ccd4a63SDavid du Colombier syspipe(int *fd)
1025*8ccd4a63SDavid du Colombier {
1026*8ccd4a63SDavid du Colombier 	int n;
1027*8ccd4a63SDavid du Colombier 
1028*8ccd4a63SDavid du Colombier 	starterror();
1029*8ccd4a63SDavid du Colombier 	if(waserror()){
1030*8ccd4a63SDavid du Colombier 		_syserror();
1031*8ccd4a63SDavid du Colombier 		return -1;
1032*8ccd4a63SDavid du Colombier 	}
1033*8ccd4a63SDavid du Colombier 	n = _syspipe(fd);
1034*8ccd4a63SDavid du Colombier 	enderror();
1035*8ccd4a63SDavid du Colombier 	return n;
1036*8ccd4a63SDavid du Colombier }
1037*8ccd4a63SDavid du Colombier 
1038*8ccd4a63SDavid du Colombier long
1039*8ccd4a63SDavid du Colombier syspread(int fd, void *buf, long n, vlong off)
1040*8ccd4a63SDavid du Colombier {
1041*8ccd4a63SDavid du Colombier 	starterror();
1042*8ccd4a63SDavid du Colombier 	if(waserror()){
1043*8ccd4a63SDavid du Colombier 		_syserror();
1044*8ccd4a63SDavid du Colombier 		return -1;
1045*8ccd4a63SDavid du Colombier 	}
1046*8ccd4a63SDavid du Colombier 	n = _syspread(fd, buf, n, off);
1047*8ccd4a63SDavid du Colombier 	enderror();
1048*8ccd4a63SDavid du Colombier 	return n;
1049*8ccd4a63SDavid du Colombier }
1050*8ccd4a63SDavid du Colombier 
1051*8ccd4a63SDavid du Colombier long
1052*8ccd4a63SDavid du Colombier syspwrite(int fd, void *buf, long n, vlong off)
1053*8ccd4a63SDavid du Colombier {
1054*8ccd4a63SDavid du Colombier 	starterror();
1055*8ccd4a63SDavid du Colombier 	if(waserror()){
1056*8ccd4a63SDavid du Colombier 		_syserror();
1057*8ccd4a63SDavid du Colombier 		return -1;
1058*8ccd4a63SDavid du Colombier 	}
1059*8ccd4a63SDavid du Colombier 	n = _syspwrite(fd, buf, n, off);
1060*8ccd4a63SDavid du Colombier 	enderror();
1061*8ccd4a63SDavid du Colombier 	return n;
1062*8ccd4a63SDavid du Colombier }
1063*8ccd4a63SDavid du Colombier 
1064*8ccd4a63SDavid du Colombier long
1065*8ccd4a63SDavid du Colombier sysread(int fd, void *buf, long n)
1066*8ccd4a63SDavid du Colombier {
1067*8ccd4a63SDavid du Colombier 	starterror();
1068*8ccd4a63SDavid du Colombier 	if(waserror()){
1069*8ccd4a63SDavid du Colombier 		_syserror();
1070*8ccd4a63SDavid du Colombier 		return -1;
1071*8ccd4a63SDavid du Colombier 	}
1072*8ccd4a63SDavid du Colombier 	n = _syspread(fd, buf, n, (uvlong) ~0);
1073*8ccd4a63SDavid du Colombier 	enderror();
1074*8ccd4a63SDavid du Colombier 	return n;
1075*8ccd4a63SDavid du Colombier }
1076*8ccd4a63SDavid du Colombier 
1077*8ccd4a63SDavid du Colombier int
1078*8ccd4a63SDavid du Colombier sysremove(char *path)
1079*8ccd4a63SDavid du Colombier {
1080*8ccd4a63SDavid du Colombier 	int n;
1081*8ccd4a63SDavid du Colombier 
1082*8ccd4a63SDavid du Colombier 	starterror();
1083*8ccd4a63SDavid du Colombier 	if(waserror()){
1084*8ccd4a63SDavid du Colombier 		_syserror();
1085*8ccd4a63SDavid du Colombier 		return -1;
1086*8ccd4a63SDavid du Colombier 	}
1087*8ccd4a63SDavid du Colombier 	n = _sysremove(path);
1088*8ccd4a63SDavid du Colombier 	enderror();
1089*8ccd4a63SDavid du Colombier 	return n;
1090*8ccd4a63SDavid du Colombier }
1091*8ccd4a63SDavid du Colombier 
1092*8ccd4a63SDavid du Colombier vlong
1093*8ccd4a63SDavid du Colombier sysseek(int fd, vlong off, int whence)
1094*8ccd4a63SDavid du Colombier {
1095*8ccd4a63SDavid du Colombier 	starterror();
1096*8ccd4a63SDavid du Colombier 	if(waserror()){
1097*8ccd4a63SDavid du Colombier 		_syserror();
1098*8ccd4a63SDavid du Colombier 		return -1;
1099*8ccd4a63SDavid du Colombier 	}
1100*8ccd4a63SDavid du Colombier 	off = _sysseek(fd, off, whence);
1101*8ccd4a63SDavid du Colombier 	enderror();
1102*8ccd4a63SDavid du Colombier 	return off;
1103*8ccd4a63SDavid du Colombier }
1104*8ccd4a63SDavid du Colombier 
1105*8ccd4a63SDavid du Colombier int
1106*8ccd4a63SDavid du Colombier sysstat(char *name, uchar *buf, int n)
1107*8ccd4a63SDavid du Colombier {
1108*8ccd4a63SDavid du Colombier 	starterror();
1109*8ccd4a63SDavid du Colombier 	if(waserror()){
1110*8ccd4a63SDavid du Colombier 		_syserror();
1111*8ccd4a63SDavid du Colombier 		return -1;
1112*8ccd4a63SDavid du Colombier 	}
1113*8ccd4a63SDavid du Colombier 	n = _sysstat(name, buf, n);
1114*8ccd4a63SDavid du Colombier 	enderror();
1115*8ccd4a63SDavid du Colombier 	return n;
1116*8ccd4a63SDavid du Colombier }
1117*8ccd4a63SDavid du Colombier 
1118*8ccd4a63SDavid du Colombier long
1119*8ccd4a63SDavid du Colombier syswrite(int fd, void *buf, long n)
1120*8ccd4a63SDavid du Colombier {
1121*8ccd4a63SDavid du Colombier 	starterror();
1122*8ccd4a63SDavid du Colombier 	if(waserror()){
1123*8ccd4a63SDavid du Colombier 		_syserror();
1124*8ccd4a63SDavid du Colombier 		return -1;
1125*8ccd4a63SDavid du Colombier 	}
1126*8ccd4a63SDavid du Colombier 	n = _syspwrite(fd, buf, n, (uvlong) ~0);
1127*8ccd4a63SDavid du Colombier 	enderror();
1128*8ccd4a63SDavid du Colombier 	return n;
1129*8ccd4a63SDavid du Colombier }
1130*8ccd4a63SDavid du Colombier 
1131*8ccd4a63SDavid du Colombier int
1132*8ccd4a63SDavid du Colombier syswstat(char *name, uchar *buf, int n)
1133*8ccd4a63SDavid du Colombier {
1134*8ccd4a63SDavid du Colombier 	starterror();
1135*8ccd4a63SDavid du Colombier 	if(waserror()){
1136*8ccd4a63SDavid du Colombier 		_syserror();
1137*8ccd4a63SDavid du Colombier 		return -1;
1138*8ccd4a63SDavid du Colombier 	}
1139*8ccd4a63SDavid du Colombier 	n = _syswstat(name, buf, n);
1140*8ccd4a63SDavid du Colombier 	enderror();
1141*8ccd4a63SDavid du Colombier 	return n;
1142*8ccd4a63SDavid du Colombier }
1143*8ccd4a63SDavid du Colombier 
1144*8ccd4a63SDavid du Colombier void
1145*8ccd4a63SDavid du Colombier werrstr(char *f, ...)
1146*8ccd4a63SDavid du Colombier {
1147*8ccd4a63SDavid du Colombier 	char buf[ERRMAX];
1148*8ccd4a63SDavid du Colombier 	va_list arg;
1149*8ccd4a63SDavid du Colombier 
1150*8ccd4a63SDavid du Colombier 	va_start(arg, f);
1151*8ccd4a63SDavid du Colombier 	vsnprint(buf, sizeof buf, f, arg);
1152*8ccd4a63SDavid du Colombier 	va_end(arg);
1153*8ccd4a63SDavid du Colombier 
1154*8ccd4a63SDavid du Colombier 	if(up->nerrlab)
1155*8ccd4a63SDavid du Colombier 		strecpy(up->errstr, up->errstr+ERRMAX, buf);
1156*8ccd4a63SDavid du Colombier 	else
1157*8ccd4a63SDavid du Colombier 		strecpy(up->syserrstr, up->syserrstr+ERRMAX, buf);
1158*8ccd4a63SDavid du Colombier }
1159*8ccd4a63SDavid du Colombier 
1160*8ccd4a63SDavid du Colombier int
1161*8ccd4a63SDavid du Colombier errfmt(Fmt *fmt)
1162*8ccd4a63SDavid du Colombier {
1163*8ccd4a63SDavid du Colombier 	if(up->nerrlab)
1164*8ccd4a63SDavid du Colombier 		return fmtstrcpy(fmt, up->errstr);
1165*8ccd4a63SDavid du Colombier 	else
1166*8ccd4a63SDavid du Colombier 		return fmtstrcpy(fmt, up->syserrstr);
1167*8ccd4a63SDavid du Colombier }
1168*8ccd4a63SDavid du Colombier 
1169*8ccd4a63SDavid du Colombier int
1170*8ccd4a63SDavid du Colombier errstr(char *buf, uint n)
1171*8ccd4a63SDavid du Colombier {
1172*8ccd4a63SDavid du Colombier 	char tmp[ERRMAX];
1173*8ccd4a63SDavid du Colombier 	char *p;
1174*8ccd4a63SDavid du Colombier 
1175*8ccd4a63SDavid du Colombier 	p = up->nerrlab ? up->errstr : up->syserrstr;
1176*8ccd4a63SDavid du Colombier 	memmove(tmp, p, ERRMAX);
1177*8ccd4a63SDavid du Colombier 	utfecpy(p, p+ERRMAX, buf);
1178*8ccd4a63SDavid du Colombier 	utfecpy(buf, buf+n, tmp);
1179*8ccd4a63SDavid du Colombier 	return strlen(buf);
1180*8ccd4a63SDavid du Colombier }
1181*8ccd4a63SDavid du Colombier 
1182*8ccd4a63SDavid du Colombier int
1183*8ccd4a63SDavid du Colombier rerrstr(char *buf, uint n)
1184*8ccd4a63SDavid du Colombier {
1185*8ccd4a63SDavid du Colombier 	char *p;
1186*8ccd4a63SDavid du Colombier 
1187*8ccd4a63SDavid du Colombier 	p = up->nerrlab ? up->errstr : up->syserrstr;
1188*8ccd4a63SDavid du Colombier 	utfecpy(buf, buf+n, p);
1189*8ccd4a63SDavid du Colombier 	return strlen(buf);
1190*8ccd4a63SDavid du Colombier }
1191*8ccd4a63SDavid du Colombier 
1192*8ccd4a63SDavid du Colombier ulong
1193*8ccd4a63SDavid du Colombier _sysrendezvous(ulong arg0, ulong arg1)
1194*8ccd4a63SDavid du Colombier {
1195*8ccd4a63SDavid du Colombier 	ulong tag, val;
1196*8ccd4a63SDavid du Colombier 	Proc *p, **l;
1197*8ccd4a63SDavid du Colombier 
1198*8ccd4a63SDavid du Colombier 	tag = arg0;
1199*8ccd4a63SDavid du Colombier 	l = &REND(up->rgrp, tag);
1200*8ccd4a63SDavid du Colombier 	up->rendval = ~0UL;
1201*8ccd4a63SDavid du Colombier 
1202*8ccd4a63SDavid du Colombier 	lock(&up->rgrp->ref.lk);
1203*8ccd4a63SDavid du Colombier 	for(p = *l; p; p = p->rendhash) {
1204*8ccd4a63SDavid du Colombier 		if(p->rendtag == tag) {
1205*8ccd4a63SDavid du Colombier 			*l = p->rendhash;
1206*8ccd4a63SDavid du Colombier 			val = p->rendval;
1207*8ccd4a63SDavid du Colombier 			p->rendval = arg1;
1208*8ccd4a63SDavid du Colombier 
1209*8ccd4a63SDavid du Colombier 			while(p->mach != 0)
1210*8ccd4a63SDavid du Colombier 				;
1211*8ccd4a63SDavid du Colombier 			procwakeup(p);
1212*8ccd4a63SDavid du Colombier 			unlock(&up->rgrp->ref.lk);
1213*8ccd4a63SDavid du Colombier 			return val;
1214*8ccd4a63SDavid du Colombier 		}
1215*8ccd4a63SDavid du Colombier 		l = &p->rendhash;
1216*8ccd4a63SDavid du Colombier 	}
1217*8ccd4a63SDavid du Colombier 
1218*8ccd4a63SDavid du Colombier 	/* Going to sleep here */
1219*8ccd4a63SDavid du Colombier 	up->rendtag = tag;
1220*8ccd4a63SDavid du Colombier 	up->rendval = arg1;
1221*8ccd4a63SDavid du Colombier 	up->rendhash = *l;
1222*8ccd4a63SDavid du Colombier 	*l = up;
1223*8ccd4a63SDavid du Colombier 	up->state = Rendezvous;
1224*8ccd4a63SDavid du Colombier 	unlock(&up->rgrp->ref.lk);
1225*8ccd4a63SDavid du Colombier 
1226*8ccd4a63SDavid du Colombier 	procsleep();
1227*8ccd4a63SDavid du Colombier 
1228*8ccd4a63SDavid du Colombier 	return up->rendval;
1229*8ccd4a63SDavid du Colombier }
1230*8ccd4a63SDavid du Colombier 
1231*8ccd4a63SDavid du Colombier ulong
1232*8ccd4a63SDavid du Colombier sysrendezvous(ulong tag, ulong val)
1233*8ccd4a63SDavid du Colombier {
1234*8ccd4a63SDavid du Colombier 	ulong n;
1235*8ccd4a63SDavid du Colombier 
1236*8ccd4a63SDavid du Colombier 	starterror();
1237*8ccd4a63SDavid du Colombier 	if(waserror()){
1238*8ccd4a63SDavid du Colombier 		_syserror();
1239*8ccd4a63SDavid du Colombier 		return -1;
1240*8ccd4a63SDavid du Colombier 	}
1241*8ccd4a63SDavid du Colombier 	n = _sysrendezvous(tag, val);
1242*8ccd4a63SDavid du Colombier 	enderror();
1243*8ccd4a63SDavid du Colombier 	return n;
1244*8ccd4a63SDavid du Colombier }
1245