Annotation of coherent/b/kernel/coh.386/sys3.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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