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