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