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