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

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

unix.superglobalmegacorp.com

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