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

unix.superglobalmegacorp.com

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