|
|
1.1 ! root 1: /* $Header: /y/coh.386/RCS/sys3.c,v 1.5 92/07/16 16:33:36 hal Exp $ */ ! 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: * Coherent. ! 17: * System calls (more filesystem related calls). ! 18: * ! 19: * $Log: sys3.c,v $ ! 20: * Revision 1.5 92/07/16 16:33:36 hal ! 21: * Kernel #58 ! 22: * ! 23: * Revision 1.3 92/02/20 19:37:59 piggy ! 24: * Three-argument S5-style open(). ! 25: * ! 26: * Revision 1.2 92/01/06 12:00:52 hal ! 27: * Compile with cc.mwc. ! 28: * ! 29: * Revision 1.3 89/02/07 18:50:27 src ! 30: * Bug: Console driver did not validate user addresses before initiating a ! 31: * transfer. This resulted in a system trap in protected mode if a write ! 32: * outside of user data space was attempted. ! 33: * Fix: Reads and writes now validate user addresses via 'useracc' prior to ! 34: * calling drivers. (ABC) ! 35: * ! 36: * Revision 1.2 88/08/02 15:01:04 src ! 37: * O_APPEND flag now supported on open/fcntl system calls. ! 38: * ! 39: * Revision 1.1 88/03/24 16:14:35 src ! 40: * Initial revision ! 41: * ! 42: * 88/01/22 Allan Cornish /usr/src/sys/coh/sys3.c ! 43: * sysio() inode lock extended to cover getting/modifying file seek offset. ! 44: * ! 45: * 86/11/19 Allan Cornish /usr/src/sys/coh/sys3.c ! 46: * uopen() now checks mode for O_NDELAY and sets IPNDLY bit in fdp->f_flag. ! 47: * sysio() now checks fdp->f_flag for IPNDLY and sets IONDLY bit in io_flag. ! 48: */ ! 49: #include <sys/coherent.h> ! 50: #include <sys/buf.h> ! 51: #include <errno.h> ! 52: #include <fcntl.h> ! 53: #include <sys/fd.h> ! 54: #include <sys/filsys.h> ! 55: #include <sys/ino.h> ! 56: #include <sys/inode.h> ! 57: #include <sys/io.h> ! 58: #include <sys/mount.h> ! 59: #include <sys/stat.h> ! 60: ! 61: /* ! 62: * Open the file `np' with the mode `mode'. ! 63: */ ! 64: uopen(np, oflag, magic) ! 65: char *np; ! 66: { ! 67: register int f; ! 68: register INODE *ip; ! 69: register int fd; ! 70: int cflag; /* Flag is set if we create a file. */ ! 71: ! 72: cflag = 0; /* Nothing created so far. */ ! 73: ! 74: /* Determine read or write status for fdopen. */ ! 75: ! 76: switch (oflag & 3) { ! 77: case O_RDONLY: ! 78: f = IPR; ! 79: break; ! 80: case O_WRONLY: ! 81: f = IPW; ! 82: break; ! 83: case O_RDWR: ! 84: f = IPR|IPW; ! 85: break; ! 86: default: ! 87: SET_U_ERROR( EINVAL, "bad oflag" ); ! 88: T_PIGGY( 0x10000, printf("<open: bad oflag %x>", oflag); ); ! 89: return; ! 90: } ! 91: ! 92: /* Process the O_CREAT flag. */ ! 93: if ( oflag & O_CREAT ) { ! 94: if (ftoi(np, 'c') != 0) { ! 95: T_PIGGY( 0x10000, ! 96: printf("<open: bad ftoi(%s, 'c')>", np); ); ! 97: return; ! 98: } ! 99: ! 100: /* If it didn't exist, but its parent did, then make it. */ ! 101: if ((ip=u.u_cdiri) == NULL) { ! 102: if ((ip=imake((magic&~IFMT)|IFREG, 0)) == NULL) { ! 103: T_PIGGY( 0x10000, ! 104: printf("<open: bad imake(%x, 0)>", ! 105: (magic&~IFMT)|IFREG); ! 106: ); ! 107: return; ! 108: } ! 109: cflag = 1; /* Note that we just created a file. */ ! 110: } else { /* The file already exists. */ ! 111: /* ! 112: * Exclusive O_CREAT on existing file should fail. ! 113: */ ! 114: if ( oflag & O_EXCL ) { ! 115: idetach(ip); ! 116: SET_U_ERROR( EEXIST, ! 117: "exclusive creat on existing file"); ! 118: return; ! 119: } ! 120: /* Do not write to a read only file system; ! 121: * never write to a directory; ! 122: * always write to block and character special devices. ! 123: */ ! 124: switch (ip->i_mode&IFMT) { ! 125: case IFBLK: ! 126: case IFCHR: ! 127: break; ! 128: case IFDIR: ! 129: idetach(ip); ! 130: SET_U_ERROR( EISDIR, "<open: EISDIR>" ); ! 131: return; ! 132: default: ! 133: if (getment(ip->i_dev, 1) == NULL) { ! 134: idetach(ip); ! 135: SET_U_ERROR( EROFS, ! 136: "Could not fetch mount entry"); ! 137: T_PIGGY( 0x10000, ! 138: printf("<open: bad getment(ip->i_dev: %x, 1)>", ip->i_dev); ); ! 139: return; ! 140: } ! 141: } ! 142: } /* Did the file exist? */ ! 143: ! 144: } else { /* O_CREAT was not set--just reference the file. */ ! 145: if (ftoi(np, 'r') != 0) { ! 146: T_PIGGY( 0x10000, printf("<open: bad ftoi(%s, 'r')>", ! 147: np); ! 148: ); ! 149: return; ! 150: } ! 151: ip = u.u_cdiri; /* This must be the inode we wanted. */ ! 152: } ! 153: ! 154: /* ! 155: * ASSERTION: We probably have an inode for an existing file. ! 156: * If we don't, the ip will be NULL and iaccess() will fail (as ! 157: * desired.) ! 158: */ ! 159: ! 160: /* ! 161: * Only check permissions on a pre-existing file. ! 162: */ ! 163: if ((0 == cflag) && (iaccess(ip, f) == 0)) { ! 164: idetach(ip); ! 165: T_PIGGY( 0x10000, ! 166: printf("<open: bad access(ip:%x, f:%x)>", ip, f); ! 167: ); ! 168: return; ! 169: } ! 170: ! 171: /* ! 172: * ASSERTION: We have an inode for a file we ! 173: * have valid permissions on. ! 174: */ ! 175: ! 176: if ( ip->i_flag & IFEXCL) { ! 177: idetach(ip); ! 178: SET_U_ERROR( EEXIST, "open: file already open O_EXCL" ); ! 179: return; /* Somebody else has an exclusive open. */ ! 180: } ! 181: ! 182: /* ! 183: * If requesting exclusive open, fail if someone else has it open. ! 184: */ ! 185: if ( oflag & O_EXCL ) { ! 186: if (ip->i_refc != 1) { ! 187: idetach(ip); ! 188: SET_U_ERROR( EEXIST, "<open: O_EXCL but already open>" ); ! 189: return; ! 190: } ! 191: ! 192: /* Mark this open inode as exclusive. */ ! 193: ip->i_flag &= IFEXCL; ! 194: } ! 195: ! 196: if ( oflag & O_NDELAY ) { ! 197: f |= IPNDLY; ! 198: } ! 199: if ( oflag & O_APPEND ) { ! 200: f |= IPAPPEND; ! 201: } ! 202: if ( oflag & O_SYNC ) { ! 203: f |= IPSYNC; ! 204: } ! 205: if ( oflag & O_EXCL ) { ! 206: f |= IPEXCL; ! 207: } ! 208: if ( oflag & O_NOCTTY ) { ! 209: f |= IPNOCTTY; ! 210: } ! 211: ! 212: if ((fd=fdopen(ip, f)) < 0) { ! 213: idetach(ip); ! 214: T_PIGGY( 0x10000, ! 215: printf("<open: bad fdopen(ip: %x, f: %x>", ip, f); ! 216: ); ! 217: return; ! 218: } ! 219: ! 220: /* If requested, truncate the file. */ ! 221: if ( oflag & O_TRUNC ) { ! 222: if (0 == cflag) { /* No need to truncate a new file. */ ! 223: if (iaccess(ip, IPW) != 0) { ! 224: iclear(ip); ! 225: } else { ! 226: idetach(ip); ! 227: T_PIGGY( 0x10000, ! 228: printf("<open: No access to truncate.>"); ! 229: ); ! 230: return; ! 231: } ! 232: } ! 233: } ! 234: ! 235: iunlock(ip); ! 236: return (fd); ! 237: } ! 238: ! 239: /* ! 240: * Create a pipe. ! 241: */ ! 242: upipe(fdp) ! 243: short fdp[2]; ! 244: { ! 245: register INODE *ip; ! 246: register int fd1; ! 247: register int fd2; ! 248: ! 249: if ((ip=pmake(0)) == NULL) ! 250: return; ! 251: if ((fd1=fdopen(ip, IPR)) >= 0) { ! 252: ip->i_refc++; ! 253: if ((fd2=fdopen(ip, IPW)) >= 0) { ! 254: iunlock(ip); ! 255: u.u_rval2 = fd2; ! 256: return fd1; ! 257: } ! 258: --ip->i_refc; ! 259: iunlock(ip); ! 260: fdclose(fd1); ! 261: return 0; ! 262: } ! 263: idetach(ip); ! 264: return 0; ! 265: } ! 266: ! 267: /* ! 268: * Read `n' bytes into the buffer `bp' from file number `fd'. ! 269: */ ! 270: uread(fd, bp, n) ! 271: char *bp; ! 272: unsigned n; ! 273: { ! 274: T_PIGGY( 0x200, printf("uread(fd: %d, bp: %x, n: %d)", fd, bp, n); ); ! 275: return (sysio(fd, bp, n, 0)); ! 276: } ! 277: ! 278: /* ! 279: * Read or write `n' bytes from the file number `fd' using the buffer ! 280: * `bp'. If `do_write' is nonzero, write, else read. ! 281: */ ! 282: int ! 283: sysio(fd, bp, n, do_write) ! 284: int fd; ! 285: char *bp; ! 286: unsigned n; ! 287: int do_write; ! 288: { ! 289: register FD *fdp; ! 290: register INODE *ip; ! 291: register int type; ! 292: ! 293: if ((fdp=fdget(fd)) == NULL) ! 294: return 0; ! 295: if ((fdp->f_flag&(do_write?IPW:IPR)) == 0) { ! 296: u.u_error = EBADF; ! 297: return 0; ! 298: } ! 299: ! 300: /* ! 301: * When reading, buffer may NOT be in text segment. ! 302: */ ! 303: if (!useracc(bp, n) && do_write == 0) { ! 304: u.u_error = EFAULT; ! 305: return 0; ! 306: } ! 307: ! 308: /* ! 309: * When writing, buffer may be in text segment. ! 310: */ ! 311: if (!useracc(bp, n) && !acctext(bp, n)) { ! 312: u.u_error = EFAULT; ! 313: return 0; ! 314: } ! 315: ! 316: ip = fdp->f_ip; ! 317: type = ip->i_mode&IFMT; ! 318: if (type != IFCHR) ! 319: ilock(ip); ! 320: if ( fdp->f_flag & IPAPPEND ) ! 321: fdp->f_seek = ip->i_size; ! 322: u.u_io.io_seek = fdp->f_seek; ! 323: u.u_io.io.vbase = (vaddr_t) bp; ! 324: u.u_io.io_ioc = n; ! 325: u.u_io.io_flag = (fdp->f_flag & IPNDLY) ? IONDLY : 0; ! 326: if (do_write) { ! 327: iwrite(ip, &u.u_io); ! 328: } else { ! 329: iread(ip, &u.u_io); ! 330: iacc(ip); /* read - atime */ ! 331: } ! 332: n -= u.u_io.io_ioc; ! 333: fdp->f_seek += n; ! 334: if (type != IFCHR) ! 335: iunlock(ip); ! 336: ! 337: /* Was this inode opened for synchronous writes? */ ! 338: if (fdp->f_flag & IPSYNC) ! 339: isync(ip->i_dev); ! 340: ! 341: return n; ! 342: } ! 343: ! 344: /* ! 345: * Return a status structure for the given file name. ! 346: */ ! 347: ustat(np, stp) ! 348: char *np; ! 349: struct stat *stp; ! 350: { ! 351: register INODE *ip; ! 352: struct stat stat; ! 353: ! 354: if (ftoi(np, 'r') != 0) ! 355: return; ! 356: ip = u.u_cdiri; ! 357: istat(ip, &stat); ! 358: idetach(ip); ! 359: kucopy(&stat, stp, sizeof(stat)); ! 360: return 0; ! 361: } ! 362: ! 363: /* ! 364: * Write out all modified buffers, inodes and super blocks to disk. ! 365: */ ! 366: usync() ! 367: { ! 368: register MOUNT *mp; ! 369: static GATE syngate; ! 370: ! 371: lock(syngate); ! 372: for (mp=mountp; mp!=NULL; mp=mp->m_next) ! 373: msync(mp); ! 374: bsync(); ! 375: unlock(syngate); ! 376: return 0; ! 377: } ! 378: ! 379: /* ! 380: * Set the mask for file access. ! 381: */ ! 382: uumask(mask) ! 383: { ! 384: register int omask; ! 385: ! 386: omask = u.u_umask; ! 387: u.u_umask = mask & 0777; ! 388: return (omask); ! 389: } ! 390: ! 391: /* ! 392: * Unmount the given device. ! 393: */ ! 394: uumount(sp) ! 395: char *sp; ! 396: { ! 397: register INODE *ip; ! 398: register MOUNT *mp; ! 399: register MOUNT **mpp; ! 400: register dev_t rdev; ! 401: register int mode; ! 402: ! 403: if (ftoi(sp, 'r') != 0) ! 404: return; ! 405: ip = u.u_cdiri; ! 406: if (iaccess(ip, IPR|IPW) == 0) { ! 407: idetach(ip); ! 408: return; ! 409: } ! 410: rdev = ip->i_a.i_rdev; ! 411: mode = ip->i_mode; ! 412: idetach(ip); ! 413: if ((mode&IFMT) != IFBLK) { ! 414: u.u_error = ENOTBLK; ! 415: return; ! 416: } ! 417: for (mpp=&mountp; (mp=*mpp)!=NULL; mpp=&mp->m_next) ! 418: if (mp->m_dev == rdev) ! 419: break; ! 420: if (mp == NULL) { ! 421: u.u_error = EINVAL; ! 422: return; ! 423: } ! 424: msync(mp); ! 425: for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) { ! 426: if (ip->i_refc>0 && ip->i_dev==rdev) { ! 427: u.u_error = EBUSY; ! 428: return; ! 429: } ! 430: } ! 431: for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) { ! 432: if (ip->i_dev == rdev) ! 433: ip->i_ino = 0; ! 434: } ! 435: bflush(rdev); ! 436: dclose(rdev); ! 437: *mpp = mp->m_next; ! 438: mp->m_ip->i_flag &= ~IFMNT; ! 439: ldetach(mp->m_ip); ! 440: kfree(mp); ! 441: return 0; ! 442: } ! 443: ! 444: /* ! 445: * Unlink the given file. ! 446: */ ! 447: uunlink(np) ! 448: char *np; ! 449: { ! 450: register INODE *ip; ! 451: register dev_t dev; ! 452: ! 453: if (ftoi(np, 'u') != 0) ! 454: return; ! 455: ip = u.u_pdiri; ! 456: if (iaccess(ip, IPW) == 0) { ! 457: u.u_error = EACCES; ! 458: goto err; ! 459: } ! 460: dev = ip->i_dev; ! 461: if (iucheck(dev, u.u_cdirn) == 0) ! 462: goto err; ! 463: idirent(0); ! 464: idetach(ip); ! 465: if ((ip=iattach(dev, u.u_cdirn)) == NULL) ! 466: return; ! 467: if (ip->i_nlink > 0) ! 468: --ip->i_nlink; ! 469: icrt(ip); /* unlink - ctime */ ! 470: if ((ip->i_mode&IFMT)==IFPIPE && ip->i_nlink==0 && ip->i_refc==2) ! 471: pevent(ip); ! 472: err: ! 473: idetach(ip); ! 474: return 0; ! 475: } ! 476: ! 477: /* ! 478: * Set file times. ! 479: */ ! 480: uutime(np, utime) ! 481: char *np; ! 482: time_t utime[2]; ! 483: { ! 484: register INODE *ip; ! 485: time_t stime[2]; ! 486: ! 487: if (ftoi(np, 'r') != 0) ! 488: return; ! 489: ip = u.u_cdiri; ! 490: if (owner(ip->i_uid)) { ! 491: iamc(ip); /* utime - atime/mtime/ctime */ ! 492: if (utime != NULL) { ! 493: ukcopy(utime, stime, sizeof(time_t[2])); ! 494: ip->i_atime = stime[0]; ! 495: ip->i_mtime = stime[1]; ! 496: } ! 497: } ! 498: idetach(ip); ! 499: return 0; ! 500: } ! 501: ! 502: /* ! 503: * Write `n' bytes from buffer `bp' on file number `fd'. ! 504: */ ! 505: uwrite(fd, bp, n) ! 506: char *bp; ! 507: unsigned n; ! 508: { ! 509: return (sysio(fd, bp, n, 1)); ! 510: } ! 511: ! 512: /** ! 513: * ! 514: * int ! 515: * useracc( base, count, mode ) -- determine user accessibility ! 516: * caddr_t base; ! 517: * int count; ! 518: * int mode; ! 519: * ! 520: * Input: base = offset in user data space of the region to be accessed. ! 521: * count = size of access region in bytes. ! 522: * mode = access mode desired [B_READ or B_WRITE]. ! 523: * ! 524: * Action: Verify user has desired access mode into specified region. ! 525: * ! 526: * Return: 0 = permission denied. ! 527: * 1 = access allowed. ! 528: * ! 529: * Notes: Mode is ignored for now, but is required for compatibility ! 530: * with System V, and future protected mode extensions. ! 531: */ ! 532: int ! 533: useracc( base, count, mode ) ! 534: register char *base; ! 535: int mode, count; ! 536: { ! 537: if (base+count < base) { ! 538: return 0; ! 539: } ! 540: return accdata(base, count) || accstack(base, count); ! 541: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.