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

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

unix.superglobalmegacorp.com

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