update syscalls.master
[unix-history] / usr / src / sys / kern / vfs_syscalls.c
index 9787ee5..015cede 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)vfs_syscalls.c      7.101 (Berkeley) %G%
+ *     @(#)vfs_syscalls.c      7.108 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -22,6 +22,7 @@
 #include <sys/dirent.h>
 
 #include <vm/vm.h>
 #include <sys/dirent.h>
 
 #include <vm/vm.h>
+#include <sys/sysctl.h>
 
 #ifdef REF_DIAGNOSTIC
 #define CURCOUNT (curproc ? curproc->p_spare[0] : 0)
 
 #ifdef REF_DIAGNOSTIC
 #define CURCOUNT (curproc ? curproc->p_spare[0] : 0)
@@ -94,7 +95,7 @@ mount(p, uap, retval)
                vput(vp);
                return (EBUSY);
        }
                vput(vp);
                return (EBUSY);
        }
-       if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p))
+       if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
                return (error);
        if (vp->v_type != VDIR) {
                vput(vp);
                return (error);
        if (vp->v_type != VDIR) {
                vput(vp);
@@ -258,6 +259,7 @@ dounmount(mp, flags, p)
  */
 #ifdef DIAGNOSTIC
 int syncprt = 0;
  */
 #ifdef DIAGNOSTIC
 int syncprt = 0;
+struct ctldebug debug0 = { "syncprt", &syncprt };
 #endif
 
 struct sync_args {
 #endif
 
 struct sync_args {
@@ -860,10 +862,12 @@ unlink(p, uap, retval)
        struct nameidata nd;
 
        CHECKPOINTREF;
        struct nameidata nd;
 
        CHECKPOINTREF;
-       NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->name, p);
+       NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->name, p);
        if (error = namei(&nd))
                return (error);
        vp = nd.ni_vp;
        if (error = namei(&nd))
                return (error);
        vp = nd.ni_vp;
+       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
+       VOP_LOCK(vp);
        if (vp->v_type == VDIR &&
            (error = suser(p->p_ucred, &p->p_acflag)))
                goto out;
        if (vp->v_type == VDIR &&
            (error = suser(p->p_ucred, &p->p_acflag)))
                goto out;
@@ -878,7 +882,6 @@ unlink(p, uap, retval)
 out:
        if (!error) {
                LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 out:
        if (!error) {
                LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
-               LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
                error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
        } else {
                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
        } else {
                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -1151,17 +1154,47 @@ lstat(p, uap, retval)
        register struct lstat_args *uap;
        int *retval;
 {
        register struct lstat_args *uap;
        int *retval;
 {
-       struct stat sb;
        int error;
        int error;
+       struct vnode *vp, *dvp;
+       struct stat sb, sb1;
        struct nameidata nd;
 
        struct nameidata nd;
 
-       NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
+       NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
+           uap->fname, p);
        if (error = namei(&nd))
                return (error);
        if (error = namei(&nd))
                return (error);
-       error = vn_stat(nd.ni_vp, &sb, p);
-       vput(nd.ni_vp);
-       if (error)
-               return (error);
+       /*
+        * For symbolic links, always return the attributes of its
+        * containing directory, except for mode, size, and links.
+        */
+       vp = nd.ni_vp;
+       dvp = nd.ni_dvp;
+       if (vp->v_type != VLNK) {
+               if (dvp == vp)
+                       vrele(dvp);
+               else
+                       vput(dvp);
+               error = vn_stat(vp, &sb, p);
+               vput(vp);
+               if (error)
+                       return (error);
+       } else {
+               error = vn_stat(dvp, &sb, p);
+               vput(dvp);
+               if (error) {
+                       vput(vp);
+                       return (error);
+               }
+               error = vn_stat(vp, &sb1, p);
+               vput(vp);
+               if (error)
+                       return (error);
+               sb.st_mode &= ~S_IFDIR;
+               sb.st_mode |= S_IFLNK;
+               sb.st_nlink = sb1.st_nlink;
+               sb.st_size = sb1.st_size;
+               sb.st_blocks = sb1.st_blocks;
+       }
        error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
        return (error);
 }
        error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
        return (error);
 }
@@ -1230,17 +1263,18 @@ chflags(p, uap, retval)
        int error;
        struct nameidata nd;
 
        int error;
        struct nameidata nd;
 
-       NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
+       NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
        if (error = namei(&nd))
                return (error);
        vp = nd.ni_vp;
        if (error = namei(&nd))
                return (error);
        vp = nd.ni_vp;
+       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
+       VOP_LOCK(vp);
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
                goto out;
        }
        VATTR_NULL(&vattr);
        vattr.va_flags = uap->flags;
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
                goto out;
        }
        VATTR_NULL(&vattr);
        vattr.va_flags = uap->flags;
-       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        vput(vp);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        vput(vp);
@@ -1268,6 +1302,7 @@ fchflags(p, uap, retval)
        if (error = getvnode(p->p_fd, uap->fd, &fp))
                return (error);
        vp = (struct vnode *)fp->f_data;
        if (error = getvnode(p->p_fd, uap->fd, &fp))
                return (error);
        vp = (struct vnode *)fp->f_data;
+       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
        VOP_LOCK(vp);
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
        VOP_LOCK(vp);
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
@@ -1275,7 +1310,6 @@ fchflags(p, uap, retval)
        }
        VATTR_NULL(&vattr);
        vattr.va_flags = uap->flags;
        }
        VATTR_NULL(&vattr);
        vattr.va_flags = uap->flags;
-       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        VOP_UNLOCK(vp);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        VOP_UNLOCK(vp);
@@ -1300,17 +1334,18 @@ chmod(p, uap, retval)
        int error;
        struct nameidata nd;
 
        int error;
        struct nameidata nd;
 
-       NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
+       NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
        if (error = namei(&nd))
                return (error);
        vp = nd.ni_vp;
        if (error = namei(&nd))
                return (error);
        vp = nd.ni_vp;
+       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
+       VOP_LOCK(vp);
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
                goto out;
        }
        VATTR_NULL(&vattr);
        vattr.va_mode = uap->fmode & 07777;
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
                goto out;
        }
        VATTR_NULL(&vattr);
        vattr.va_mode = uap->fmode & 07777;
-       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        vput(vp);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        vput(vp);
@@ -1338,6 +1373,7 @@ fchmod(p, uap, retval)
        if (error = getvnode(p->p_fd, uap->fd, &fp))
                return (error);
        vp = (struct vnode *)fp->f_data;
        if (error = getvnode(p->p_fd, uap->fd, &fp))
                return (error);
        vp = (struct vnode *)fp->f_data;
+       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
        VOP_LOCK(vp);
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
        VOP_LOCK(vp);
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
@@ -1345,7 +1381,6 @@ fchmod(p, uap, retval)
        }
        VATTR_NULL(&vattr);
        vattr.va_mode = uap->fmode & 07777;
        }
        VATTR_NULL(&vattr);
        vattr.va_mode = uap->fmode & 07777;
-       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        VOP_UNLOCK(vp);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        VOP_UNLOCK(vp);
@@ -1371,10 +1406,12 @@ chown(p, uap, retval)
        int error;
        struct nameidata nd;
 
        int error;
        struct nameidata nd;
 
-       NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
+       NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, p);
        if (error = namei(&nd))
                return (error);
        vp = nd.ni_vp;
        if (error = namei(&nd))
                return (error);
        vp = nd.ni_vp;
+       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
+       VOP_LOCK(vp);
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
                goto out;
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
                goto out;
@@ -1382,7 +1419,6 @@ chown(p, uap, retval)
        VATTR_NULL(&vattr);
        vattr.va_uid = uap->uid;
        vattr.va_gid = uap->gid;
        VATTR_NULL(&vattr);
        vattr.va_uid = uap->uid;
        vattr.va_gid = uap->gid;
-       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        vput(vp);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        vput(vp);
@@ -1411,6 +1447,7 @@ fchown(p, uap, retval)
        if (error = getvnode(p->p_fd, uap->fd, &fp))
                return (error);
        vp = (struct vnode *)fp->f_data;
        if (error = getvnode(p->p_fd, uap->fd, &fp))
                return (error);
        vp = (struct vnode *)fp->f_data;
+       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
        VOP_LOCK(vp);
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
        VOP_LOCK(vp);
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
@@ -1419,7 +1456,6 @@ fchown(p, uap, retval)
        VATTR_NULL(&vattr);
        vattr.va_uid = uap->uid;
        vattr.va_gid = uap->gid;
        VATTR_NULL(&vattr);
        vattr.va_uid = uap->uid;
        vattr.va_gid = uap->gid;
-       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        VOP_UNLOCK(vp);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        VOP_UNLOCK(vp);
@@ -1445,22 +1481,27 @@ utimes(p, uap, retval)
        int error;
        struct nameidata nd;
 
        int error;
        struct nameidata nd;
 
-       if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
-               return (error);
-       NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
+       VATTR_NULL(&vattr);
+       if (uap->tptr == NULL) {
+               microtime(&tv[0]);
+               tv[1] = tv[0];
+               vattr.va_vaflags |= VA_UTIMES_NULL;
+       } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
+               return (error);
+       NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
        if (error = namei(&nd))
                return (error);
        vp = nd.ni_vp;
        if (error = namei(&nd))
                return (error);
        vp = nd.ni_vp;
+       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
+       VOP_LOCK(vp);
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
                goto out;
        }
        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                error = EROFS;
                goto out;
        }
-       VATTR_NULL(&vattr);
        vattr.va_atime.ts_sec = tv[0].tv_sec;
        vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
        vattr.va_mtime.ts_sec = tv[1].tv_sec;
        vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
        vattr.va_atime.ts_sec = tv[0].tv_sec;
        vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
        vattr.va_mtime.ts_sec = tv[1].tv_sec;
        vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
-       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        vput(vp);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        vput(vp);
@@ -1487,10 +1528,12 @@ __truncate(p, uap, retval)
        int error;
        struct nameidata nd;
 
        int error;
        struct nameidata nd;
 
-       NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
+       NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
        if (error = namei(&nd))
                return (error);
        vp = nd.ni_vp;
        if (error = namei(&nd))
                return (error);
        vp = nd.ni_vp;
+       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
+       VOP_LOCK(vp);
        if (vp->v_type == VDIR) {
                error = EISDIR;
                goto out;
        if (vp->v_type == VDIR) {
                error = EISDIR;
                goto out;
@@ -1500,7 +1543,6 @@ __truncate(p, uap, retval)
                goto out;
        VATTR_NULL(&vattr);
        vattr.va_size = uap->length;
                goto out;
        VATTR_NULL(&vattr);
        vattr.va_size = uap->length;
-       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        vput(vp);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 out:
        vput(vp);
@@ -1532,6 +1574,7 @@ __ftruncate(p, uap, retval)
        if ((fp->f_flag & FWRITE) == 0)
                return (EINVAL);
        vp = (struct vnode *)fp->f_data;
        if ((fp->f_flag & FWRITE) == 0)
                return (EINVAL);
        vp = (struct vnode *)fp->f_data;
+       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
        VOP_LOCK(vp);
        if (vp->v_type == VDIR) {
                error = EISDIR;
        VOP_LOCK(vp);
        if (vp->v_type == VDIR) {
                error = EISDIR;
@@ -1541,7 +1584,6 @@ __ftruncate(p, uap, retval)
                goto out;
        VATTR_NULL(&vattr);
        vattr.va_size = uap->length;
                goto out;
        VATTR_NULL(&vattr);
        vattr.va_size = uap->length;
-       LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
        error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
 out:
        VOP_UNLOCK(vp);
        error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
 out:
        VOP_UNLOCK(vp);