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