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