Annotation of Net2/ufs/ufs_vnops.c, revision 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.