lint
[unix-history] / usr / src / sys / ufs / ffs / ufs_vnops.c
index 031648b..3a68963 100644 (file)
@@ -1,10 +1,10 @@
 /*
 /*
- * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)ufs_vnops.c 7.114 (Berkeley) %G%
+ *     @(#)ufs_vnops.c 8.8 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -98,7 +98,7 @@ ufs_mknod(ap)
            ap->a_dvp, vpp, ap->a_cnp))
                return (error);
        ip = VTOI(*vpp);
            ap->a_dvp, vpp, ap->a_cnp))
                return (error);
        ip = VTOI(*vpp);
-       ip->i_flag |= IACC|IUPD|ICHG;
+       ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
        if (vap->va_rdev != VNOVAL) {
                /*
                 * Want to be able to use this to make badblock
        if (vap->va_rdev != VNOVAL) {
                /*
                 * Want to be able to use this to make badblock
@@ -144,7 +144,7 @@ ufs_open(ap)
 }
 
 /*
 }
 
 /*
- * Close called
+ * Close called.
  *
  * Update the times on the inode.
  */
  *
  * Update the times on the inode.
  */
@@ -161,16 +161,11 @@ ufs_close(ap)
        register struct vnode *vp = ap->a_vp;
        register struct inode *ip = VTOI(vp);
 
        register struct vnode *vp = ap->a_vp;
        register struct inode *ip = VTOI(vp);
 
-       if (vp->v_usecount > 1 && !(ip->i_flag & ILOCKED))
+       if (vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED))
                ITIMES(ip, &time, &time);
        return (0);
 }
 
                ITIMES(ip, &time, &time);
        return (0);
 }
 
-/*
- * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
- * The mode is shifted to select the owner/group/other fields. The
- * super user is granted all permissions.
- */
 int
 ufs_access(ap)
        struct vop_access_args /* {
 int
 ufs_access(ap)
        struct vop_access_args /* {
@@ -183,7 +178,7 @@ ufs_access(ap)
        register struct vnode *vp = ap->a_vp;
        register struct inode *ip = VTOI(vp);
        register struct ucred *cred = ap->a_cred;
        register struct vnode *vp = ap->a_vp;
        register struct inode *ip = VTOI(vp);
        register struct ucred *cred = ap->a_cred;
-       mode_t mode = ap->a_mode;
+       mode_t mask, mode = ap->a_mode;
        register gid_t *gp;
        int i, error;
 
        register gid_t *gp;
        int i, error;
 
@@ -194,37 +189,58 @@ ufs_access(ap)
        }
 #endif
 #ifdef QUOTA
        }
 #endif
 #ifdef QUOTA
-       if (mode & VWRITE) {
+       if (mode & VWRITE)
                switch (vp->v_type) {
                switch (vp->v_type) {
-               case VREG: case VDIR: case VLNK:
+               case VDIR:
+               case VLNK:
+               case VREG:
                        if (error = getinoquota(ip))
                                return (error);
                        if (error = getinoquota(ip))
                                return (error);
+                       break;
                }
                }
-       }
-#endif /* QUOTA */
+#endif
+
+       /* If immutable bit set, nobody gets to write it. */
        if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE))
                return (EPERM);
        if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE))
                return (EPERM);
-       /*
-        * If you're the super-user, you always get access.
-        */
+
+       /* Otherwise, user id 0 always gets access. */
        if (cred->cr_uid == 0)
                return (0);
        if (cred->cr_uid == 0)
                return (0);
-       /*
-        * Access check is based on only one of owner, group, public.
-        * If not owner, then check group. If not a member of the
-        * group, then check public access.
-        */
-       if (cred->cr_uid != ip->i_uid) {
-               mode >>= 3;
-               gp = cred->cr_groups;
-               for (i = 0; i < cred->cr_ngroups; i++, gp++)
-                       if (ip->i_gid == *gp)
-                               goto found;
-               mode >>= 3;
-found:
-               ;
+
+       mask = 0;
+
+       /* Otherwise, check the owner. */
+       if (cred->cr_uid == ip->i_uid) {
+               if (mode & VEXEC)
+                       mask |= S_IXUSR;
+               if (mode & VREAD)
+                       mask |= S_IRUSR;
+               if (mode & VWRITE)
+                       mask |= S_IWUSR;
+               return ((ip->i_mode & mask) == mask ? 0 : EACCES);
        }
        }
-       return ((ip->i_mode & mode) == mode ? 0 : EACCES);
+
+       /* Otherwise, check the groups. */
+       for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
+               if (ip->i_gid == *gp) {
+                       if (mode & VEXEC)
+                               mask |= S_IXGRP;
+                       if (mode & VREAD)
+                               mask |= S_IRGRP;
+                       if (mode & VWRITE)
+                               mask |= S_IWGRP;
+                       return ((ip->i_mode & mask) == mask ? 0 : EACCES);
+               }
+
+       /* Otherwise, check everyone else. */
+       if (mode & VEXEC)
+               mask |= S_IXOTH;
+       if (mode & VREAD)
+               mask |= S_IROTH;
+       if (mode & VWRITE)
+               mask |= S_IWOTH;
+       return ((ip->i_mode & mask) == mask ? 0 : EACCES);
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
@@ -312,10 +328,10 @@ ufs_setattr(ap)
                } else {
                        if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND))
                                return (EPERM);
                } else {
                        if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND))
                                return (EPERM);
-                       ip->i_flags &= 0xffff0000;
-                       ip->i_flags |= (vap->va_flags & 0xffff);
+                       ip->i_flags &= SF_SETTABLE;
+                       ip->i_flags |= (vap->va_flags & UF_SETTABLE);
                }
                }
-               ip->i_flag |= ICHG;
+               ip->i_flag |= IN_CHANGE;
                if (vap->va_flags & (IMMUTABLE | APPEND))
                        return (0);
        }
                if (vap->va_flags & (IMMUTABLE | APPEND))
                        return (0);
        }
@@ -336,12 +352,14 @@ ufs_setattr(ap)
        ip = VTOI(vp);
        if (vap->va_atime.ts_sec != VNOVAL || vap->va_mtime.ts_sec != VNOVAL) {
                if (cred->cr_uid != ip->i_uid &&
        ip = VTOI(vp);
        if (vap->va_atime.ts_sec != VNOVAL || vap->va_mtime.ts_sec != VNOVAL) {
                if (cred->cr_uid != ip->i_uid &&
-                   (error = suser(cred, &p->p_acflag)))
+                   (error = suser(cred, &p->p_acflag)) &&
+                   ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || 
+                   (error = VOP_ACCESS(vp, VWRITE, cred, p))))
                        return (error);
                if (vap->va_atime.ts_sec != VNOVAL)
                        return (error);
                if (vap->va_atime.ts_sec != VNOVAL)
-                       ip->i_flag |= IACC;
+                       ip->i_flag |= IN_ACCESS;
                if (vap->va_mtime.ts_sec != VNOVAL)
                if (vap->va_mtime.ts_sec != VNOVAL)
-                       ip->i_flag |= IUPD | ICHG;
+                       ip->i_flag |= IN_CHANGE | IN_UPDATE;
                atimeval.tv_sec = vap->va_atime.ts_sec;
                atimeval.tv_usec = vap->va_atime.ts_nsec / 1000;
                mtimeval.tv_sec = vap->va_mtime.ts_sec;
                atimeval.tv_sec = vap->va_atime.ts_sec;
                atimeval.tv_usec = vap->va_atime.ts_nsec / 1000;
                mtimeval.tv_sec = vap->va_mtime.ts_sec;
@@ -373,15 +391,15 @@ ufs_chmod(vp, mode, cred, p)
            (error = suser(cred, &p->p_acflag)))
                return (error);
        if (cred->cr_uid) {
            (error = suser(cred, &p->p_acflag)))
                return (error);
        if (cred->cr_uid) {
-               if (vp->v_type != VDIR && (mode & ISVTX))
+               if (vp->v_type != VDIR && (mode & S_ISTXT))
                        return (EFTYPE);
                if (!groupmember(ip->i_gid, cred) && (mode & ISGID))
                        return (EPERM);
        }
                        return (EFTYPE);
                if (!groupmember(ip->i_gid, cred) && (mode & ISGID))
                        return (EPERM);
        }
-       ip->i_mode &= ~07777;
-       ip->i_mode |= mode & 07777;
-       ip->i_flag |= ICHG;
-       if ((vp->v_flag & VTEXT) && (ip->i_mode & ISVTX) == 0)
+       ip->i_mode &= ~ALLPERMS;
+       ip->i_mode |= (mode & ALLPERMS);
+       ip->i_flag |= IN_CHANGE;
+       if ((vp->v_flag & VTEXT) && (ip->i_mode & S_ISTXT) == 0)
                (void) vnode_pager_uncache(vp);
        return (0);
 }
                (void) vnode_pager_uncache(vp);
        return (0);
 }
@@ -420,8 +438,8 @@ ufs_chown(vp, uid, gid, cred, p)
            !groupmember((gid_t)gid, cred)) &&
            (error = suser(cred, &p->p_acflag)))
                return (error);
            !groupmember((gid_t)gid, cred)) &&
            (error = suser(cred, &p->p_acflag)))
                return (error);
-       ouid = ip->i_uid;
        ogid = ip->i_gid;
        ogid = ip->i_gid;
+       ouid = ip->i_uid;
 #ifdef QUOTA
        if (error = getinoquota(ip))
                return (error);
 #ifdef QUOTA
        if (error = getinoquota(ip))
                return (error);
@@ -441,8 +459,8 @@ ufs_chown(vp, uid, gid, cred, p)
                ip->i_dquot[i] = NODQUOT;
        }
 #endif
                ip->i_dquot[i] = NODQUOT;
        }
 #endif
-       ip->i_uid = uid;
        ip->i_gid = gid;
        ip->i_gid = gid;
+       ip->i_uid = uid;
 #ifdef QUOTA
        if ((error = getinoquota(ip)) == 0) {
                if (ouid == uid) {
 #ifdef QUOTA
        if ((error = getinoquota(ip)) == 0) {
                if (ouid == uid) {
@@ -464,8 +482,8 @@ ufs_chown(vp, uid, gid, cred, p)
                        ip->i_dquot[i] = NODQUOT;
                }
        }
                        ip->i_dquot[i] = NODQUOT;
                }
        }
-       ip->i_uid = ouid;
        ip->i_gid = ogid;
        ip->i_gid = ogid;
+       ip->i_uid = ouid;
        if (getinoquota(ip) == 0) {
                if (ouid == uid) {
                        dqrele(vp, ip->i_dquot[USRQUOTA]);
        if (getinoquota(ip) == 0) {
                if (ouid == uid) {
                        dqrele(vp, ip->i_dquot[USRQUOTA]);
@@ -485,7 +503,7 @@ good:
                panic("chown: lost quota");
 #endif /* QUOTA */
        if (ouid != uid || ogid != gid)
                panic("chown: lost quota");
 #endif /* QUOTA */
        if (ouid != uid || ogid != gid)
-               ip->i_flag |= ICHG;
+               ip->i_flag |= IN_CHANGE;
        if (ouid != uid && cred->cr_uid != 0)
                ip->i_mode &= ~ISUID;
        if (ogid != gid && cred->cr_uid != 0)
        if (ouid != uid && cred->cr_uid != 0)
                ip->i_mode &= ~ISUID;
        if (ogid != gid && cred->cr_uid != 0)
@@ -565,11 +583,6 @@ ufs_seek(ap)
        return (0);
 }
 
        return (0);
 }
 
-/*
- * ufs remove
- * Hard to avoid races here, especially
- * in unlinking directories.
- */
 int
 ufs_remove(ap)
        struct vop_remove_args /* {
 int
 ufs_remove(ap)
        struct vop_remove_args /* {
@@ -591,7 +604,7 @@ ufs_remove(ap)
        }
        if ((error = ufs_dirremove(dvp, ap->a_cnp)) == 0) {
                ip->i_nlink--;
        }
        if ((error = ufs_dirremove(dvp, ap->a_cnp)) == 0) {
                ip->i_nlink--;
-               ip->i_flag |= ICHG;
+               ip->i_flag |= IN_CHANGE;
        }
 out:
        if (dvp == vp)
        }
 out:
        if (dvp == vp)
@@ -645,14 +658,14 @@ ufs_link(ap)
                goto out1;
        }
        ip->i_nlink++;
                goto out1;
        }
        ip->i_nlink++;
-       ip->i_flag |= ICHG;
+       ip->i_flag |= IN_CHANGE;
        tv = time;
        error = VOP_UPDATE(tdvp, &tv, &tv, 1);
        if (!error)
                error = ufs_direnter(ip, vp, cnp);
        if (error) {
                ip->i_nlink--;
        tv = time;
        error = VOP_UPDATE(tdvp, &tv, &tv, 1);
        if (!error)
                error = ufs_direnter(ip, vp, cnp);
        if (error) {
                ip->i_nlink--;
-               ip->i_flag |= ICHG;
+               ip->i_flag |= IN_CHANGE;
        }
        FREE(cnp->cn_pnbuf, M_NAMEI);
 out1:
        }
        FREE(cnp->cn_pnbuf, M_NAMEI);
 out1:
@@ -675,14 +688,14 @@ relookup(dvp, vpp, cnp)
        struct componentname *cnp;
 {
        register struct vnode *dp = 0;  /* the directory we are searching */
        struct componentname *cnp;
 {
        register struct vnode *dp = 0;  /* the directory we are searching */
-       struct vnode *tdp;              /* saved dp */
-       struct mount *mp;               /* mount table entry */
        int docache;                    /* == 0 do not cache last component */
        int wantparent;                 /* 1 => wantparent or lockparent flag */
        int rdonly;                     /* lookup read-only flag bit */
        int docache;                    /* == 0 do not cache last component */
        int wantparent;                 /* 1 => wantparent or lockparent flag */
        int rdonly;                     /* lookup read-only flag bit */
-       char *cp;                       /* DEBUG: check name ptr/len */
-       int newhash;                    /* DEBUG: check name hash */
        int error = 0;
        int error = 0;
+#ifdef NAMEI_DIAGNOSTIC
+       int newhash;                    /* DEBUG: check name hash */
+       char *cp;                       /* DEBUG: check name ptr/len */
+#endif
 
        /*
         * Setup: break out flag bits into variables.
 
        /*
         * Setup: break out flag bits into variables.
@@ -782,7 +795,6 @@ relookup(dvp, vpp, cnp)
                panic ("relookup: symlink found.\n");
 #endif
 
                panic ("relookup: symlink found.\n");
 #endif
 
-nextname:
        /*
         * Check for read-only file systems.
         */
        /*
         * Check for read-only file systems.
         */
@@ -865,7 +877,6 @@ ufs_rename(ap)
        struct timeval tv;
        int doingdirectory = 0, oldparent = 0, newparent = 0;
        int error = 0;
        struct timeval tv;
        int doingdirectory = 0, oldparent = 0, newparent = 0;
        int error = 0;
-       int fdvpneedsrele = 1, tdvpneedsrele = 1;
        u_char namlen;
 
 #ifdef DIAGNOSTIC
        u_char namlen;
 
 #ifdef DIAGNOSTIC
@@ -934,12 +945,12 @@ abortit:
                 */
                if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
                    dp == ip || (fcnp->cn_flags&ISDOTDOT) ||
                 */
                if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
                    dp == ip || (fcnp->cn_flags&ISDOTDOT) ||
-                   (ip->i_flag & IRENAME)) {
+                   (ip->i_flag & IN_RENAME)) {
                        VOP_UNLOCK(fvp);
                        error = EINVAL;
                        goto abortit;
                }
                        VOP_UNLOCK(fvp);
                        error = EINVAL;
                        goto abortit;
                }
-               ip->i_flag |= IRENAME;
+               ip->i_flag |= IN_RENAME;
                oldparent = dp->i_number;
                doingdirectory++;
        }
                oldparent = dp->i_number;
                doingdirectory++;
        }
@@ -961,7 +972,7 @@ abortit:
         *    may be wrong, but correctable.
         */
        ip->i_nlink++;
         *    may be wrong, but correctable.
         */
        ip->i_nlink++;
-       ip->i_flag |= ICHG;
+       ip->i_flag |= IN_CHANGE;
        tv = time;
        if (error = VOP_UPDATE(fvp, &tv, &tv, 1)) {
                VOP_UNLOCK(fvp);
        tv = time;
        if (error = VOP_UPDATE(fvp, &tv, &tv, 1)) {
                VOP_UNLOCK(fvp);
@@ -1020,14 +1031,14 @@ abortit:
                                goto bad;
                        }
                        dp->i_nlink++;
                                goto bad;
                        }
                        dp->i_nlink++;
-                       dp->i_flag |= ICHG;
+                       dp->i_flag |= IN_CHANGE;
                        if (error = VOP_UPDATE(tdvp, &tv, &tv, 1))
                                goto bad;
                }
                if (error = ufs_direnter(ip, tdvp, tcnp)) {
                        if (doingdirectory && newparent) {
                                dp->i_nlink--;
                        if (error = VOP_UPDATE(tdvp, &tv, &tv, 1))
                                goto bad;
                }
                if (error = ufs_direnter(ip, tdvp, tcnp)) {
                        if (doingdirectory && newparent) {
                                dp->i_nlink--;
-                               dp->i_flag |= ICHG;
+                               dp->i_flag |= IN_CHANGE;
                                (void)VOP_UPDATE(tdvp, &tv, &tv, 1);
                        }
                        goto bad;
                                (void)VOP_UPDATE(tdvp, &tv, &tv, 1);
                        }
                        goto bad;
@@ -1047,7 +1058,7 @@ abortit:
                 * otherwise the destination may not be changed (except by
                 * root). This implements append-only directories.
                 */
                 * otherwise the destination may not be changed (except by
                 * root). This implements append-only directories.
                 */
-               if ((dp->i_mode & ISVTX) && tcnp->cn_cred->cr_uid != 0 &&
+               if ((dp->i_mode & S_ISTXT) && tcnp->cn_cred->cr_uid != 0 &&
                    tcnp->cn_cred->cr_uid != dp->i_uid &&
                    xp->i_uid != tcnp->cn_cred->cr_uid) {
                        error = EPERM;
                    tcnp->cn_cred->cr_uid != dp->i_uid &&
                    xp->i_uid != tcnp->cn_cred->cr_uid) {
                        error = EPERM;
@@ -1083,7 +1094,7 @@ abortit:
                 */
                 if (doingdirectory && !newparent) {
                        dp->i_nlink--;
                 */
                 if (doingdirectory && !newparent) {
                        dp->i_nlink--;
-                       dp->i_flag |= ICHG;
+                       dp->i_flag |= IN_CHANGE;
                }
                vput(tdvp);
                /*
                }
                vput(tdvp);
                /*
@@ -1103,7 +1114,7 @@ abortit:
                        error = VOP_TRUNCATE(tvp, (off_t)0, IO_SYNC,
                            tcnp->cn_cred, tcnp->cn_proc);
                }
                        error = VOP_TRUNCATE(tvp, (off_t)0, IO_SYNC,
                            tcnp->cn_cred, tcnp->cn_proc);
                }
-               xp->i_flag |= ICHG;
+               xp->i_flag |= IN_CHANGE;
                vput(tvp);
                xp = NULL;
        }
                vput(tvp);
                xp = NULL;
        }
@@ -1151,7 +1162,7 @@ abortit:
                 */
                if (doingdirectory && newparent) {
                        dp->i_nlink--;
                 */
                if (doingdirectory && newparent) {
                        dp->i_nlink--;
-                       dp->i_flag |= ICHG;
+                       dp->i_flag |= IN_CHANGE;
                        error = vn_rdwr(UIO_READ, fvp, (caddr_t)&dirbuf,
                                sizeof (struct dirtemplate), (off_t)0,
                                UIO_SYSSPACE, IO_NODELOCKED, 
                        error = vn_rdwr(UIO_READ, fvp, (caddr_t)&dirbuf,
                                sizeof (struct dirtemplate), (off_t)0,
                                UIO_SYSSPACE, IO_NODELOCKED, 
@@ -1186,9 +1197,9 @@ abortit:
                error = ufs_dirremove(fdvp, fcnp);
                if (!error) {
                        xp->i_nlink--;
                error = ufs_dirremove(fdvp, fcnp);
                if (!error) {
                        xp->i_nlink--;
-                       xp->i_flag |= ICHG;
+                       xp->i_flag |= IN_CHANGE;
                }
                }
-               xp->i_flag &= ~IRENAME;
+               xp->i_flag &= ~IN_RENAME;
        }
        if (dp)
                vput(fdvp);
        }
        if (dp)
                vput(fdvp);
@@ -1204,7 +1215,7 @@ bad:
 out:
        if (VOP_LOCK(fvp) == 0) {
                ip->i_nlink--;
 out:
        if (VOP_LOCK(fvp) == 0) {
                ip->i_nlink--;
-               ip->i_flag |= ICHG;
+               ip->i_flag |= IN_CHANGE;
                vput(fvp);
        } else
                vrele(fvp);
                vput(fvp);
        } else
                vrele(fvp);
@@ -1256,9 +1267,9 @@ ufs_mkdir(ap)
        dmode = vap->va_mode & 0777;
        dmode |= IFDIR;
        /*
        dmode = vap->va_mode & 0777;
        dmode |= IFDIR;
        /*
-        * Must simulate part of maknode here to acquire the inode, but
-        * not have it entered in the parent directory. The entry is made
-        * later after writing "." and ".." entries.
+        * Must simulate part of ufs_makeinode here to acquire the inode,
+        * but not have it entered in the parent directory. The entry is
+        * made later after writing "." and ".." entries.
         */
        if (error = VOP_VALLOC(dvp, dmode, cnp->cn_cred, &tvp))
                goto out;
         */
        if (error = VOP_VALLOC(dvp, dmode, cnp->cn_cred, &tvp))
                goto out;
@@ -1275,7 +1286,7 @@ ufs_mkdir(ap)
                return (error);
        }
 #endif
                return (error);
        }
 #endif
-       ip->i_flag |= IACC|IUPD|ICHG;
+       ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
        ip->i_mode = dmode;
        tvp->v_type = VDIR;     /* Rest init'd in iget() */
        ip->i_nlink = 2;
        ip->i_mode = dmode;
        tvp->v_type = VDIR;     /* Rest init'd in iget() */
        ip->i_nlink = 2;
@@ -1289,7 +1300,7 @@ ufs_mkdir(ap)
         * so reparation is possible if we crash.
         */
        dp->i_nlink++;
         * so reparation is possible if we crash.
         */
        dp->i_nlink++;
-       dp->i_flag |= ICHG;
+       dp->i_flag |= IN_CHANGE;
        if (error = VOP_UPDATE(dvp, &tv, &tv, 1))
                goto bad;
 
        if (error = VOP_UPDATE(dvp, &tv, &tv, 1))
                goto bad;
 
@@ -1306,20 +1317,20 @@ ufs_mkdir(ap)
            IO_NODELOCKED|IO_SYNC, cnp->cn_cred, (int *)0, (struct proc *)0);
        if (error) {
                dp->i_nlink--;
            IO_NODELOCKED|IO_SYNC, cnp->cn_cred, (int *)0, (struct proc *)0);
        if (error) {
                dp->i_nlink--;
-               dp->i_flag |= ICHG;
+               dp->i_flag |= IN_CHANGE;
                goto bad;
        }
        if (DIRBLKSIZ > VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
                panic("ufs_mkdir: blksize"); /* XXX should grow with balloc() */
        else {
                ip->i_size = DIRBLKSIZ;
                goto bad;
        }
        if (DIRBLKSIZ > VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
                panic("ufs_mkdir: blksize"); /* XXX should grow with balloc() */
        else {
                ip->i_size = DIRBLKSIZ;
-               ip->i_flag |= ICHG;
+               ip->i_flag |= IN_CHANGE;
        }
 
        /* Directory set up, now install it's entry in the parent directory. */
        if (error = ufs_direnter(ip, dvp, cnp)) {
                dp->i_nlink--;
        }
 
        /* Directory set up, now install it's entry in the parent directory. */
        if (error = ufs_direnter(ip, dvp, cnp)) {
                dp->i_nlink--;
-               dp->i_flag |= ICHG;
+               dp->i_flag |= IN_CHANGE;
        }
 bad:
        /*
        }
 bad:
        /*
@@ -1328,7 +1339,7 @@ bad:
         */
        if (error) {
                ip->i_nlink = 0;
         */
        if (error) {
                ip->i_nlink = 0;
-               ip->i_flag |= ICHG;
+               ip->i_flag |= IN_CHANGE;
                vput(tvp);
        } else
                *ap->a_vpp = tvp;
                vput(tvp);
        } else
                *ap->a_vpp = tvp;
@@ -1390,7 +1401,7 @@ ufs_rmdir(ap)
        if (error = ufs_dirremove(dvp, cnp))
                goto out;
        dp->i_nlink--;
        if (error = ufs_dirremove(dvp, cnp))
                goto out;
        dp->i_nlink--;
-       dp->i_flag |= ICHG;
+       dp->i_flag |= IN_CHANGE;
        cache_purge(dvp);
        vput(dvp);
        dvp = NULL;
        cache_purge(dvp);
        vput(dvp);
        dvp = NULL;
@@ -1442,7 +1453,7 @@ ufs_symlink(ap)
                ip = VTOI(vp);
                bcopy(ap->a_target, (char *)ip->i_shortlink, len);
                ip->i_size = len;
                ip = VTOI(vp);
                bcopy(ap->a_target, (char *)ip->i_shortlink, len);
                ip->i_size = len;
-               ip->i_flag |= IUPD|ICHG;
+               ip->i_flag |= IN_CHANGE | IN_UPDATE;
        } else
                error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
                    UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, (int *)0,
        } else
                error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
                    UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, (int *)0,
@@ -1585,8 +1596,8 @@ start:
        if (vp->v_tag == VT_NON)
                return (ENOENT);
        ip = VTOI(vp);
        if (vp->v_tag == VT_NON)
                return (ENOENT);
        ip = VTOI(vp);
-       if (ip->i_flag & ILOCKED) {
-               ip->i_flag |= IWANT;
+       if (ip->i_flag & IN_LOCKED) {
+               ip->i_flag |= IN_WANTED;
 #ifdef DIAGNOSTIC
                if (p) {
                        if (p->p_pid == ip->i_lockholder)
 #ifdef DIAGNOSTIC
                if (p) {
                        if (p->p_pid == ip->i_lockholder)
@@ -1609,7 +1620,7 @@ start:
        else
                ip->i_lockholder = -1;
 #endif
        else
                ip->i_lockholder = -1;
 #endif
-       ip->i_flag |= ILOCKED;
+       ip->i_flag |= IN_LOCKED;
        return (0);
 }
 
        return (0);
 }
 
@@ -1627,7 +1638,7 @@ ufs_unlock(ap)
        struct proc *p = curproc;       /* XXX */
 
 #ifdef DIAGNOSTIC
        struct proc *p = curproc;       /* XXX */
 
 #ifdef DIAGNOSTIC
-       if ((ip->i_flag & ILOCKED) == 0) {
+       if ((ip->i_flag & IN_LOCKED) == 0) {
                vprint("ufs_unlock: unlocked inode", ap->a_vp);
                panic("ufs_unlock NOT LOCKED");
        }
                vprint("ufs_unlock: unlocked inode", ap->a_vp);
                panic("ufs_unlock NOT LOCKED");
        }
@@ -1637,9 +1648,9 @@ ufs_unlock(ap)
                    p->p_pid, ip->i_lockholder);
        ip->i_lockholder = 0;
 #endif
                    p->p_pid, ip->i_lockholder);
        ip->i_lockholder = 0;
 #endif
-       ip->i_flag &= ~ILOCKED;
-       if (ip->i_flag & IWANT) {
-               ip->i_flag &= ~IWANT;
+       ip->i_flag &= ~IN_LOCKED;
+       if (ip->i_flag & IN_WANTED) {
+               ip->i_flag &= ~IN_WANTED;
                wakeup((caddr_t)ip);
        }
        return (0);
                wakeup((caddr_t)ip);
        }
        return (0);
@@ -1655,7 +1666,7 @@ ufs_islocked(ap)
        } */ *ap;
 {
 
        } */ *ap;
 {
 
-       if (VTOI(ap->a_vp)->i_flag & ILOCKED)
+       if (VTOI(ap->a_vp)->i_flag & IN_LOCKED)
                return (1);
        return (0);
 }
                return (1);
        return (0);
 }
@@ -1664,7 +1675,9 @@ ufs_islocked(ap)
  * Calculate the logical to physical mapping if not done already,
  * then call the device strategy routine.
  */
  * Calculate the logical to physical mapping if not done already,
  * then call the device strategy routine.
  */
-int checkblk = 0;
+#include <sys/sysctl.h>
+int checkblk = 1;
+struct ctldebug debug10 = { "checkblk", &checkblk };
 int
 ufs_strategy(ap)
        struct vop_strategy_args /* {
 int
 ufs_strategy(ap)
        struct vop_strategy_args /* {
@@ -1696,9 +1709,11 @@ ufs_strategy(ap)
                /* If this is a clustered block, check sub-blocks as well */
                if (bp->b_saveaddr) {
                        struct buf *tbp;
                /* If this is a clustered block, check sub-blocks as well */
                if (bp->b_saveaddr) {
                        struct buf *tbp;
-                       struct cluster_save *b_save = bp->b_saveaddr;
+                       struct cluster_save *b_save;
                        int i;
                        daddr_t bn;
                        int i;
                        daddr_t bn;
+
+                       b_save = (struct cluster_save *)bp->b_saveaddr;
                        for (i = 0; i < b_save->bs_nchildren; i++) {
                                tbp = b_save->bs_children[i];
                                if ((tbp->b_flags & B_XXX) == 0 &&
                        for (i = 0; i < b_save->bs_nchildren; i++) {
                                tbp = b_save->bs_children[i];
                                if ((tbp->b_flags & B_XXX) == 0 &&
@@ -1744,7 +1759,7 @@ ufs_print(ap)
        if (vp->v_type == VFIFO)
                fifo_printinfo(vp);
 #endif /* FIFO */
        if (vp->v_type == VFIFO)
                fifo_printinfo(vp);
 #endif /* FIFO */
-       printf("%s\n", (ip->i_flag & ILOCKED) ? " (LOCKED)" : "");
+       printf("%s\n", (ip->i_flag & IN_LOCKED) ? " (LOCKED)" : "");
        if (ip->i_lockholder == 0)
                return (0);
        printf("\towner pid %d", ip->i_lockholder);
        if (ip->i_lockholder == 0)
                return (0);
        printf("\towner pid %d", ip->i_lockholder);
@@ -1770,7 +1785,7 @@ ufsspec_read(ap)
        /*
         * Set access flag.
         */
        /*
         * Set access flag.
         */
-       VTOI(ap->a_vp)->i_flag |= IACC;
+       VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
        return (VOCALL (spec_vnodeop_p, VOFFSET(vop_read), ap));
 }
 
        return (VOCALL (spec_vnodeop_p, VOFFSET(vop_read), ap));
 }
 
@@ -1790,7 +1805,7 @@ ufsspec_write(ap)
        /*
         * Set update and change flags.
         */
        /*
         * Set update and change flags.
         */
-       VTOI(ap->a_vp)->i_flag |= IUPD|ICHG;
+       VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
        return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap));
 }
 
        return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap));
 }
 
@@ -1810,7 +1825,7 @@ ufsspec_close(ap)
 {
        register struct inode *ip = VTOI(ap->a_vp);
 
 {
        register struct inode *ip = VTOI(ap->a_vp);
 
-       if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & ILOCKED))
+       if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED))
                ITIMES(ip, &time, &time);
        return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
 }
                ITIMES(ip, &time, &time);
        return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
 }
@@ -1833,7 +1848,7 @@ ufsfifo_read(ap)
        /*
         * Set access flag.
         */
        /*
         * Set access flag.
         */
-       VTOI(ap->a_vp)->i_flag |= IACC;
+       VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
        return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_read), ap));
 }
 
        return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_read), ap));
 }
 
@@ -1854,7 +1869,7 @@ ufsfifo_write(ap)
        /*
         * Set update and change flags.
         */
        /*
         * Set update and change flags.
         */
-       VTOI(ap->a_vp)->i_flag |= IUPD|ICHG;
+       VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
        return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_write), ap));
 }
 
        return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_write), ap));
 }
 
@@ -1874,12 +1889,48 @@ ufsfifo_close(ap)
        extern int (**fifo_vnodeop_p)();
        register struct inode *ip = VTOI(ap->a_vp);
 
        extern int (**fifo_vnodeop_p)();
        register struct inode *ip = VTOI(ap->a_vp);
 
-       if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & ILOCKED))
+       if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED))
                ITIMES(ip, &time, &time);
        return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
 }
 #endif /* FIFO */
 
                ITIMES(ip, &time, &time);
        return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
 }
 #endif /* FIFO */
 
+/*
+ * Return POSIX pathconf information applicable to ufs filesystems.
+ */
+ufs_pathconf(ap)
+       struct vop_pathconf_args /* {
+               struct vnode *a_vp;
+               int a_name;
+               int *a_retval;
+       } */ *ap;
+{
+
+       switch (ap->a_name) {
+       case _PC_LINK_MAX:
+               *ap->a_retval = LINK_MAX;
+               return (0);
+       case _PC_NAME_MAX:
+               *ap->a_retval = NAME_MAX;
+               return (0);
+       case _PC_PATH_MAX:
+               *ap->a_retval = PATH_MAX;
+               return (0);
+       case _PC_PIPE_BUF:
+               *ap->a_retval = PIPE_BUF;
+               return (0);
+       case _PC_CHOWN_RESTRICTED:
+               *ap->a_retval = 1;
+               return (0);
+       case _PC_NO_TRUNC:
+               *ap->a_retval = 1;
+               return (0);
+       default:
+               return (EINVAL);
+       }
+       /* NOTREACHED */
+}
+
 /*
  * Advisory record locking support
  */
 /*
  * Advisory record locking support
  */
@@ -2059,8 +2110,11 @@ ufs_makeinode(mode, dvp, vpp, cnp)
                return (error);
        }
        ip = VTOI(tvp);
                return (error);
        }
        ip = VTOI(tvp);
-       ip->i_uid = cnp->cn_cred->cr_uid;
        ip->i_gid = pdir->i_gid;
        ip->i_gid = pdir->i_gid;
+       if ((mode & IFMT) == IFLNK)
+               ip->i_uid = pdir->i_uid;
+       else
+               ip->i_uid = cnp->cn_cred->cr_uid;
 #ifdef QUOTA
        if ((error = getinoquota(ip)) ||
            (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
 #ifdef QUOTA
        if ((error = getinoquota(ip)) ||
            (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
@@ -2071,7 +2125,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
                return (error);
        }
 #endif
                return (error);
        }
 #endif
-       ip->i_flag |= IACC|IUPD|ICHG;
+       ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
        ip->i_mode = mode;
        tvp->v_type = IFTOVT(mode);     /* Rest init'd in iget() */
        ip->i_nlink = 1;
        ip->i_mode = mode;
        tvp->v_type = IFTOVT(mode);     /* Rest init'd in iget() */
        ip->i_nlink = 1;
@@ -2101,7 +2155,7 @@ bad:
        free(cnp->cn_pnbuf, M_NAMEI);
        vput(dvp);
        ip->i_nlink = 0;
        free(cnp->cn_pnbuf, M_NAMEI);
        vput(dvp);
        ip->i_nlink = 0;
-       ip->i_flag |= ICHG;
+       ip->i_flag |= IN_CHANGE;
        vput(tvp);
        return (error);
 }
        vput(tvp);
        return (error);
 }