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