Annotation of Net2/ufs/ufs_vnops.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  *
                     33:  *     @(#)ufs_vnops.c 7.64 (Berkeley) 5/16/91
1.1.1.2 ! root       34:  *
        !            35:  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
        !            36:  * --------------------         -----   ----------------------
        !            37:  * CURRENT PATCH LEVEL:         2       00026
        !            38:  * --------------------         -----   ----------------------
        !            39:  *
        !            40:  * 27 Nov 92   Bruce Evans             Fixed access()
        !            41:  * 20 Aug 92   David Greenman          Fixed incorrect setting of B_AGE after
        !            42:  *                                     each read to improve cache performance
1.1       root       43:  */
                     44: 
                     45: #include "param.h"
                     46: #include "systm.h"
                     47: #include "namei.h"
                     48: #include "resourcevar.h"
                     49: #include "kernel.h"
                     50: #include "file.h"
                     51: #include "stat.h"
                     52: #include "buf.h"
                     53: #include "proc.h"
                     54: #include "conf.h"
                     55: #include "mount.h"
                     56: #include "vnode.h"
                     57: #include "specdev.h"
                     58: #include "fifo.h"
                     59: #include "malloc.h"
                     60: 
                     61: #include "lockf.h"
                     62: #include "quota.h"
                     63: #include "inode.h"
                     64: #include "dir.h"
                     65: #include "fs.h"
                     66: 
                     67: /*
                     68:  * Create a regular file
                     69:  */
                     70: ufs_create(ndp, vap, p)
                     71:        struct nameidata *ndp;
                     72:        struct vattr *vap;
                     73:        struct proc *p;
                     74: {
                     75:        struct inode *ip;
                     76:        int error;
                     77: 
                     78:        if (error = maknode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip))
                     79:                return (error);
                     80:        ndp->ni_vp = ITOV(ip);
                     81:        return (0);
                     82: }
                     83: 
                     84: /*
                     85:  * Mknod vnode call
                     86:  */
                     87: /* ARGSUSED */
                     88: ufs_mknod(ndp, vap, cred, p)
                     89:        struct nameidata *ndp;
                     90:        struct ucred *cred;
                     91:        struct vattr *vap;
                     92:        struct proc *p;
                     93: {
                     94:        register struct vnode *vp;
                     95:        struct inode *ip;
                     96:        int error;
                     97: 
                     98:        if (error = maknode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip))
                     99:                return (error);
                    100:        ip->i_flag |= IACC|IUPD|ICHG;
                    101:        if (vap->va_rdev != VNOVAL) {
                    102:                /*
                    103:                 * Want to be able to use this to make badblock
                    104:                 * inodes, so don't truncate the dev number.
                    105:                 */
                    106:                ip->i_rdev = vap->va_rdev;
                    107:        }
                    108:        /*
                    109:         * Remove inode so that it will be reloaded by iget and
                    110:         * checked to see if it is an alias of an existing entry
                    111:         * in the inode cache.
                    112:         */
                    113:        vp = ITOV(ip);
                    114:        vput(vp);
                    115:        vp->v_type = VNON;
                    116:        vgone(vp);
                    117:        return (0);
                    118: }
                    119: 
                    120: /*
                    121:  * Open called.
                    122:  *
                    123:  * Nothing to do.
                    124:  */
                    125: /* ARGSUSED */
                    126: ufs_open(vp, mode, cred, p)
                    127:        struct vnode *vp;
                    128:        int mode;
                    129:        struct ucred *cred;
                    130:        struct proc *p;
                    131: {
                    132: 
                    133:        return (0);
                    134: }
                    135: 
                    136: /*
                    137:  * Close called
                    138:  *
                    139:  * Update the times on the inode.
                    140:  */
                    141: /* ARGSUSED */
                    142: ufs_close(vp, fflag, cred, p)
                    143:        struct vnode *vp;
                    144:        int fflag;
                    145:        struct ucred *cred;
                    146:        struct proc *p;
                    147: {
                    148:        register struct inode *ip = VTOI(vp);
                    149: 
                    150:        if (vp->v_usecount > 1 && !(ip->i_flag & ILOCKED))
                    151:                ITIMES(ip, &time, &time);
                    152:        return (0);
                    153: }
                    154: 
                    155: /*
                    156:  * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
                    157:  * The mode is shifted to select the owner/group/other fields. The
                    158:  * super user is granted all permissions.
                    159:  */
                    160: ufs_access(vp, mode, cred, p)
                    161:        struct vnode *vp;
                    162:        register int mode;
                    163:        struct ucred *cred;
                    164:        struct proc *p;
                    165: {
                    166:        register struct inode *ip = VTOI(vp);
                    167:        register gid_t *gp;
                    168:        int i, error;
                    169: 
                    170: #ifdef DIAGNOSTIC
                    171:        if (!VOP_ISLOCKED(vp)) {
                    172:                vprint("ufs_access: not locked", vp);
                    173:                panic("ufs_access: not locked");
                    174:        }
                    175: #endif
                    176: #ifdef QUOTA
                    177:        if (mode & VWRITE) {
                    178:                switch (vp->v_type) {
                    179:                case VREG: case VDIR: case VLNK:
                    180:                        if (error = getinoquota(ip))
                    181:                                return (error);
                    182:                }
                    183:        }
                    184: #endif /* QUOTA */
                    185:        /*
                    186:         * If you're the super-user, you always get access.
                    187:         */
                    188:        if (cred->cr_uid == 0)
                    189:                return (0);
                    190:        /*
                    191:         * Access check is based on only one of owner, group, public.
                    192:         * If not owner, then check group. If not a member of the
                    193:         * group, then check public access.
                    194:         */
                    195:        if (cred->cr_uid != ip->i_uid) {
                    196:                mode >>= 3;
                    197:                gp = cred->cr_groups;
                    198:                for (i = 0; i < cred->cr_ngroups; i++, gp++)
                    199:                        if (ip->i_gid == *gp)
                    200:                                goto found;
                    201:                mode >>= 3;
                    202: found:
                    203:                ;
                    204:        }
1.1.1.2 ! root      205:        if ((ip->i_mode & mode) == mode)
1.1       root      206:                return (0);
                    207:        return (EACCES);
                    208: }
                    209: 
                    210: /* ARGSUSED */
                    211: ufs_getattr(vp, vap, cred, p)
                    212:        struct vnode *vp;
                    213:        register struct vattr *vap;
                    214:        struct ucred *cred;
                    215:        struct proc *p;
                    216: {
                    217:        register struct inode *ip = VTOI(vp);
                    218: 
                    219:        ITIMES(ip, &time, &time);
                    220:        /*
                    221:         * Copy from inode table
                    222:         */
                    223:        vap->va_fsid = ip->i_dev;
                    224:        vap->va_fileid = ip->i_number;
                    225:        vap->va_mode = ip->i_mode & ~IFMT;
                    226:        vap->va_nlink = ip->i_nlink;
                    227:        vap->va_uid = ip->i_uid;
                    228:        vap->va_gid = ip->i_gid;
                    229:        vap->va_rdev = (dev_t)ip->i_rdev;
                    230: #ifdef tahoe
                    231:        vap->va_size = ip->i_size;
                    232:        vap->va_size_rsv = 0;
                    233: #else
                    234:        vap->va_qsize = ip->i_din.di_qsize;
                    235: #endif
                    236:        vap->va_atime.tv_sec = ip->i_atime;
                    237:        vap->va_atime.tv_usec = 0;
                    238:        vap->va_mtime.tv_sec = ip->i_mtime;
                    239:        vap->va_mtime.tv_usec = 0;
                    240:        vap->va_ctime.tv_sec = ip->i_ctime;
                    241:        vap->va_ctime.tv_usec = 0;
                    242:        vap->va_flags = ip->i_flags;
                    243:        vap->va_gen = ip->i_gen;
                    244:        /* this doesn't belong here */
                    245:        if (vp->v_type == VBLK)
                    246:                vap->va_blocksize = BLKDEV_IOSIZE;
                    247:        else if (vp->v_type == VCHR)
                    248:                vap->va_blocksize = MAXBSIZE;
                    249:        else
                    250:                vap->va_blocksize = ip->i_fs->fs_bsize;
                    251:        vap->va_bytes = dbtob(ip->i_blocks);
                    252:        vap->va_bytes_rsv = 0;
                    253:        vap->va_type = vp->v_type;
                    254:        return (0);
                    255: }
                    256: 
                    257: /*
                    258:  * Set attribute vnode op. called from several syscalls
                    259:  */
                    260: ufs_setattr(vp, vap, cred, p)
                    261:        register struct vnode *vp;
                    262:        register struct vattr *vap;
                    263:        register struct ucred *cred;
                    264:        struct proc *p;
                    265: {
                    266:        register struct inode *ip = VTOI(vp);
                    267:        int error = 0;
                    268: 
                    269:        /*
                    270:         * Check for unsetable attributes.
                    271:         */
                    272:        if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
                    273:            (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
                    274:            (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
                    275:            ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
                    276:                return (EINVAL);
                    277:        }
                    278:        /*
                    279:         * Go through the fields and update iff not VNOVAL.
                    280:         */
                    281:        if (vap->va_uid != (u_short)VNOVAL || vap->va_gid != (u_short)VNOVAL)
                    282:                if (error = chown1(vp, vap->va_uid, vap->va_gid, p))
                    283:                        return (error);
                    284:        if (vap->va_size != VNOVAL) {
                    285:                if (vp->v_type == VDIR)
                    286:                        return (EISDIR);
                    287:                if (error = itrunc(ip, vap->va_size, 0)) /* XXX IO_SYNC? */
                    288:                        return (error);
                    289:        }
                    290:        if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
                    291:                if (cred->cr_uid != ip->i_uid &&
                    292:                    (error = suser(cred, &p->p_acflag)))
                    293:                        return (error);
                    294:                if (vap->va_atime.tv_sec != VNOVAL)
                    295:                        ip->i_flag |= IACC;
                    296:                if (vap->va_mtime.tv_sec != VNOVAL)
                    297:                        ip->i_flag |= IUPD;
                    298:                ip->i_flag |= ICHG;
                    299:                if (error = iupdat(ip, &vap->va_atime, &vap->va_mtime, 1))
                    300:                        return (error);
                    301:        }
                    302:        if (vap->va_mode != (u_short)VNOVAL)
                    303:                error = chmod1(vp, (int)vap->va_mode, p);
                    304:        if (vap->va_flags != VNOVAL) {
                    305:                if (cred->cr_uid != ip->i_uid &&
                    306:                    (error = suser(cred, &p->p_acflag)))
                    307:                        return (error);
                    308:                if (cred->cr_uid == 0) {
                    309:                        ip->i_flags = vap->va_flags;
                    310:                } else {
                    311:                        ip->i_flags &= 0xffff0000;
                    312:                        ip->i_flags |= (vap->va_flags & 0xffff);
                    313:                }
                    314:                ip->i_flag |= ICHG;
                    315:        }
                    316:        return (error);
                    317: }
                    318: 
                    319: /*
                    320:  * Change the mode on a file.
                    321:  * Inode must be locked before calling.
                    322:  */
                    323: chmod1(vp, mode, p)
                    324:        register struct vnode *vp;
                    325:        register int mode;
                    326:        struct proc *p;
                    327: {
                    328:        register struct ucred *cred = p->p_ucred;
                    329:        register struct inode *ip = VTOI(vp);
                    330:        int error;
                    331: 
                    332:        if (cred->cr_uid != ip->i_uid &&
                    333:            (error = suser(cred, &p->p_acflag)))
                    334:                return (error);
                    335:        if (cred->cr_uid) {
                    336:                if (vp->v_type != VDIR && (mode & ISVTX))
                    337:                        return (EFTYPE);
                    338:                if (!groupmember(ip->i_gid, cred) && (mode & ISGID))
                    339:                        return (EPERM);
                    340:        }
                    341:        ip->i_mode &= ~07777;
                    342:        ip->i_mode |= mode & 07777;
                    343:        ip->i_flag |= ICHG;
                    344:        if ((vp->v_flag & VTEXT) && (ip->i_mode & ISVTX) == 0)
                    345:                (void) vnode_pager_uncache(vp);
                    346:        return (0);
                    347: }
                    348: 
                    349: /*
                    350:  * Perform chown operation on inode ip;
                    351:  * inode must be locked prior to call.
                    352:  */
                    353: chown1(vp, uid, gid, p)
                    354:        register struct vnode *vp;
                    355:        uid_t uid;
                    356:        gid_t gid;
                    357:        struct proc *p;
                    358: {
                    359:        register struct inode *ip = VTOI(vp);
                    360:        register struct ucred *cred = p->p_ucred;
                    361:        uid_t ouid;
                    362:        gid_t ogid;
                    363:        int error = 0;
                    364: #ifdef QUOTA
                    365:        register int i;
                    366:        long change;
                    367: #endif
                    368: 
                    369:        if (uid == (u_short)VNOVAL)
                    370:                uid = ip->i_uid;
                    371:        if (gid == (u_short)VNOVAL)
                    372:                gid = ip->i_gid;
                    373:        /*
                    374:         * If we don't own the file, are trying to change the owner
                    375:         * of the file, or are not a member of the target group,
                    376:         * the caller must be superuser or the call fails.
                    377:         */
                    378:        if ((cred->cr_uid != ip->i_uid || uid != ip->i_uid ||
                    379:            !groupmember((gid_t)gid, cred)) &&
                    380:            (error = suser(cred, &p->p_acflag)))
                    381:                return (error);
                    382:        ouid = ip->i_uid;
                    383:        ogid = ip->i_gid;
                    384: #ifdef QUOTA
                    385:        if (error = getinoquota(ip))
                    386:                return (error);
                    387:        if (ouid == uid) {
                    388:                dqrele(vp, ip->i_dquot[USRQUOTA]);
                    389:                ip->i_dquot[USRQUOTA] = NODQUOT;
                    390:        }
                    391:        if (ogid == gid) {
                    392:                dqrele(vp, ip->i_dquot[GRPQUOTA]);
                    393:                ip->i_dquot[GRPQUOTA] = NODQUOT;
                    394:        }
                    395:        change = ip->i_blocks;
                    396:        (void) chkdq(ip, -change, cred, CHOWN);
                    397:        (void) chkiq(ip, -1, cred, CHOWN);
                    398:        for (i = 0; i < MAXQUOTAS; i++) {
                    399:                dqrele(vp, ip->i_dquot[i]);
                    400:                ip->i_dquot[i] = NODQUOT;
                    401:        }
                    402: #endif
                    403:        ip->i_uid = uid;
                    404:        ip->i_gid = gid;
                    405: #ifdef QUOTA
                    406:        if ((error = getinoquota(ip)) == 0) {
                    407:                if (ouid == uid) {
                    408:                        dqrele(vp, ip->i_dquot[USRQUOTA]);
                    409:                        ip->i_dquot[USRQUOTA] = NODQUOT;
                    410:                }
                    411:                if (ogid == gid) {
                    412:                        dqrele(vp, ip->i_dquot[GRPQUOTA]);
                    413:                        ip->i_dquot[GRPQUOTA] = NODQUOT;
                    414:                }
                    415:                if ((error = chkdq(ip, change, cred, CHOWN)) == 0) {
                    416:                        if ((error = chkiq(ip, 1, cred, CHOWN)) == 0)
                    417:                                goto good;
                    418:                        else
                    419:                                (void) chkdq(ip, -change, cred, CHOWN|FORCE);
                    420:                }
                    421:                for (i = 0; i < MAXQUOTAS; i++) {
                    422:                        dqrele(vp, ip->i_dquot[i]);
                    423:                        ip->i_dquot[i] = NODQUOT;
                    424:                }
                    425:        }
                    426:        ip->i_uid = ouid;
                    427:        ip->i_gid = ogid;
                    428:        if (getinoquota(ip) == 0) {
                    429:                if (ouid == uid) {
                    430:                        dqrele(vp, ip->i_dquot[USRQUOTA]);
                    431:                        ip->i_dquot[USRQUOTA] = NODQUOT;
                    432:                }
                    433:                if (ogid == gid) {
                    434:                        dqrele(vp, ip->i_dquot[GRPQUOTA]);
                    435:                        ip->i_dquot[GRPQUOTA] = NODQUOT;
                    436:                }
                    437:                (void) chkdq(ip, change, cred, FORCE|CHOWN);
                    438:                (void) chkiq(ip, 1, cred, FORCE|CHOWN);
                    439:                (void) getinoquota(ip);
                    440:        }
                    441:        return (error);
                    442: good:
                    443:        if (getinoquota(ip))
                    444:                panic("chown: lost quota");
                    445: #endif /* QUOTA */
                    446:        if (ouid != uid || ogid != gid)
                    447:                ip->i_flag |= ICHG;
                    448:        if (ouid != uid && cred->cr_uid != 0)
                    449:                ip->i_mode &= ~ISUID;
                    450:        if (ogid != gid && cred->cr_uid != 0)
                    451:                ip->i_mode &= ~ISGID;
                    452:        return (0);
                    453: }
                    454: 
                    455: /*
                    456:  * Vnode op for reading.
                    457:  */
                    458: /* ARGSUSED */
                    459: ufs_read(vp, uio, ioflag, cred)
                    460:        struct vnode *vp;
                    461:        register struct uio *uio;
                    462:        int ioflag;
                    463:        struct ucred *cred;
                    464: {
                    465:        register struct inode *ip = VTOI(vp);
                    466:        register struct fs *fs;
                    467:        struct buf *bp;
                    468:        daddr_t lbn, bn, rablock;
                    469:        int size, diff, error = 0;
                    470:        long n, on, type;
                    471: 
                    472: #ifdef DIAGNOSTIC
                    473:        if (uio->uio_rw != UIO_READ)
                    474:                panic("ufs_read mode");
                    475:        type = ip->i_mode & IFMT;
                    476:        if (type != IFDIR && type != IFREG && type != IFLNK)
                    477:                panic("ufs_read type");
                    478: #endif
                    479:        if (uio->uio_resid == 0)
                    480:                return (0);
                    481:        if (uio->uio_offset < 0)
                    482:                return (EINVAL);
                    483:        ip->i_flag |= IACC;
                    484:        fs = ip->i_fs;
                    485:        do {
                    486:                lbn = lblkno(fs, uio->uio_offset);
                    487:                on = blkoff(fs, uio->uio_offset);
                    488:                n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid);
                    489:                diff = ip->i_size - uio->uio_offset;
                    490:                if (diff <= 0)
                    491:                        return (0);
                    492:                if (diff < n)
                    493:                        n = diff;
                    494:                size = blksize(fs, ip, lbn);
                    495:                rablock = lbn + 1;
                    496:                if (vp->v_lastr + 1 == lbn &&
                    497:                    lblktosize(fs, rablock) < ip->i_size)
                    498:                        error = breada(ITOV(ip), lbn, size, rablock,
                    499:                                blksize(fs, ip, rablock), NOCRED, &bp);
                    500:                else
                    501:                        error = bread(ITOV(ip), lbn, size, NOCRED, &bp);
                    502:                vp->v_lastr = lbn;
                    503:                n = MIN(n, size - bp->b_resid);
                    504:                if (error) {
                    505:                        brelse(bp);
                    506:                        return (error);
                    507:                }
                    508:                error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
1.1.1.2 ! root      509: #if OMIT       /* 20 Aug 92*/
1.1       root      510:                if (n + on == fs->fs_bsize || uio->uio_offset == ip->i_size)
                    511:                        bp->b_flags |= B_AGE;
1.1.1.2 ! root      512: #endif /* OMIT*/
1.1       root      513:                brelse(bp);
                    514:        } while (error == 0 && uio->uio_resid > 0 && n != 0);
                    515:        return (error);
                    516: }
                    517: 
                    518: /*
                    519:  * Vnode op for writing.
                    520:  */
                    521: ufs_write(vp, uio, ioflag, cred)
                    522:        register struct vnode *vp;
                    523:        struct uio *uio;
                    524:        int ioflag;
                    525:        struct ucred *cred;
                    526: {
                    527:        struct proc *p = uio->uio_procp;
                    528:        register struct inode *ip = VTOI(vp);
                    529:        register struct fs *fs;
                    530:        struct buf *bp;
                    531:        daddr_t lbn, bn;
                    532:        u_long osize;
                    533:        int n, on, flags;
                    534:        int size, resid, error = 0;
                    535: 
                    536: #ifdef DIAGNOSTIC
                    537:        if (uio->uio_rw != UIO_WRITE)
                    538:                panic("ufs_write mode");
                    539: #endif
                    540:        switch (vp->v_type) {
                    541:        case VREG:
                    542:                if (ioflag & IO_APPEND)
                    543:                        uio->uio_offset = ip->i_size;
                    544:                /* fall through */
                    545:        case VLNK:
                    546:                break;
                    547: 
                    548:        case VDIR:
                    549:                if ((ioflag & IO_SYNC) == 0)
                    550:                        panic("ufs_write nonsync dir write");
                    551:                break;
                    552: 
                    553:        default:
                    554:                panic("ufs_write type");
                    555:        }
                    556:        if (uio->uio_offset < 0)
                    557:                return (EINVAL);
                    558:        if (uio->uio_resid == 0)
                    559:                return (0);
                    560:        /*
                    561:         * Maybe this should be above the vnode op call, but so long as
                    562:         * file servers have no limits, i don't think it matters
                    563:         */
                    564:        if (vp->v_type == VREG && p &&
                    565:            uio->uio_offset + uio->uio_resid >
                    566:              p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
                    567:                psignal(p, SIGXFSZ);
                    568:                return (EFBIG);
                    569:        }
                    570:        resid = uio->uio_resid;
                    571:        osize = ip->i_size;
                    572:        fs = ip->i_fs;
                    573:        flags = 0;
                    574:        if (ioflag & IO_SYNC)
                    575:                flags = B_SYNC;
                    576:        do {
                    577:                lbn = lblkno(fs, uio->uio_offset);
                    578:                on = blkoff(fs, uio->uio_offset);
                    579:                n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid);
                    580:                if (n < fs->fs_bsize)
                    581:                        flags |= B_CLRBUF;
                    582:                else
                    583:                        flags &= ~B_CLRBUF;
                    584:                if (error = balloc(ip, lbn, (int)(on + n), &bp, flags))
                    585:                        break;
                    586:                bn = bp->b_blkno;
                    587:                if (uio->uio_offset + n > ip->i_size) {
                    588:                        ip->i_size = uio->uio_offset + n;
                    589:                        vnode_pager_setsize(vp, ip->i_size);
                    590:                }
                    591:                size = blksize(fs, ip, lbn);
                    592:                (void) vnode_pager_uncache(vp);
                    593:                n = MIN(n, size - bp->b_resid);
                    594:                error = uiomove(bp->b_un.b_addr + on, n, uio);
                    595:                if (ioflag & IO_SYNC)
                    596:                        (void) bwrite(bp);
                    597:                else if (n + on == fs->fs_bsize) {
                    598:                        bp->b_flags |= B_AGE;
                    599:                        bawrite(bp);
                    600:                } else
                    601:                        bdwrite(bp);
                    602:                ip->i_flag |= IUPD|ICHG;
                    603:                if (cred->cr_uid != 0)
                    604:                        ip->i_mode &= ~(ISUID|ISGID);
                    605:        } while (error == 0 && uio->uio_resid > 0 && n != 0);
                    606:        if (error && (ioflag & IO_UNIT)) {
                    607:                (void) itrunc(ip, osize, ioflag & IO_SYNC);
                    608:                uio->uio_offset -= resid - uio->uio_resid;
                    609:                uio->uio_resid = resid;
                    610:        }
                    611:        if (!error && (ioflag & IO_SYNC))
                    612:                error = iupdat(ip, &time, &time, 1);
                    613:        return (error);
                    614: }
                    615: 
                    616: /* ARGSUSED */
                    617: ufs_ioctl(vp, com, data, fflag, cred, p)
                    618:        struct vnode *vp;
                    619:        int com;
                    620:        caddr_t data;
                    621:        int fflag;
                    622:        struct ucred *cred;
                    623:        struct proc *p;
                    624: {
                    625: 
                    626:        return (ENOTTY);
                    627: }
                    628: 
                    629: /* ARGSUSED */
                    630: ufs_select(vp, which, fflags, cred, p)
                    631:        struct vnode *vp;
                    632:        int which, fflags;
                    633:        struct ucred *cred;
                    634:        struct proc *p;
                    635: {
                    636: 
                    637:        /*
                    638:         * We should really check to see if I/O is possible.
                    639:         */
                    640:        return (1);
                    641: }
                    642: 
                    643: /*
                    644:  * Mmap a file
                    645:  *
                    646:  * NB Currently unsupported.
                    647:  */
                    648: /* ARGSUSED */
                    649: ufs_mmap(vp, fflags, cred, p)
                    650:        struct vnode *vp;
                    651:        int fflags;
                    652:        struct ucred *cred;
                    653:        struct proc *p;
                    654: {
                    655: 
                    656:        return (EINVAL);
                    657: }
                    658: 
                    659: /*
                    660:  * Synch an open file.
                    661:  */
                    662: /* ARGSUSED */
                    663: ufs_fsync(vp, fflags, cred, waitfor, p)
                    664:        struct vnode *vp;
                    665:        int fflags;
                    666:        struct ucred *cred;
                    667:        int waitfor;
                    668:        struct proc *p;
                    669: {
                    670:        struct inode *ip = VTOI(vp);
                    671: 
                    672:        if (fflags & FWRITE)
                    673:                ip->i_flag |= ICHG;
                    674:        vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0);
                    675:        return (iupdat(ip, &time, &time, waitfor == MNT_WAIT));
                    676: }
                    677: 
                    678: /*
                    679:  * Seek on a file
                    680:  *
                    681:  * Nothing to do, so just return.
                    682:  */
                    683: /* ARGSUSED */
                    684: ufs_seek(vp, oldoff, newoff, cred)
                    685:        struct vnode *vp;
                    686:        off_t oldoff, newoff;
                    687:        struct ucred *cred;
                    688: {
                    689: 
                    690:        return (0);
                    691: }
                    692: 
                    693: /*
                    694:  * ufs remove
                    695:  * Hard to avoid races here, especially
                    696:  * in unlinking directories.
                    697:  */
                    698: ufs_remove(ndp, p)
                    699:        struct nameidata *ndp;
                    700:        struct proc *p;
                    701: {
                    702:        register struct inode *ip, *dp;
                    703:        int error;
                    704: 
                    705:        ip = VTOI(ndp->ni_vp);
                    706:        dp = VTOI(ndp->ni_dvp);
                    707:        error = dirremove(ndp);
                    708:        if (!error) {
                    709:                ip->i_nlink--;
                    710:                ip->i_flag |= ICHG;
                    711:        }
                    712:        if (dp == ip)
                    713:                vrele(ITOV(ip));
                    714:        else
                    715:                iput(ip);
                    716:        iput(dp);
                    717:        return (error);
                    718: }
                    719: 
                    720: /*
                    721:  * link vnode call
                    722:  */
                    723: ufs_link(vp, ndp, p)
                    724:        register struct vnode *vp;
                    725:        register struct nameidata *ndp;
                    726:        struct proc *p;
                    727: {
                    728:        register struct inode *ip = VTOI(vp);
                    729:        int error;
                    730: 
                    731: #ifdef DIANOSTIC
                    732:        if ((ndp->ni_nameiop & HASBUF) == 0)
                    733:                panic("ufs_link: no name");
                    734: #endif
                    735:        if ((unsigned short)ip->i_nlink >= LINK_MAX) {
                    736:                free(ndp->ni_pnbuf, M_NAMEI);
                    737:                return (EMLINK);
                    738:        }
                    739:        if (ndp->ni_dvp != vp)
                    740:                ILOCK(ip);
                    741:        ip->i_nlink++;
                    742:        ip->i_flag |= ICHG;
                    743:        error = iupdat(ip, &time, &time, 1);
                    744:        if (!error)
                    745:                error = direnter(ip, ndp);
                    746:        if (ndp->ni_dvp != vp)
                    747:                IUNLOCK(ip);
                    748:        FREE(ndp->ni_pnbuf, M_NAMEI);
                    749:        vput(ndp->ni_dvp);
                    750:        if (error) {
                    751:                ip->i_nlink--;
                    752:                ip->i_flag |= ICHG;
                    753:        }
                    754:        return (error);
                    755: }
                    756: 
                    757: /*
                    758:  * Rename system call.
                    759:  *     rename("foo", "bar");
                    760:  * is essentially
                    761:  *     unlink("bar");
                    762:  *     link("foo", "bar");
                    763:  *     unlink("foo");
                    764:  * but ``atomically''.  Can't do full commit without saving state in the
                    765:  * inode on disk which isn't feasible at this time.  Best we can do is
                    766:  * always guarantee the target exists.
                    767:  *
                    768:  * Basic algorithm is:
                    769:  *
                    770:  * 1) Bump link count on source while we're linking it to the
                    771:  *    target.  This also ensure the inode won't be deleted out
                    772:  *    from underneath us while we work (it may be truncated by
                    773:  *    a concurrent `trunc' or `open' for creation).
                    774:  * 2) Link source to destination.  If destination already exists,
                    775:  *    delete it first.
                    776:  * 3) Unlink source reference to inode if still around. If a
                    777:  *    directory was moved and the parent of the destination
                    778:  *    is different from the source, patch the ".." entry in the
                    779:  *    directory.
                    780:  */
                    781: ufs_rename(fndp, tndp, p)
                    782:        register struct nameidata *fndp, *tndp;
                    783:        struct proc *p;
                    784: {
                    785:        register struct inode *ip, *xp, *dp;
                    786:        struct dirtemplate dirbuf;
                    787:        int doingdirectory = 0, oldparent = 0, newparent = 0;
                    788:        int error = 0;
                    789: 
                    790: #ifdef DIANOSTIC
                    791:        if ((tndp->ni_nameiop & HASBUF) == 0 ||
                    792:            (fndp->ni_nameiop & HASBUF) == 0)
                    793:                panic("ufs_rename: no name");
                    794: #endif
                    795:        dp = VTOI(fndp->ni_dvp);
                    796:        ip = VTOI(fndp->ni_vp);
                    797:        /*
                    798:         * Check if just deleting a link name.
                    799:         */
                    800:        if (fndp->ni_vp == tndp->ni_vp) {
                    801:                VOP_ABORTOP(tndp);
                    802:                vput(tndp->ni_dvp);
                    803:                vput(tndp->ni_vp);
                    804:                vrele(fndp->ni_dvp);
                    805:                if ((ip->i_mode&IFMT) == IFDIR) {
                    806:                        VOP_ABORTOP(fndp);
                    807:                        vrele(fndp->ni_vp);
                    808:                        return (EINVAL);
                    809:                }
                    810:                doingdirectory = 0;
                    811:                goto unlinkit;
                    812:        }
                    813:        ILOCK(ip);
                    814:        if ((ip->i_mode&IFMT) == IFDIR) {
                    815:                /*
                    816:                 * Avoid ".", "..", and aliases of "." for obvious reasons.
                    817:                 */
                    818:                if ((fndp->ni_namelen == 1 && fndp->ni_ptr[0] == '.') ||
                    819:                    dp == ip || fndp->ni_isdotdot || (ip->i_flag & IRENAME)) {
                    820:                        VOP_ABORTOP(tndp);
                    821:                        vput(tndp->ni_dvp);
                    822:                        if (tndp->ni_vp)
                    823:                                vput(tndp->ni_vp);
                    824:                        VOP_ABORTOP(fndp);
                    825:                        vrele(fndp->ni_dvp);
                    826:                        vput(fndp->ni_vp);
                    827:                        return (EINVAL);
                    828:                }
                    829:                ip->i_flag |= IRENAME;
                    830:                oldparent = dp->i_number;
                    831:                doingdirectory++;
                    832:        }
                    833:        vrele(fndp->ni_dvp);
                    834: 
                    835:        /*
                    836:         * 1) Bump link count while we're moving stuff
                    837:         *    around.  If we crash somewhere before
                    838:         *    completing our work, the link count
                    839:         *    may be wrong, but correctable.
                    840:         */
                    841:        ip->i_nlink++;
                    842:        ip->i_flag |= ICHG;
                    843:        error = iupdat(ip, &time, &time, 1);
                    844:        IUNLOCK(ip);
                    845: 
                    846:        /*
                    847:         * When the target exists, both the directory
                    848:         * and target vnodes are returned locked.
                    849:         */
                    850:        dp = VTOI(tndp->ni_dvp);
                    851:        xp = NULL;
                    852:        if (tndp->ni_vp)
                    853:                xp = VTOI(tndp->ni_vp);
                    854:        /*
                    855:         * If ".." must be changed (ie the directory gets a new
                    856:         * parent) then the source directory must not be in the
                    857:         * directory heirarchy above the target, as this would
                    858:         * orphan everything below the source directory. Also
                    859:         * the user must have write permission in the source so
                    860:         * as to be able to change "..". We must repeat the call 
                    861:         * to namei, as the parent directory is unlocked by the
                    862:         * call to checkpath().
                    863:         */
                    864:        if (oldparent != dp->i_number)
                    865:                newparent = dp->i_number;
                    866:        if (doingdirectory && newparent) {
                    867:                VOP_LOCK(fndp->ni_vp);
                    868:                error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred, p);
                    869:                VOP_UNLOCK(fndp->ni_vp);
                    870:                if (error)
                    871:                        goto bad;
                    872:                if (xp != NULL)
                    873:                        iput(xp);
                    874:                if (error = checkpath(ip, dp, tndp->ni_cred))
                    875:                        goto out;
                    876:                if ((tndp->ni_nameiop & SAVESTART) == 0)
                    877:                        panic("ufs_rename: lost to startdir");
                    878:                if (error = lookup(tndp, p))
                    879:                        goto out;
                    880:                dp = VTOI(tndp->ni_dvp);
                    881:                xp = NULL;
                    882:                if (tndp->ni_vp)
                    883:                        xp = VTOI(tndp->ni_vp);
                    884:        }
                    885:        /*
                    886:         * 2) If target doesn't exist, link the target
                    887:         *    to the source and unlink the source. 
                    888:         *    Otherwise, rewrite the target directory
                    889:         *    entry to reference the source inode and
                    890:         *    expunge the original entry's existence.
                    891:         */
                    892:        if (xp == NULL) {
                    893:                if (dp->i_dev != ip->i_dev)
                    894:                        panic("rename: EXDEV");
                    895:                /*
                    896:                 * Account for ".." in new directory.
                    897:                 * When source and destination have the same
                    898:                 * parent we don't fool with the link count.
                    899:                 */
                    900:                if (doingdirectory && newparent) {
                    901:                        if ((unsigned short)dp->i_nlink >= LINK_MAX) {
                    902:                                error = EMLINK;
                    903:                                goto bad;
                    904:                        }
                    905:                        dp->i_nlink++;
                    906:                        dp->i_flag |= ICHG;
                    907:                        if (error = iupdat(dp, &time, &time, 1))
                    908:                                goto bad;
                    909:                }
                    910:                if (error = direnter(ip, tndp)) {
                    911:                        if (doingdirectory && newparent) {
                    912:                                dp->i_nlink--;
                    913:                                dp->i_flag |= ICHG;
                    914:                                (void) iupdat(dp, &time, &time, 1);
                    915:                        }
                    916:                        goto bad;
                    917:                }
                    918:                iput(dp);
                    919:        } else {
                    920:                if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
                    921:                        panic("rename: EXDEV");
                    922:                /*
                    923:                 * Short circuit rename(foo, foo).
                    924:                 */
                    925:                if (xp->i_number == ip->i_number)
                    926:                        panic("rename: same file");
                    927:                /*
                    928:                 * If the parent directory is "sticky", then the user must
                    929:                 * own the parent directory, or the destination of the rename,
                    930:                 * otherwise the destination may not be changed (except by
                    931:                 * root). This implements append-only directories.
                    932:                 */
                    933:                if ((dp->i_mode & ISVTX) && tndp->ni_cred->cr_uid != 0 &&
                    934:                    tndp->ni_cred->cr_uid != dp->i_uid &&
                    935:                    xp->i_uid != tndp->ni_cred->cr_uid) {
                    936:                        error = EPERM;
                    937:                        goto bad;
                    938:                }
                    939:                /*
                    940:                 * Target must be empty if a directory and have no links
                    941:                 * to it. Also, ensure source and target are compatible
                    942:                 * (both directories, or both not directories).
                    943:                 */
                    944:                if ((xp->i_mode&IFMT) == IFDIR) {
                    945:                        if (!dirempty(xp, dp->i_number, tndp->ni_cred) || 
                    946:                            xp->i_nlink > 2) {
                    947:                                error = ENOTEMPTY;
                    948:                                goto bad;
                    949:                        }
                    950:                        if (!doingdirectory) {
                    951:                                error = ENOTDIR;
                    952:                                goto bad;
                    953:                        }
                    954:                        cache_purge(ITOV(dp));
                    955:                } else if (doingdirectory) {
                    956:                        error = EISDIR;
                    957:                        goto bad;
                    958:                }
                    959:                if (error = dirrewrite(dp, ip, tndp))
                    960:                        goto bad;
                    961:                /*
                    962:                 * If the target directory is in the same
                    963:                 * directory as the source directory,
                    964:                 * decrement the link count on the parent
                    965:                 * of the target directory.
                    966:                 */
                    967:                 if (doingdirectory && !newparent) {
                    968:                        dp->i_nlink--;
                    969:                        dp->i_flag |= ICHG;
                    970:                }
                    971:                vput(ITOV(dp));
                    972:                /*
                    973:                 * Adjust the link count of the target to
                    974:                 * reflect the dirrewrite above.  If this is
                    975:                 * a directory it is empty and there are
                    976:                 * no links to it, so we can squash the inode and
                    977:                 * any space associated with it.  We disallowed
                    978:                 * renaming over top of a directory with links to
                    979:                 * it above, as the remaining link would point to
                    980:                 * a directory without "." or ".." entries.
                    981:                 */
                    982:                xp->i_nlink--;
                    983:                if (doingdirectory) {
                    984:                        if (--xp->i_nlink != 0)
                    985:                                panic("rename: linked directory");
                    986:                        error = itrunc(xp, (u_long)0, IO_SYNC);
                    987:                }
                    988:                xp->i_flag |= ICHG;
                    989:                iput(xp);
                    990:                xp = NULL;
                    991:        }
                    992: 
                    993:        /*
                    994:         * 3) Unlink the source.
                    995:         */
                    996: unlinkit:
                    997:        fndp->ni_nameiop &= ~MODMASK;
                    998:        fndp->ni_nameiop |= LOCKPARENT | LOCKLEAF;
                    999:        if ((fndp->ni_nameiop & SAVESTART) == 0)
                   1000:                panic("ufs_rename: lost from startdir");
                   1001:        (void) lookup(fndp, p);
                   1002:        if (fndp->ni_vp != NULL) {
                   1003:                xp = VTOI(fndp->ni_vp);
                   1004:                dp = VTOI(fndp->ni_dvp);
                   1005:        } else {
                   1006:                /*
                   1007:                 * From name has disappeared.
                   1008:                 */
                   1009:                if (doingdirectory)
                   1010:                        panic("rename: lost dir entry");
                   1011:                vrele(ITOV(ip));
                   1012:                return (0);
                   1013:        }
                   1014:        /*
                   1015:         * Ensure that the directory entry still exists and has not
                   1016:         * changed while the new name has been entered. If the source is
                   1017:         * a file then the entry may have been unlinked or renamed. In
                   1018:         * either case there is no further work to be done. If the source
                   1019:         * is a directory then it cannot have been rmdir'ed; its link
                   1020:         * count of three would cause a rmdir to fail with ENOTEMPTY.
                   1021:         * The IRENAME flag ensures that it cannot be moved by another
                   1022:         * rename.
                   1023:         */
                   1024:        if (xp != ip) {
                   1025:                if (doingdirectory)
                   1026:                        panic("rename: lost dir entry");
                   1027:        } else {
                   1028:                /*
                   1029:                 * If the source is a directory with a
                   1030:                 * new parent, the link count of the old
                   1031:                 * parent directory must be decremented
                   1032:                 * and ".." set to point to the new parent.
                   1033:                 */
                   1034:                if (doingdirectory && newparent) {
                   1035:                        dp->i_nlink--;
                   1036:                        dp->i_flag |= ICHG;
                   1037:                        error = vn_rdwr(UIO_READ, ITOV(xp), (caddr_t)&dirbuf,
                   1038:                                sizeof (struct dirtemplate), (off_t)0,
                   1039:                                UIO_SYSSPACE, IO_NODELOCKED, 
                   1040:                                tndp->ni_cred, (int *)0, (struct proc *)0);
                   1041:                        if (error == 0) {
                   1042:                                if (dirbuf.dotdot_namlen != 2 ||
                   1043:                                    dirbuf.dotdot_name[0] != '.' ||
                   1044:                                    dirbuf.dotdot_name[1] != '.') {
                   1045:                                        dirbad(xp, 12, "rename: mangled dir");
                   1046:                                } else {
                   1047:                                        dirbuf.dotdot_ino = newparent;
                   1048:                                        (void) vn_rdwr(UIO_WRITE, ITOV(xp),
                   1049:                                            (caddr_t)&dirbuf,
                   1050:                                            sizeof (struct dirtemplate),
                   1051:                                            (off_t)0, UIO_SYSSPACE,
                   1052:                                            IO_NODELOCKED|IO_SYNC,
                   1053:                                            tndp->ni_cred, (int *)0,
                   1054:                                            (struct proc *)0);
                   1055:                                        cache_purge(ITOV(dp));
                   1056:                                }
                   1057:                        }
                   1058:                }
                   1059:                error = dirremove(fndp);
                   1060:                if (!error) {
                   1061:                        xp->i_nlink--;
                   1062:                        xp->i_flag |= ICHG;
                   1063:                }
                   1064:                xp->i_flag &= ~IRENAME;
                   1065:        }
                   1066:        if (dp)
                   1067:                vput(ITOV(dp));
                   1068:        if (xp)
                   1069:                vput(ITOV(xp));
                   1070:        vrele(ITOV(ip));
                   1071:        return (error);
                   1072: 
                   1073: bad:
                   1074:        if (xp)
                   1075:                vput(ITOV(xp));
                   1076:        vput(ITOV(dp));
                   1077: out:
                   1078:        ip->i_nlink--;
                   1079:        ip->i_flag |= ICHG;
                   1080:        vrele(ITOV(ip));
                   1081:        return (error);
                   1082: }
                   1083: 
                   1084: /*
                   1085:  * A virgin directory (no blushing please).
                   1086:  */
                   1087: struct dirtemplate mastertemplate = {
                   1088:        0, 12, 1, ".",
                   1089:        0, DIRBLKSIZ - 12, 2, ".."
                   1090: };
                   1091: 
                   1092: /*
                   1093:  * Mkdir system call
                   1094:  */
                   1095: ufs_mkdir(ndp, vap, p)
                   1096:        struct nameidata *ndp;
                   1097:        struct vattr *vap;
                   1098:        struct proc *p;
                   1099: {
                   1100:        register struct inode *ip, *dp;
                   1101:        struct inode *tip;
                   1102:        struct vnode *dvp;
                   1103:        struct dirtemplate dirtemplate;
                   1104:        int error;
                   1105:        int dmode;
                   1106: 
                   1107: #ifdef DIANOSTIC
                   1108:        if ((ndp->ni_nameiop & HASBUF) == 0)
                   1109:                panic("ufs_mkdir: no name");
                   1110: #endif
                   1111:        dvp = ndp->ni_dvp;
                   1112:        dp = VTOI(dvp);
                   1113:        if ((unsigned short)dp->i_nlink >= LINK_MAX) {
                   1114:                free(ndp->ni_pnbuf, M_NAMEI);
                   1115:                iput(dp);
                   1116:                return (EMLINK);
                   1117:        }
                   1118:        dmode = vap->va_mode&0777;
                   1119:        dmode |= IFDIR;
                   1120:        /*
                   1121:         * Must simulate part of maknode here to acquire the inode, but
                   1122:         * not have it entered in the parent directory. The entry is made
                   1123:         * later after writing "." and ".." entries.
                   1124:         */
                   1125:        if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
                   1126:                free(ndp->ni_pnbuf, M_NAMEI);
                   1127:                iput(dp);
                   1128:                return (error);
                   1129:        }
                   1130:        ip = tip;
                   1131:        ip->i_uid = ndp->ni_cred->cr_uid;
                   1132:        ip->i_gid = dp->i_gid;
                   1133: #ifdef QUOTA
                   1134:        if ((error = getinoquota(ip)) ||
                   1135:            (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
                   1136:                free(ndp->ni_pnbuf, M_NAMEI);
                   1137:                ifree(ip, ip->i_number, dmode);
                   1138:                iput(ip);
                   1139:                iput(dp);
                   1140:                return (error);
                   1141:        }
                   1142: #endif
                   1143:        ip->i_flag |= IACC|IUPD|ICHG;
                   1144:        ip->i_mode = dmode;
                   1145:        ITOV(ip)->v_type = VDIR;        /* Rest init'd in iget() */
                   1146:        ip->i_nlink = 2;
                   1147:        error = iupdat(ip, &time, &time, 1);
                   1148: 
                   1149:        /*
                   1150:         * Bump link count in parent directory
                   1151:         * to reflect work done below.  Should
                   1152:         * be done before reference is created
                   1153:         * so reparation is possible if we crash.
                   1154:         */
                   1155:        dp->i_nlink++;
                   1156:        dp->i_flag |= ICHG;
                   1157:        if (error = iupdat(dp, &time, &time, 1))
                   1158:                goto bad;
                   1159: 
                   1160:        /*
                   1161:         * Initialize directory with "."
                   1162:         * and ".." from static template.
                   1163:         */
                   1164:        dirtemplate = mastertemplate;
                   1165:        dirtemplate.dot_ino = ip->i_number;
                   1166:        dirtemplate.dotdot_ino = dp->i_number;
                   1167:        error = vn_rdwr(UIO_WRITE, ITOV(ip), (caddr_t)&dirtemplate,
                   1168:            sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
                   1169:            IO_NODELOCKED|IO_SYNC, ndp->ni_cred, (int *)0, (struct proc *)0);
                   1170:        if (error) {
                   1171:                dp->i_nlink--;
                   1172:                dp->i_flag |= ICHG;
                   1173:                goto bad;
                   1174:        }
                   1175:        if (DIRBLKSIZ > dp->i_fs->fs_fsize) {
                   1176:                panic("mkdir: blksize");     /* XXX - should grow w/balloc() */
                   1177:        } else {
                   1178:                ip->i_size = DIRBLKSIZ;
                   1179:                ip->i_flag |= ICHG;
                   1180:        }
                   1181:        /*
                   1182:         * Directory all set up, now
                   1183:         * install the entry for it in
                   1184:         * the parent directory.
                   1185:         */
                   1186:        if (error = direnter(ip, ndp)) {
                   1187:                dp->i_nlink--;
                   1188:                dp->i_flag |= ICHG;
                   1189:        }
                   1190: bad:
                   1191:        /*
                   1192:         * No need to do an explicit itrunc here,
                   1193:         * vrele will do this for us because we set
                   1194:         * the link count to 0.
                   1195:         */
                   1196:        if (error) {
                   1197:                ip->i_nlink = 0;
                   1198:                ip->i_flag |= ICHG;
                   1199:                iput(ip);
                   1200:        } else
                   1201:                ndp->ni_vp = ITOV(ip);
                   1202:        FREE(ndp->ni_pnbuf, M_NAMEI);
                   1203:        iput(dp);
                   1204:        return (error);
                   1205: }
                   1206: 
                   1207: /*
                   1208:  * Rmdir system call.
                   1209:  */
                   1210: ufs_rmdir(ndp, p)
                   1211:        register struct nameidata *ndp;
                   1212:        struct proc *p;
                   1213: {
                   1214:        register struct inode *ip, *dp;
                   1215:        int error = 0;
                   1216: 
                   1217:        ip = VTOI(ndp->ni_vp);
                   1218:        dp = VTOI(ndp->ni_dvp);
                   1219:        /*
                   1220:         * No rmdir "." please.
                   1221:         */
                   1222:        if (dp == ip) {
                   1223:                vrele(ITOV(dp));
                   1224:                iput(ip);
                   1225:                return (EINVAL);
                   1226:        }
                   1227:        /*
                   1228:         * Verify the directory is empty (and valid).
                   1229:         * (Rmdir ".." won't be valid since
                   1230:         *  ".." will contain a reference to
                   1231:         *  the current directory and thus be
                   1232:         *  non-empty.)
                   1233:         */
                   1234:        if (ip->i_nlink != 2 || !dirempty(ip, dp->i_number, ndp->ni_cred)) {
                   1235:                error = ENOTEMPTY;
                   1236:                goto out;
                   1237:        }
                   1238:        /*
                   1239:         * Delete reference to directory before purging
                   1240:         * inode.  If we crash in between, the directory
                   1241:         * will be reattached to lost+found,
                   1242:         */
                   1243:        if (error = dirremove(ndp))
                   1244:                goto out;
                   1245:        dp->i_nlink--;
                   1246:        dp->i_flag |= ICHG;
                   1247:        cache_purge(ITOV(dp));
                   1248:        iput(dp);
                   1249:        ndp->ni_dvp = NULL;
                   1250:        /*
                   1251:         * Truncate inode.  The only stuff left
                   1252:         * in the directory is "." and "..".  The
                   1253:         * "." reference is inconsequential since
                   1254:         * we're quashing it.  The ".." reference
                   1255:         * has already been adjusted above.  We've
                   1256:         * removed the "." reference and the reference
                   1257:         * in the parent directory, but there may be
                   1258:         * other hard links so decrement by 2 and
                   1259:         * worry about them later.
                   1260:         */
                   1261:        ip->i_nlink -= 2;
                   1262:        error = itrunc(ip, (u_long)0, IO_SYNC);
                   1263:        cache_purge(ITOV(ip));
                   1264: out:
                   1265:        if (ndp->ni_dvp)
                   1266:                iput(dp);
                   1267:        iput(ip);
                   1268:        return (error);
                   1269: }
                   1270: 
                   1271: /*
                   1272:  * symlink -- make a symbolic link
                   1273:  */
                   1274: ufs_symlink(ndp, vap, target, p)
                   1275:        struct nameidata *ndp;
                   1276:        struct vattr *vap;
                   1277:        char *target;
                   1278:        struct proc *p;
                   1279: {
                   1280:        struct inode *ip;
                   1281:        int error;
                   1282: 
                   1283:        error = maknode(IFLNK | vap->va_mode, ndp, &ip);
                   1284:        if (error)
                   1285:                return (error);
                   1286:        error = vn_rdwr(UIO_WRITE, ITOV(ip), target, strlen(target), (off_t)0,
                   1287:                UIO_SYSSPACE, IO_NODELOCKED, ndp->ni_cred, (int *)0,
                   1288:                (struct proc *)0);
                   1289:        iput(ip);
                   1290:        return (error);
                   1291: }
                   1292: 
                   1293: /*
                   1294:  * Vnode op for read and write
                   1295:  */
                   1296: ufs_readdir(vp, uio, cred, eofflagp)
                   1297:        struct vnode *vp;
                   1298:        register struct uio *uio;
                   1299:        struct ucred *cred;
                   1300:        int *eofflagp;
                   1301: {
                   1302:        int count, lost, error;
                   1303: 
                   1304:        count = uio->uio_resid;
                   1305:        count &= ~(DIRBLKSIZ - 1);
                   1306:        lost = uio->uio_resid - count;
                   1307:        if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1)))
                   1308:                return (EINVAL);
                   1309:        uio->uio_resid = count;
                   1310:        uio->uio_iov->iov_len = count;
                   1311:        error = ufs_read(vp, uio, 0, cred);
                   1312:        uio->uio_resid += lost;
                   1313:        if ((VTOI(vp)->i_size - uio->uio_offset) <= 0)
                   1314:                *eofflagp = 1;
                   1315:        else
                   1316:                *eofflagp = 0;
                   1317:        return (error);
                   1318: }
                   1319: 
                   1320: /*
                   1321:  * Return target name of a symbolic link
                   1322:  */
                   1323: ufs_readlink(vp, uiop, cred)
                   1324:        struct vnode *vp;
                   1325:        struct uio *uiop;
                   1326:        struct ucred *cred;
                   1327: {
                   1328: 
                   1329:        return (ufs_read(vp, uiop, 0, cred));
                   1330: }
                   1331: 
                   1332: /*
                   1333:  * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
                   1334:  * done. If a buffer has been saved in anticipation of a CREATE, delete it.
                   1335:  */
                   1336: /* ARGSUSED */
                   1337: ufs_abortop(ndp)
                   1338:        struct nameidata *ndp;
                   1339: {
                   1340: 
                   1341:        if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
                   1342:                FREE(ndp->ni_pnbuf, M_NAMEI);
                   1343:        return (0);
                   1344: }
                   1345: 
                   1346: /*
                   1347:  * Lock an inode.
                   1348:  */
                   1349: ufs_lock(vp)
                   1350:        struct vnode *vp;
                   1351: {
                   1352:        register struct inode *ip = VTOI(vp);
                   1353: 
                   1354:        ILOCK(ip);
                   1355:        return (0);
                   1356: }
                   1357: 
                   1358: /*
                   1359:  * Unlock an inode.
                   1360:  */
                   1361: ufs_unlock(vp)
                   1362:        struct vnode *vp;
                   1363: {
                   1364:        register struct inode *ip = VTOI(vp);
                   1365: 
                   1366:        if (!(ip->i_flag & ILOCKED))
                   1367:                panic("ufs_unlock NOT LOCKED");
                   1368:        IUNLOCK(ip);
                   1369:        return (0);
                   1370: }
                   1371: 
                   1372: /*
                   1373:  * Check for a locked inode.
                   1374:  */
                   1375: ufs_islocked(vp)
                   1376:        struct vnode *vp;
                   1377: {
                   1378: 
                   1379:        if (VTOI(vp)->i_flag & ILOCKED)
                   1380:                return (1);
                   1381:        return (0);
                   1382: }
                   1383: 
                   1384: /*
                   1385:  * Get access to bmap
                   1386:  */
                   1387: ufs_bmap(vp, bn, vpp, bnp)
                   1388:        struct vnode *vp;
                   1389:        daddr_t bn;
                   1390:        struct vnode **vpp;
                   1391:        daddr_t *bnp;
                   1392: {
                   1393:        struct inode *ip = VTOI(vp);
                   1394: 
                   1395:        if (vpp != NULL)
                   1396:                *vpp = ip->i_devvp;
                   1397:        if (bnp == NULL)
                   1398:                return (0);
                   1399:        return (bmap(ip, bn, bnp));
                   1400: }
                   1401: 
                   1402: /*
                   1403:  * Calculate the logical to physical mapping if not done already,
                   1404:  * then call the device strategy routine.
                   1405:  */
                   1406: int checkoverlap = 0;
                   1407: 
                   1408: ufs_strategy(bp)
                   1409:        register struct buf *bp;
                   1410: {
                   1411:        register struct inode *ip = VTOI(bp->b_vp);
                   1412:        struct vnode *vp;
                   1413:        int error;
                   1414: 
                   1415:        if (bp->b_vp->v_type == VBLK || bp->b_vp->v_type == VCHR)
                   1416:                panic("ufs_strategy: spec");
                   1417:        if (bp->b_blkno == bp->b_lblkno) {
                   1418:                if (error = bmap(ip, bp->b_lblkno, &bp->b_blkno))
                   1419:                        return (error);
                   1420:                if ((long)bp->b_blkno == -1)
                   1421:                        clrbuf(bp);
                   1422:        }
                   1423:        if ((long)bp->b_blkno == -1) {
                   1424:                biodone(bp);
                   1425:                return (0);
                   1426:        }
                   1427: #ifdef DIAGNOSTIC
                   1428:        if (checkoverlap) {
                   1429:                register struct buf *ep;
                   1430:                struct buf *ebp;
                   1431:                daddr_t start, last;
                   1432: 
                   1433:                ebp = &buf[nbuf];
                   1434:                start = bp->b_blkno;
                   1435:                last = start + btodb(bp->b_bcount) - 1;
                   1436:                for (ep = buf; ep < ebp; ep++) {
                   1437:                        if (ep == bp || (ep->b_flags & B_INVAL) ||
                   1438:                            ep->b_vp == NULLVP)
                   1439:                                continue;
                   1440:                        if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0))
                   1441:                                continue;
                   1442:                        if (vp != ip->i_devvp)
                   1443:                                continue;
                   1444:                        /* look for overlap */
                   1445:                        if (ep->b_bcount == 0 || ep->b_blkno > last ||
                   1446:                            ep->b_blkno + btodb(ep->b_bcount) <= start)
                   1447:                                continue;
                   1448:                        vprint("Disk overlap", vp);
                   1449:                        printf("\tstart %d, end %d overlap start %d, end %d\n",
                   1450:                                start, last, ep->b_blkno,
                   1451:                                ep->b_blkno + btodb(ep->b_bcount) - 1);
                   1452:                        panic("Disk buffer overlap");
                   1453:                }
                   1454:        }
                   1455: #endif /* DIAGNOSTIC */
                   1456:        vp = ip->i_devvp;
                   1457:        bp->b_dev = vp->v_rdev;
                   1458:        (*(vp->v_op->vop_strategy))(bp);
                   1459:        return (0);
                   1460: }
                   1461: 
                   1462: /*
                   1463:  * Print out the contents of an inode.
                   1464:  */
                   1465: ufs_print(vp)
                   1466:        struct vnode *vp;
                   1467: {
                   1468:        register struct inode *ip = VTOI(vp);
                   1469: 
                   1470:        printf("tag VT_UFS, ino %d, on dev %d, %d", ip->i_number,
                   1471:                major(ip->i_dev), minor(ip->i_dev));
                   1472: #ifdef FIFO
                   1473:        if (vp->v_type == VFIFO)
                   1474:                fifo_printinfo(vp);
                   1475: #endif /* FIFO */
                   1476:        printf("%s\n", (ip->i_flag & ILOCKED) ? " (LOCKED)" : "");
                   1477:        if (ip->i_spare0 == 0)
                   1478:                return;
                   1479:        printf("\towner pid %d", ip->i_spare0);
                   1480:        if (ip->i_spare1)
                   1481:                printf(" waiting pid %d", ip->i_spare1);
                   1482:        printf("\n");
                   1483: }
                   1484: 
                   1485: /*
                   1486:  * Read wrapper for special devices.
                   1487:  */
                   1488: ufsspec_read(vp, uio, ioflag, cred)
                   1489:        struct vnode *vp;
                   1490:        struct uio *uio;
                   1491:        int ioflag;
                   1492:        struct ucred *cred;
                   1493: {
                   1494: 
                   1495:        /*
                   1496:         * Set access flag.
                   1497:         */
                   1498:        VTOI(vp)->i_flag |= IACC;
                   1499:        return (spec_read(vp, uio, ioflag, cred));
                   1500: }
                   1501: 
                   1502: /*
                   1503:  * Write wrapper for special devices.
                   1504:  */
                   1505: ufsspec_write(vp, uio, ioflag, cred)
                   1506:        struct vnode *vp;
                   1507:        struct uio *uio;
                   1508:        int ioflag;
                   1509:        struct ucred *cred;
                   1510: {
                   1511: 
                   1512:        /*
                   1513:         * Set update and change flags.
                   1514:         */
                   1515:        VTOI(vp)->i_flag |= IUPD|ICHG;
                   1516:        return (spec_write(vp, uio, ioflag, cred));
                   1517: }
                   1518: 
                   1519: /*
                   1520:  * Close wrapper for special devices.
                   1521:  *
                   1522:  * Update the times on the inode then do device close.
                   1523:  */
                   1524: ufsspec_close(vp, fflag, cred, p)
                   1525:        struct vnode *vp;
                   1526:        int fflag;
                   1527:        struct ucred *cred;
                   1528:        struct proc *p;
                   1529: {
                   1530:        register struct inode *ip = VTOI(vp);
                   1531: 
                   1532:        if (vp->v_usecount > 1 && !(ip->i_flag & ILOCKED))
                   1533:                ITIMES(ip, &time, &time);
                   1534:        return (spec_close(vp, fflag, cred, p));
                   1535: }
                   1536: 
                   1537: #ifdef FIFO
                   1538: /*
                   1539:  * Read wrapper for fifo's
                   1540:  */
                   1541: ufsfifo_read(vp, uio, ioflag, cred)
                   1542:        struct vnode *vp;
                   1543:        struct uio *uio;
                   1544:        int ioflag;
                   1545:        struct ucred *cred;
                   1546: {
                   1547: 
                   1548:        /*
                   1549:         * Set access flag.
                   1550:         */
                   1551:        VTOI(vp)->i_flag |= IACC;
                   1552:        return (fifo_read(vp, uio, ioflag, cred));
                   1553: }
                   1554: 
                   1555: /*
                   1556:  * Write wrapper for fifo's.
                   1557:  */
                   1558: ufsfifo_write(vp, uio, ioflag, cred)
                   1559:        struct vnode *vp;
                   1560:        struct uio *uio;
                   1561:        int ioflag;
                   1562:        struct ucred *cred;
                   1563: {
                   1564: 
                   1565:        /*
                   1566:         * Set update and change flags.
                   1567:         */
                   1568:        VTOI(vp)->i_flag |= IUPD|ICHG;
                   1569:        return (fifo_write(vp, uio, ioflag, cred));
                   1570: }
                   1571: 
                   1572: /*
                   1573:  * Close wrapper for fifo's.
                   1574:  *
                   1575:  * Update the times on the inode then do device close.
                   1576:  */
                   1577: ufsfifo_close(vp, fflag, cred, p)
                   1578:        struct vnode *vp;
                   1579:        int fflag;
                   1580:        struct ucred *cred;
                   1581:        struct proc *p;
                   1582: {
                   1583:        register struct inode *ip = VTOI(vp);
                   1584: 
                   1585:        if (vp->v_usecount > 1 && !(ip->i_flag & ILOCKED))
                   1586:                ITIMES(ip, &time, &time);
                   1587:        return (fifo_close(vp, fflag, cred, p));
                   1588: }
                   1589: #endif /* FIFO */
                   1590: 
                   1591: /*
                   1592:  * Allocate a new inode.
                   1593:  */
                   1594: maknode(mode, ndp, ipp)
                   1595:        int mode;
                   1596:        register struct nameidata *ndp;
                   1597:        struct inode **ipp;
                   1598: {
                   1599:        register struct inode *ip;
                   1600:        struct inode *tip;
                   1601:        register struct inode *pdir = VTOI(ndp->ni_dvp);
                   1602:        ino_t ipref;
                   1603:        int error;
                   1604: 
                   1605: #ifdef DIANOSTIC
                   1606:        if ((ndp->ni_nameiop & HASBUF) == 0)
                   1607:                panic("maknode: no name");
                   1608: #endif
                   1609:        *ipp = 0;
                   1610:        if ((mode & IFMT) == 0)
                   1611:                mode |= IFREG;
                   1612:        if ((mode & IFMT) == IFDIR)
                   1613:                ipref = dirpref(pdir->i_fs);
                   1614:        else
                   1615:                ipref = pdir->i_number;
                   1616:        if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
                   1617:                free(ndp->ni_pnbuf, M_NAMEI);
                   1618:                iput(pdir);
                   1619:                return (error);
                   1620:        }
                   1621:        ip = tip;
                   1622:        ip->i_uid = ndp->ni_cred->cr_uid;
                   1623:        ip->i_gid = pdir->i_gid;
                   1624: #ifdef QUOTA
                   1625:        if ((error = getinoquota(ip)) ||
                   1626:            (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
                   1627:                free(ndp->ni_pnbuf, M_NAMEI);
                   1628:                ifree(ip, ip->i_number, mode);
                   1629:                iput(ip);
                   1630:                iput(pdir);
                   1631:                return (error);
                   1632:        }
                   1633: #endif
                   1634:        ip->i_flag |= IACC|IUPD|ICHG;
                   1635:        ip->i_mode = mode;
                   1636:        ITOV(ip)->v_type = IFTOVT(mode);        /* Rest init'd in iget() */
                   1637:        ip->i_nlink = 1;
                   1638:        if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) &&
                   1639:            suser(ndp->ni_cred, NULL))
                   1640:                ip->i_mode &= ~ISGID;
                   1641: 
                   1642:        /*
                   1643:         * Make sure inode goes to disk before directory entry.
                   1644:         */
                   1645:        if (error = iupdat(ip, &time, &time, 1))
                   1646:                goto bad;
                   1647:        if (error = direnter(ip, ndp))
                   1648:                goto bad;
                   1649:        if ((ndp->ni_nameiop & SAVESTART) == 0)
                   1650:                FREE(ndp->ni_pnbuf, M_NAMEI);
                   1651:        iput(pdir);
                   1652:        *ipp = ip;
                   1653:        return (0);
                   1654: 
                   1655: bad:
                   1656:        /*
                   1657:         * Write error occurred trying to update the inode
                   1658:         * or the directory so must deallocate the inode.
                   1659:         */
                   1660:        free(ndp->ni_pnbuf, M_NAMEI);
                   1661:        iput(pdir);
                   1662:        ip->i_nlink = 0;
                   1663:        ip->i_flag |= ICHG;
                   1664:        iput(ip);
                   1665:        return (error);
                   1666: }
                   1667: 
                   1668: /*
                   1669:  * Advisory record locking support
                   1670:  */
                   1671: ufs_advlock(vp, id, op, fl, flags)
                   1672:        struct vnode *vp;
                   1673:        caddr_t id;
                   1674:        int op;
                   1675:        register struct flock *fl;
                   1676:        int flags;
                   1677: {
                   1678:        register struct inode *ip = VTOI(vp);
                   1679:        register struct lockf *lock;
                   1680:        off_t start, end;
                   1681:        int error;
                   1682: 
                   1683:        /*
                   1684:         * Avoid the common case of unlocking when inode has no locks.
                   1685:         */
                   1686:        if (ip->i_lockf == (struct lockf *)0) {
                   1687:                if (op != F_SETLK) {
                   1688:                        fl->l_type = F_UNLCK;
                   1689:                        return (0);
                   1690:                }
                   1691:        }
                   1692:        /*
                   1693:         * Convert the flock structure into a start and end.
                   1694:         */
                   1695:        switch (fl->l_whence) {
                   1696: 
                   1697:        case SEEK_SET:
                   1698:        case SEEK_CUR:
                   1699:                /*
                   1700:                 * Caller is responsible for adding any necessary offset
                   1701:                 * when SEEK_CUR is used.
                   1702:                 */
                   1703:                start = fl->l_start;
                   1704:                break;
                   1705: 
                   1706:        case SEEK_END:
                   1707:                start = ip->i_size + fl->l_start;
                   1708:                break;
                   1709: 
                   1710:        default:
                   1711:                return (EINVAL);
                   1712:        }
                   1713:        if (start < 0)
                   1714:                return (EINVAL);
                   1715:        if (fl->l_len == 0)
                   1716:                end = -1;
                   1717:        else
                   1718:                end = start + fl->l_len - 1;
                   1719:        /*
                   1720:         * Create the lockf structure
                   1721:         */
                   1722:        MALLOC(lock, struct lockf *, sizeof *lock, M_LOCKF, M_WAITOK);
                   1723:        lock->lf_start = start;
                   1724:        lock->lf_end = end;
                   1725:        lock->lf_id = id;
                   1726:        lock->lf_inode = ip;
                   1727:        lock->lf_type = fl->l_type;
                   1728:        lock->lf_next = (struct lockf *)0;
                   1729:        lock->lf_block = (struct lockf *)0;
                   1730:        lock->lf_flags = flags;
                   1731:        /*
                   1732:         * Do the requested operation.
                   1733:         */
                   1734:        switch(op) {
                   1735:        case F_SETLK:
                   1736:                return (lf_setlock(lock));
                   1737: 
                   1738:        case F_UNLCK:
                   1739:                error = lf_clearlock(lock);
                   1740:                FREE(lock, M_LOCKF);
                   1741:                return (error);
                   1742: 
                   1743:        case F_GETLK:
                   1744:                error = lf_getlock(lock, fl);
                   1745:                FREE(lock, M_LOCKF);
                   1746:                return (error);
                   1747:        
                   1748:        default:
                   1749:                free(lock, M_LOCKF);
                   1750:                return (EINVAL);
                   1751:        }
                   1752:        /* NOTREACHED */
                   1753: }
                   1754: 
                   1755: /*
                   1756:  * Global vfs data structures for ufs
                   1757:  */
                   1758: struct vnodeops ufs_vnodeops = {
                   1759:        ufs_lookup,             /* lookup */
                   1760:        ufs_create,             /* create */
                   1761:        ufs_mknod,              /* mknod */
                   1762:        ufs_open,               /* open */
                   1763:        ufs_close,              /* close */
                   1764:        ufs_access,             /* access */
                   1765:        ufs_getattr,            /* getattr */
                   1766:        ufs_setattr,            /* setattr */
                   1767:        ufs_read,               /* read */
                   1768:        ufs_write,              /* write */
                   1769:        ufs_ioctl,              /* ioctl */
                   1770:        ufs_select,             /* select */
                   1771:        ufs_mmap,               /* mmap */
                   1772:        ufs_fsync,              /* fsync */
                   1773:        ufs_seek,               /* seek */
                   1774:        ufs_remove,             /* remove */
                   1775:        ufs_link,               /* link */
                   1776:        ufs_rename,             /* rename */
                   1777:        ufs_mkdir,              /* mkdir */
                   1778:        ufs_rmdir,              /* rmdir */
                   1779:        ufs_symlink,            /* symlink */
                   1780:        ufs_readdir,            /* readdir */
                   1781:        ufs_readlink,           /* readlink */
                   1782:        ufs_abortop,            /* abortop */
                   1783:        ufs_inactive,           /* inactive */
                   1784:        ufs_reclaim,            /* reclaim */
                   1785:        ufs_lock,               /* lock */
                   1786:        ufs_unlock,             /* unlock */
                   1787:        ufs_bmap,               /* bmap */
                   1788:        ufs_strategy,           /* strategy */
                   1789:        ufs_print,              /* print */
                   1790:        ufs_islocked,           /* islocked */
                   1791:        ufs_advlock,            /* advlock */
                   1792: };
                   1793: 
                   1794: struct vnodeops spec_inodeops = {
                   1795:        spec_lookup,            /* lookup */
                   1796:        spec_create,            /* create */
                   1797:        spec_mknod,             /* mknod */
                   1798:        spec_open,              /* open */
                   1799:        ufsspec_close,          /* close */
                   1800:        ufs_access,             /* access */
                   1801:        ufs_getattr,            /* getattr */
                   1802:        ufs_setattr,            /* setattr */
                   1803:        ufsspec_read,           /* read */
                   1804:        ufsspec_write,          /* write */
                   1805:        spec_ioctl,             /* ioctl */
                   1806:        spec_select,            /* select */
                   1807:        spec_mmap,              /* mmap */
                   1808:        spec_fsync,             /* fsync */
                   1809:        spec_seek,              /* seek */
                   1810:        spec_remove,            /* remove */
                   1811:        spec_link,              /* link */
                   1812:        spec_rename,            /* rename */
                   1813:        spec_mkdir,             /* mkdir */
                   1814:        spec_rmdir,             /* rmdir */
                   1815:        spec_symlink,           /* symlink */
                   1816:        spec_readdir,           /* readdir */
                   1817:        spec_readlink,          /* readlink */
                   1818:        spec_abortop,           /* abortop */
                   1819:        ufs_inactive,           /* inactive */
                   1820:        ufs_reclaim,            /* reclaim */
                   1821:        ufs_lock,               /* lock */
                   1822:        ufs_unlock,             /* unlock */
                   1823:        spec_bmap,              /* bmap */
                   1824:        spec_strategy,          /* strategy */
                   1825:        ufs_print,              /* print */
                   1826:        ufs_islocked,           /* islocked */
                   1827:        spec_advlock,           /* advlock */
                   1828: };
                   1829: 
                   1830: #ifdef FIFO
                   1831: struct vnodeops fifo_inodeops = {
                   1832:        fifo_lookup,            /* lookup */
                   1833:        fifo_create,            /* create */
                   1834:        fifo_mknod,             /* mknod */
                   1835:        fifo_open,              /* open */
                   1836:        ufsfifo_close,          /* close */
                   1837:        ufs_access,             /* access */
                   1838:        ufs_getattr,            /* getattr */
                   1839:        ufs_setattr,            /* setattr */
                   1840:        ufsfifo_read,           /* read */
                   1841:        ufsfifo_write,          /* write */
                   1842:        fifo_ioctl,             /* ioctl */
                   1843:        fifo_select,            /* select */
                   1844:        fifo_mmap,              /* mmap */
                   1845:        fifo_fsync,             /* fsync */
                   1846:        fifo_seek,              /* seek */
                   1847:        fifo_remove,            /* remove */
                   1848:        fifo_link,              /* link */
                   1849:        fifo_rename,            /* rename */
                   1850:        fifo_mkdir,             /* mkdir */
                   1851:        fifo_rmdir,             /* rmdir */
                   1852:        fifo_symlink,           /* symlink */
                   1853:        fifo_readdir,           /* readdir */
                   1854:        fifo_readlink,          /* readlink */
                   1855:        fifo_abortop,           /* abortop */
                   1856:        ufs_inactive,           /* inactive */
                   1857:        ufs_reclaim,            /* reclaim */
                   1858:        ufs_lock,               /* lock */
                   1859:        ufs_unlock,             /* unlock */
                   1860:        fifo_bmap,              /* bmap */
                   1861:        fifo_strategy,          /* strategy */
                   1862:        ufs_print,              /* print */
                   1863:        ufs_islocked,           /* islocked */
                   1864:        fifo_advlock,           /* advlock */
                   1865: };
                   1866: #endif /* FIFO */
                   1867: 
                   1868: enum vtype iftovt_tab[16] = {
                   1869:        VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
                   1870:        VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
                   1871: };
                   1872: int    vttoif_tab[9] = {
                   1873:        0, IFREG, IFDIR, IFBLK, IFCHR, IFLNK, IFSOCK, IFIFO, IFMT,
                   1874: };

unix.superglobalmegacorp.com

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