Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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*
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
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
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
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
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
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
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
324
_sysclose(int fd)
325
{
326
	fdtochan(fd, -1, 0, 0);
327
	fdclose(fd, 0);
328
 
329
	return 0;
330
}
331
 
332
long
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
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
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
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
488
sys_write(int fd, void *buf, long n)
489
{
490
	return kwrite(fd, buf, n, nil);
491
}
492
 
493
long
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
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
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
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
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
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
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
719
_sysbind(char *old, char *new, int flag)
720
{
721
	return bindmount(0, -1, -1, old, new, flag, nil);
722
}
723
 
724
long
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
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
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
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
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
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
855
starterror(void)
856
{
857
	assert(up->nerrlab == 0);
858
}
859
 
860
static 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
871
enderror(void)
872
{
873
	assert(up->nerrlab == 1);
874
	poperror();
875
}
876
 
877
int
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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*
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*
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
}