Annotation of coherent/d/PS2_KERNEL/coh.386/sys3.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.