|
|
1.1 ! root 1: /* $Header: /src386/kernel/coh.386/RCS/sys2.c,v 1.11 93/06/14 13:35:29 bin Exp Locker: bin $ */ ! 2: /* (lgl- ! 3: * The information contained herein is a trade secret of Mark Williams ! 4: * Company, and is confidential information. It is provided under a ! 5: * license agreement, and may be copied or disclosed only under the ! 6: * terms of that agreement. Any reproduction or disclosure of this ! 7: * material without the express written authorization of Mark Williams ! 8: * Company or pursuant to the license agreement is unlawful. ! 9: * ! 10: * COHERENT Version 4.0 ! 11: * Copyright (c) 1982, 1993. ! 12: * All rights reserved. ! 13: -lgl) */ ! 14: /* ! 15: * Coherent. ! 16: * System calls (filesystem related). ! 17: */ ! 18: #include <sys/coherent.h> ! 19: #include <errno.h> ! 20: #include <fcntl.h> ! 21: #include <sys/fd.h> ! 22: #include <sys/ino.h> ! 23: #include <sys/inode.h> ! 24: #include <sys/mount.h> ! 25: #include <sys/sched.h> ! 26: #include <sys/stat.h> ! 27: ! 28: /* ! 29: * Determine accessibility of the given file. ! 30: */ ! 31: uaccess(np, mode) ! 32: char *np; ! 33: register int mode; ! 34: { ! 35: register INODE *ip; ! 36: register int r; ! 37: ! 38: schizo(); ! 39: r = ftoi(np, 'r'); ! 40: schizo(); ! 41: if (r) ! 42: return; ! 43: ip = u.u_cdiri; ! 44: if ((mode&imode(ip, u.u_ruid, u.u_rgid)) != mode) ! 45: u.u_error = EACCES; ! 46: idetach(ip); ! 47: return 0; ! 48: } ! 49: ! 50: /* ! 51: * Schizo - swap real and effective id's. ! 52: */ ! 53: schizo() ! 54: { ! 55: register int t; ! 56: ! 57: t = u.u_uid; ! 58: u.u_uid = u.u_ruid; ! 59: u.u_ruid = t; ! 60: t = u.u_gid; ! 61: u.u_gid = u.u_rgid; ! 62: u.u_rgid = t; ! 63: } ! 64: ! 65: /* ! 66: * Turn accounting on or off. ! 67: */ ! 68: uacct(np) ! 69: register char *np; ! 70: { ! 71: register INODE *ip; ! 72: ! 73: if (super() == 0) ! 74: return; ! 75: if (np == NULL) { ! 76: if (acctip == NULL) { ! 77: u.u_error = EINVAL; ! 78: return; ! 79: } ! 80: ldetach(acctip); ! 81: acctip = NULL; ! 82: } else { ! 83: if (acctip != NULL) { ! 84: u.u_error = EINVAL; ! 85: return; ! 86: } ! 87: if (ftoi(np, 'r')) ! 88: return; ! 89: ip = u.u_cdiri; ! 90: if ((ip->i_mode&IFMT) != IFREG) { ! 91: u.u_error = EINVAL; ! 92: idetach(ip); ! 93: return; ! 94: } ! 95: iunlock(ip); ! 96: acctip = ip; ! 97: } ! 98: return 0; ! 99: } ! 100: ! 101: /* ! 102: * Set current directory. ! 103: */ ! 104: uchdir(np) ! 105: char *np; ! 106: { ! 107: setcdir(np, &u.u_cdir); ! 108: return 0; ! 109: } ! 110: ! 111: /* ! 112: * Given a directory name and a pointer to a working directory pointer, ! 113: * Save the inode associated with the directory name in the working ! 114: * directory pointer and release the old one. This is used to change ! 115: * working and root directories. ! 116: */ ! 117: setcdir(np, ipp) ! 118: char *np; ! 119: register INODE **ipp; ! 120: { ! 121: register INODE *ip; ! 122: ! 123: if (ftoi(np, 'r')) ! 124: return; ! 125: ip = u.u_cdiri; ! 126: if ((ip->i_mode&IFMT) != IFDIR) { ! 127: u.u_error = ENOTDIR; ! 128: idetach(ip); ! 129: return; ! 130: } ! 131: if (iaccess(ip, IPE) == 0) { ! 132: u.u_error = EACCES; ! 133: idetach(ip); ! 134: return; ! 135: } ! 136: iunlock(ip); ! 137: ldetach(*ipp); ! 138: *ipp = ip; ! 139: } ! 140: ! 141: /* ! 142: * Change the mode of a file. ! 143: */ ! 144: uchmod(np, mode) ! 145: char *np; ! 146: { ! 147: register INODE *ip; ! 148: ! 149: if (ftoi(np, 'r')) ! 150: return; ! 151: ip = u.u_cdiri; ! 152: if (owner(ip->i_uid)) { ! 153: if (u.u_uid) ! 154: mode &= ~ISVTXT; ! 155: ip->i_mode &= IFMT; ! 156: ip->i_mode |= mode&~IFMT; ! 157: icrt(ip); /* chmod - ctime */ ! 158: } ! 159: idetach(ip); ! 160: return 0; ! 161: } ! 162: ! 163: /* ! 164: * Change owner and group of a file. ! 165: */ ! 166: uchown(np, uid, gid) ! 167: char *np; ! 168: { ! 169: register INODE *ip; ! 170: ! 171: if (ftoi(np, 'r')) ! 172: return; ! 173: ip = u.u_cdiri; ! 174: if (super()) { ! 175: ip->i_mode &= ~(ISUID | ISGID); /* clear any setuid/setgid */ ! 176: ip->i_uid = uid; ! 177: ip->i_gid = gid; ! 178: icrt(ip); /* chown - ctime */ ! 179: } ! 180: idetach(ip); ! 181: return 0; ! 182: } ! 183: ! 184: /* ! 185: * Set root directory. ! 186: */ ! 187: uchroot(np) ! 188: register char *np; ! 189: { ! 190: if (super()) ! 191: setcdir(np, &u.u_rdir); ! 192: return 0; ! 193: } ! 194: ! 195: /* ! 196: * Close the given file descriptor. ! 197: */ ! 198: uclose(fd) ! 199: { ! 200: fdclose(fd); ! 201: return 0; ! 202: } ! 203: ! 204: /* ! 205: * Create a file with the given mode. ! 206: */ ! 207: ucreat(np, mode) ! 208: char *np; ! 209: register int mode; ! 210: { ! 211: return(uopen(np, O_WRONLY|O_CREAT|O_TRUNC, mode)); ! 212: } ! 213: ! 214: /* ! 215: * Duplicate a file descriptor. ! 216: */ ! 217: udup(ofd) ! 218: { ! 219: return ufcntl(ofd, F_DUPFD, 0); ! 220: } ! 221: ! 222: /* ! 223: * Given a file descriptor, return a status structure. ! 224: */ ! 225: ufstat(fd, stp) ! 226: struct stat *stp; ! 227: { ! 228: register INODE *ip; ! 229: register FD *fdp; ! 230: struct stat stat; ! 231: ! 232: if ((fdp=fdget(fd)) == NULL) ! 233: return; ! 234: ip = fdp->f_ip; ! 235: istat(ip, &stat); ! 236: kucopy(&stat, stp, sizeof(stat)); ! 237: return 0; ! 238: } ! 239: ! 240: /* ! 241: * File control. ! 242: */ ! 243: ufcntl( fd, cmd, arg ) ! 244: int fd, cmd, arg; ! 245: { ! 246: register FD * fdp; ! 247: FLOCK sfl; ! 248: ! 249: T_VLAD(2, printf("fcntl(%d,%x,%x) ", fd, cmd, arg)); ! 250: ! 251: /* ! 252: * Validate file descriptor. ! 253: */ ! 254: if ( (fd < 0) || (fd >= NOFILE) || ((fdp = u.u_filep[fd]) == 0) ) { ! 255: u.u_error = EBADF; ! 256: return; ! 257: } ! 258: ! 259: switch ( cmd ) { ! 260: ! 261: case F_DUPFD: ! 262: /* ! 263: * Validate base file descriptor. ! 264: */ ! 265: if ( (arg < 0) || (arg >= NOFILE) ) { ! 266: u.u_error = EINVAL; ! 267: return; ! 268: } ! 269: ! 270: /* ! 271: * Search for next available file descriptor. ! 272: */ ! 273: do { ! 274: if ( u.u_filep[arg] == 0 ) { ! 275: u.u_filep[arg] = fdp; ! 276: fdp->f_refc++; ! 277: return arg; ! 278: } ! 279: } while ( ++arg < NOFILE ); ! 280: ! 281: u.u_error = EMFILE; ! 282: return; ! 283: ! 284: case F_SETFL: ! 285: fdp->f_flag &= ~(IPNDLY|IPAPPEND); ! 286: if ( arg & O_NDELAY ) ! 287: fdp->f_flag |= IPNDLY; ! 288: if ( arg & O_APPEND ) ! 289: fdp->f_flag |= IPAPPEND; ! 290: /* no break */ ! 291: ! 292: case F_GETFL: ! 293: switch ( fdp->f_flag & (IPR+IPW) ) { ! 294: case IPR: arg = O_RDONLY; break; ! 295: case IPW: arg = O_WRONLY; break; ! 296: default: arg = O_RDWR; break; ! 297: } ! 298: if ( fdp->f_flag & IPNDLY ) ! 299: arg |= O_NDELAY; ! 300: if ( fdp->f_flag & IPAPPEND ) ! 301: arg |= O_APPEND; ! 302: return arg; ! 303: ! 304: case F_GETLK: ! 305: case F_SETLK: ! 306: case F_SETLKW: ! 307: ukcopy(*(FLOCK **)&arg, &sfl, sizeof(FLOCK)); ! 308: if (u.u_error) ! 309: return -1; ! 310: if (rlock(fdp, cmd, &sfl)) ! 311: return -1; ! 312: if (cmd == F_GETLK) { ! 313: kucopy(&sfl, *(FLOCK **)&arg, sizeof(FLOCK)); ! 314: if (u.u_error) ! 315: return -1; ! 316: } ! 317: return 0; ! 318: ! 319: case F_GETFD: ! 320: return fdp->f_flag2 & FD_CLOEXEC; ! 321: ! 322: case F_SETFD: ! 323: if (arg & FD_CLOEXEC) ! 324: fdp->f_flag2 |= FD_CLOEXEC; ! 325: else ! 326: fdp->f_flag2 &= ~FD_CLOEXEC; ! 327: return 0; ! 328: ! 329: default: ! 330: T_VLAD(0x02, ! 331: printf("'fcntl - unknown cmd=%d arg=0x0%x' ", cmd, arg)); ! 332: u.u_error = EINVAL; ! 333: } ! 334: } ! 335: ! 336: /* ! 337: * Device control information. ! 338: */ ! 339: uioctl(fd, r, argp) ! 340: struct sgttyb *argp; ! 341: { ! 342: register FD *fdp; ! 343: register INODE *ip; ! 344: register int mode; ! 345: ! 346: ! 347: T_PIGGY( 0x8, printf("uioctl(%d, 0x%x, 0x%x)", fd, r, argp); ); ! 348: ! 349: if ((fdp=fdget(fd)) == NULL) ! 350: return; ! 351: ip = fdp->f_ip; ! 352: mode = ip->i_mode&IFMT; ! 353: if (mode!=IFCHR && mode!=IFBLK) { ! 354: u.u_error = ENOTTY; ! 355: return; ! 356: } ! 357: dioctl(ip->i_a.i_rdev, r, argp); ! 358: return 0; ! 359: } ! 360: ! 361: /* ! 362: * Create a link, `np2' to the already existing file `np1'. ! 363: */ ! 364: ulink(np1, np2) ! 365: char *np1; ! 366: char *np2; ! 367: { ! 368: register INODE *ip1; ! 369: ! 370: if (ftoi(np1, 'r')) ! 371: return; ! 372: ip1 = u.u_cdiri; ! 373: if ((ip1->i_mode&IFMT)==IFDIR && super()==0) { ! 374: idetach(ip1); ! 375: return; ! 376: } ! 377: iunlock(ip1); ! 378: if (ftoi(np2, 'c')) { ! 379: ldetach(ip1); ! 380: return; ! 381: } ! 382: if (u.u_cdiri != NULL) { ! 383: u.u_error = EEXIST; ! 384: idetach(u.u_cdiri); ! 385: ldetach(ip1); ! 386: return; ! 387: } ! 388: if (ip1->i_dev != u.u_pdiri->i_dev) { ! 389: u.u_error = EXDEV; ! 390: idetach(u.u_pdiri); ! 391: ldetach(ip1); ! 392: return; ! 393: } ! 394: if (iaccess(u.u_pdiri, IPW) == 0) { ! 395: idetach(u.u_pdiri); ! 396: ldetach(ip1); ! 397: return; ! 398: } ! 399: idirent(ip1->i_ino); ! 400: idetach(u.u_pdiri); ! 401: ilock(ip1); ! 402: /* idirent() can fail during iwrite. In this case we should not ! 403: * increase link count. ! 404: * As result of this old bug, 286 mkdir utility destroys file ! 405: * system when runs out of free blocks. ! 406: */ ! 407: if (!u.u_error) ! 408: ip1->i_nlink++; ! 409: icrt(ip1); /* link - ctime */ ! 410: idetach(ip1); ! 411: return 0; ! 412: } ! 413: ! 414: /* ! 415: * Seek on the given file descriptor. ! 416: */ ! 417: off_t ! 418: ulseek(fd, off, w) ! 419: register off_t off; ! 420: { ! 421: register FD *fdp; ! 422: register INODE *ip; ! 423: ! 424: if ((fdp=fdget(fd)) == NULL) ! 425: return; ! 426: ip = fdp->f_ip; ! 427: if ((ip->i_mode&IFMT) == IFPIPE) { ! 428: u.u_error = ESPIPE; ! 429: return; ! 430: } ! 431: switch (w) { ! 432: case 0: ! 433: break; ! 434: case 1: ! 435: off += fdp->f_seek; ! 436: break; ! 437: case 2: ! 438: off += ip->i_size; ! 439: break; ! 440: default: ! 441: u.u_error = EINVAL; ! 442: return; ! 443: } ! 444: ! 445: if (off < 0) { ! 446: u.u_error = EINVAL; ! 447: return; ! 448: } ! 449: ! 450: fdp->f_seek = off; ! 451: return (off); ! 452: } ! 453: ! 454: /* ! 455: * Create a special file. ! 456: */ ! 457: umknod(np, mode, rdev) ! 458: char *np; ! 459: dev_t rdev; ! 460: { ! 461: register INODE *ip; ! 462: register int type; ! 463: ! 464: type = mode&IFMT; ! 465: if (type!=IFPIPE && super()==0) ! 466: return; ! 467: if (type!=IFBLK && type!=IFCHR) ! 468: rdev = 0; ! 469: if (ftoi(np, 'c')) ! 470: return; ! 471: if ((ip=u.u_cdiri) != NULL) { ! 472: u.u_error = EEXIST; ! 473: idetach(ip); ! 474: return; ! 475: } ! 476: if ((ip=imake(mode, rdev)) != NULL) ! 477: idetach(ip); ! 478: return 0; ! 479: } ! 480: ! 481: /* ! 482: * Mount the device `sp' on the pathname `np'. The flag, `f', ! 483: * indicates that the device is to be mounted read only. ! 484: */ ! 485: umount(sp, np, f) ! 486: char *sp; ! 487: char *np; ! 488: { ! 489: register INODE *ip; ! 490: register MOUNT *mp; ! 491: register dev_t rdev; ! 492: register int mode; ! 493: ! 494: if (ftoi(sp, 'r')) ! 495: return; ! 496: ip = u.u_cdiri; ! 497: if (iaccess(ip, IPR|IPW) == 0) ! 498: goto err; ! 499: mode = ip->i_mode; ! 500: rdev = ip->i_a.i_rdev; ! 501: if ((mode&IFMT) != IFBLK) { ! 502: u.u_error = ENOTBLK; ! 503: goto err; ! 504: } ! 505: idetach(ip); ! 506: if (ftoi(np, 'r')) ! 507: return; ! 508: ip = u.u_cdiri; ! 509: if (iaccess(ip, IPR) == 0) ! 510: goto err; ! 511: if ((ip->i_mode&IFMT) != IFDIR) { ! 512: u.u_error = ENOTDIR; ! 513: goto err; ! 514: } ! 515: /* Check for current directory, open, or mount directory */ ! 516: if (ip->i_refc > 1 || ip->i_ino == ROOTIN) { ! 517: u.u_error = EBUSY; ! 518: goto err; ! 519: } ! 520: for (mp=mountp; mp!=NULL; mp=mp->m_next) { ! 521: if (mp->m_dev == rdev) { ! 522: u.u_error = EBUSY; ! 523: goto err; ! 524: } ! 525: } ! 526: if ((mp=fsmount(rdev, f)) == NULL) ! 527: goto err; ! 528: mp->m_ip = ip; ! 529: ip->i_flag |= IFMNT; ! 530: ip->i_refc++; ! 531: err: ! 532: idetach(ip); ! 533: return 0; ! 534: } ! 535: ! 536: /* ! 537: * Poll devices for input/output events. ! 538: */ ! 539: int ! 540: upoll(pollfds, npoll, msec) ! 541: struct pollfd * pollfds; ! 542: unsigned long npoll; ! 543: int msec; ! 544: { ! 545: register struct pollfd * pollp; /* current poll pointer */ ! 546: register FD * fdp; /* current file descriptor ptr */ ! 547: auto int fd; /* current file descriptor */ ! 548: auto int rev; /* last event report received */ ! 549: auto int nev; /* number non-zero event reports */ ! 550: auto int i; ! 551: char * cp; ! 552: int ret = -1; ! 553: ! 554: /* ! 555: * Validate number of polls. ! 556: */ ! 557: if ((npoll < 0) || (npoll > NOFILE)) { ! 558: u.u_error = EINVAL; ! 559: goto poll_done; ! 560: } ! 561: ! 562: /* ! 563: * If there are any fd's to poll ! 564: * validate address of polling information. ! 565: * npoll of 0 is legal, allows user a short delay. ! 566: */ ! 567: if (npoll) ! 568: if ((pollfds == NULL) ! 569: || !useracc(pollfds, npoll*sizeof(struct pollfd), 1)) { ! 570: u.u_error = EFAULT; ! 571: goto poll_done; ! 572: } ! 573: ! 574: for (;;) { ! 575: /* ! 576: * Service each poll in turn. ! 577: */ ! 578: for (nev=0, i=npoll, pollp = pollfds; i > 0; --i, pollp++) { ! 579: ! 580: /* ! 581: * Fetch file descriptor. ! 582: */ ! 583: fd = getuwd(&pollp->fd); ! 584: ! 585: /* ! 586: * Ignore negative file descriptors. ! 587: */ ! 588: if (fd < 0) { ! 589: rev = 0; ! 590: goto remember; ! 591: } ! 592: ! 593: #if 1 ! 594: /* ! 595: * Ignore file descriptors that are too large. ! 596: */ ! 597: if (fd >= NOFILE) { ! 598: rev = 0; ! 599: goto remember; ! 600: } ! 601: #else ! 602: /* For now, msg polling is deleted. */ ! 603: /* ! 604: * Poll message queue. ! 605: */ ! 606: if (fd >= NOFILE) { ! 607: rev = msgpoll(fd, getusd(&pollp->events), msec); ! 608: goto remember; ! 609: } ! 610: #endif ! 611: ! 612: /* ! 613: * Validate file descriptor. ! 614: */ ! 615: if ((fdp = u.u_filep[fd]) == 0) { ! 616: rev = POLLNVAL; ! 617: goto remember; ! 618: } ! 619: ! 620: switch ( fdp->f_ip->i_mode & IFMT ) { ! 621: case IFCHR: ! 622: rev = dpoll(fdp->f_ip->i_a.i_rdev, ! 623: getusd(&pollp->events)&0xffff, msec); ! 624: break; ! 625: case IFPIPE: ! 626: rev = ppoll(fdp->f_ip, ! 627: getusd(&pollp->events)&0xffff, msec); ! 628: break; ! 629: default: ! 630: printf("polling illegal dev: fd=%d mode=%x\n", ! 631: fd, fdp->f_ip->i_mode); ! 632: rev = POLLNVAL; ! 633: break; ! 634: } ! 635: ! 636: /* ! 637: * Remember reponses. ! 638: */ ! 639: remember: ! 640: cp = (char *)(&pollp->revents); ! 641: putusd(cp, rev); ! 642: ! 643: /* ! 644: * Record number of non-zero responses. ! 645: */ ! 646: if (rev) ! 647: nev++; ! 648: } ! 649: ! 650: /* ! 651: * Non-blocking poll or poll response received. ! 652: */ ! 653: if ( (nev != 0) || (msec == 0) ) { ! 654: pollexit(); ! 655: ret = nev; ! 656: goto poll_done; ! 657: } ! 658: ! 659: /* ! 660: * Schedule wakeup timer if positive delay interval given ! 661: * and the timer is not currently set. ! 662: */ ! 663: if ( (msec > 0) && (cprocp->p_polltim.t_func == NULL) ) { ! 664: /* ! 665: * Convert milliseconds to clock ticks. ! 666: */ ! 667: msec += (1000 / HZ) - 1; ! 668: msec /= (1000 / HZ); ! 669: timeout(&cprocp->p_polltim, msec, ! 670: wakeup, &cprocp->p_polls); ! 671: } ! 672: ! 673: /* ! 674: * Wake for polled event, poll timeout, or signal. ! 675: */ ! 676: x_sleep(&cprocp->p_polls, pritty, slpriSigCatch, "poll"); ! 677: /* Wakeup for polled event, poll timeout, or signal. */ ! 678: ! 679: /* ! 680: * Terminate event monitoring. ! 681: */ ! 682: pollexit(); ! 683: ! 684: /* ! 685: * Signal woke us up. ! 686: */ ! 687: if (nondsig()) { ! 688: u.u_error = EINTR; ! 689: goto poll_done; ! 690: } ! 691: /* ! 692: * We were woken up by timeout wakeup. ! 693: */ ! 694: if ( (msec > 0) && (cprocp->p_polltim.t_lbolt <= lbolt) ) { ! 695: ret = 0; ! 696: goto poll_done; ! 697: } ! 698: } ! 699: ! 700: poll_done: ! 701: /* ! 702: * Cancel timeout ! 703: */ ! 704: if ( (msec > 0) && (cprocp->p_polltim.t_func != NULL) ) ! 705: timeout(&cprocp->p_polltim, 0, NULL, NULL); ! 706: ! 707: return ret; ! 708: } ! 709: ! 710: /* ! 711: * Suspend execution for a short interval. ! 712: * ! 713: * Return the number of milliseconds actually slept. ! 714: * Shares use of cprocp->p_polltim with upoll(). ! 715: */ ! 716: int ! 717: unap(msec) ! 718: int msec; ! 719: { ! 720: int ret, lbolt0; ! 721: int ticksToWait, ticksWaited; ! 722: ! 723: if (msec <= 0) ! 724: return 0; ! 725: ! 726: /* ! 727: * Convert milliseconds to clock ticks. ! 728: * ! 729: * Wait for at least the specified number of milliseconds. ! 730: * For 100 Hz clock, if nap is for 11 msec, timeout is for 2 ticks. ! 731: */ ! 732: ticksToWait = ((msec * HZ) + 999) / 1000; ! 733: timeout(&cprocp->p_polltim, ticksToWait, wakeup, &cprocp->p_polls); ! 734: ! 735: /* ! 736: * Wake for timeout or signal. ! 737: */ ! 738: lbolt0 = lbolt; ! 739: if (x_sleep(&cprocp->p_polls, pritty, slpriSigCatch, "nap")) { ! 740: /* ! 741: * Signal woke us up. ! 742: */ ! 743: u.u_error = EINTR; ! 744: goto napDone; ! 745: } else { ! 746: /* ! 747: * We were awakened by a timeout. ! 748: * Return number of milliseconds actually waited. ! 749: */ ! 750: ticksWaited = lbolt - lbolt0; ! 751: if (ticksWaited >= 0) ! 752: ret = (ticksWaited * 1000) / HZ; ! 753: else ! 754: ret = 0; ! 755: goto napDone; ! 756: } ! 757: ! 758: napDone: ! 759: /* ! 760: * Cancel timeout ! 761: */ ! 762: timeout(&cprocp->p_polltim, 0, NULL, NULL); ! 763: ! 764: return ret; ! 765: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.