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

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

unix.superglobalmegacorp.com

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