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