Annotation of 43BSDReno/sys/ufs/ufs_vnops.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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