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 } 1245