diff options
Diffstat (limited to 'sys/kern/vfs_extattr.c')
-rw-r--r-- | sys/kern/vfs_extattr.c | 1321 |
1 files changed, 858 insertions, 463 deletions
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 22e16d84..83b6dec 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -50,6 +50,7 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/sysent.h> #include <sys/sysproto.h> #include <sys/namei.h> #include <sys/filedesc.h> @@ -64,9 +65,11 @@ #include <sys/malloc.h> #include <sys/dirent.h> +/* see if this is needed XXX JH #ifdef UNION #include <miscfs/union/union.h> #endif +*/ #include <vm/vm.h> #include <vm/vm_param.h> @@ -74,7 +77,8 @@ #include <vm/vm_extern.h> #include <sys/sysctl.h> -static int change_dir __P((struct nameidata *ndp, struct proc *p)); +static int change_dir __P((struct nameidata *ndp, struct proc *p)); +static void checkdirs __P((struct vnode *olddp)); /* * Virtual File System System Calls @@ -85,7 +89,7 @@ static int change_dir __P((struct nameidata *ndp, struct proc *p)); */ #ifndef _SYS_SYSPROTO_H_ struct mount_args { - int type; + char *type; char *path; int flags; caddr_t data; @@ -95,29 +99,32 @@ struct mount_args { int mount(p, uap, retval) struct proc *p; - register struct mount_args *uap; - int *retval; + register struct mount_args /* { + syscallarg(char *) type; + syscallarg(char *) path; + syscallarg(int) flags; + syscallarg(caddr_t) data; + } */ *uap; + register_t *retval; { - register struct vnode *vp; - register struct mount *mp; + struct vnode *vp; + struct mount *mp; + struct vfsconf *vfsp; int error, flag = 0; + struct vattr va; + u_long fstypenum; struct nameidata nd; + char fstypename[MFSNAMELEN]; /* - * Must be super user - */ - error = suser(p->p_ucred, &p->p_acflag); - if (error) - return (error); - /* * Get vnode to be covered */ - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); + if (error = namei(&nd)) return (error); vp = nd.ni_vp; - if (uap->flags & MNT_UPDATE) { + if (SCARG(uap, flags) & MNT_UPDATE) { if ((vp->v_flag & VROOT) == 0) { vput(vp); return (EINVAL); @@ -128,68 +135,135 @@ mount(p, uap, retval) * We only allow the filesystem to be reloaded if it * is currently mounted read-only. */ - if ((uap->flags & MNT_RELOAD) && + if ((SCARG(uap, flags) & MNT_RELOAD) && ((mp->mnt_flag & MNT_RDONLY) == 0)) { vput(vp); return (EOPNOTSUPP); /* Needs translation */ } mp->mnt_flag |= - uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE); - VOP_UNLOCK(vp); + SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE); + /* + * Only root, or the user that did the original mount is + * permitted to update it. + */ + if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid && + (error = suser(p->p_ucred, &p->p_acflag))) { + vput(vp); + return (error); + } + /* + * Do not allow NFS export by non-root users. Silently + * enforce MNT_NOSUID and MNT_NODEV for non-root users. + */ + if (p->p_ucred->cr_uid != 0) { + if (SCARG(uap, flags) & MNT_EXPORTED) { + vput(vp); + return (EPERM); + } + SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; + } + if (vfs_busy(mp, LK_NOWAIT, 0, p)) { + vput(vp); + return (EBUSY); + } + VOP_UNLOCK(vp, 0, p); goto update; } - error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0); - if (error) + /* + * If the user is not root, ensure that they own the directory + * onto which we are attempting to mount. + */ + if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) || + (va.va_uid != p->p_ucred->cr_uid && + (error = suser(p->p_ucred, &p->p_acflag)))) { + vput(vp); + return (error); + } + /* + * Do not allow NFS export by non-root users. Silently + * enforce MNT_NOSUID and MNT_NODEV for non-root users. + */ + if (p->p_ucred->cr_uid != 0) { + if (SCARG(uap, flags) & MNT_EXPORTED) { + vput(vp); + return (EPERM); + } + SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; + } + if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) return (error); if (vp->v_type != VDIR) { vput(vp); return (ENOTDIR); } - if ((u_long)uap->type > MOUNT_MAXTYPE || vfssw[uap->type] == NULL) { - vput(vp); - return (ENODEV); - } - +#ifdef COMPAT_43 /* - * Allocate and initialize the file system. + * Historically filesystem types were identified by number. If we + * get an integer for the filesystem type instead of a string, we + * check to see if it matches one of the historic filesystem types. */ - mp = (struct mount *)malloc((u_long)sizeof(struct mount), - M_MOUNT, M_WAITOK); - bzero((char *)mp, (u_long)sizeof(struct mount)); - mp->mnt_op = vfssw[uap->type]; - mp->mnt_vfc = vfsconf[uap->type]; - error = vfs_lock(mp); - if (error) { - free((caddr_t)mp, M_MOUNT); + fstypenum = (u_long)SCARG(uap, type); + if (fstypenum < maxvfsconf) { + for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) + if (vfsp->vfc_typenum == fstypenum) + break; + if (vfsp == NULL) { + vput(vp); + return (ENODEV); + } + strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN); + } else +#endif /* COMPAT_43 */ + if (error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) { vput(vp); return (error); } + for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) + if (!strcmp(vfsp->vfc_name, fstypename)) + break; + if (vfsp == NULL) { + vput(vp); + return (ENODEV); + } if (vp->v_mountedhere != NULL) { - vfs_unlock(mp); - free((caddr_t)mp, M_MOUNT); vput(vp); return (EBUSY); } + + /* + * Allocate and initialize the filesystem. + */ + mp = (struct mount *)malloc((u_long)sizeof(struct mount), + M_MOUNT, M_WAITOK); + bzero((char *)mp, (u_long)sizeof(struct mount)); + lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); + (void)vfs_busy(mp, LK_NOWAIT, 0, p); + mp->mnt_op = vfsp->vfc_vfsops; + mp->mnt_vfc = vfsp; + vfsp->vfc_refcount++; + mp->mnt_stat.f_type = vfsp->vfc_typenum; + mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; + strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); vp->v_mountedhere = mp; mp->mnt_vnodecovered = vp; - vfsconf[uap->type]->vfc_refcount++; - + mp->mnt_stat.f_owner = p->p_ucred->cr_uid; update: /* * Set the mount level flags. */ - if (uap->flags & MNT_RDONLY) + if (SCARG(uap, flags) & MNT_RDONLY) mp->mnt_flag |= MNT_RDONLY; else if (mp->mnt_flag & MNT_RDONLY) mp->mnt_flag |= MNT_WANTRDWR; mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME); - mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | - MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE | MNT_NOATIME); + mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC | + MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE | + MNT_NOATIME); /* * Mount the filesystem. */ - error = VFS_MOUNT(mp, uap->path, uap->data, &nd, p); + error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p); if (mp->mnt_flag & MNT_UPDATE) { vrele(vp); if (mp->mnt_flag & MNT_WANTRDWR) @@ -198,6 +272,7 @@ update: (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR); if (error) mp->mnt_flag = flag; + vfs_unbusy(mp, p); return (error); } /* @@ -205,23 +280,63 @@ update: */ cache_purge(vp); if (!error) { + simple_lock(&mountlist_slock); CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); - VOP_UNLOCK(vp); - vfs_unlock(mp); - error = VFS_START(mp, 0, p); - if (error) + simple_unlock(&mountlist_slock); + checkdirs(vp); + VOP_UNLOCK(vp, 0, p); + vfs_unbusy(mp, p); + if (error = VFS_START(mp, 0, p)) vrele(vp); } else { mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; - vfs_unlock(mp); + mp->mnt_vfc->vfc_refcount--; + vfs_unbusy(mp, p); free((caddr_t)mp, M_MOUNT); vput(vp); - vfsconf[uap->type]->vfc_refcount--; } return (error); } /* + * Scan all active processes to see if any of them have a current + * or root directory onto which the new filesystem has just been + * mounted. If so, replace them with the new mount point. + */ +static void +checkdirs(olddp) + struct vnode *olddp; +{ + struct filedesc *fdp; + struct vnode *newdp; + struct proc *p; + + if (olddp->v_usecount == 1) + return; + if (VFS_ROOT(olddp->v_mountedhere, &newdp)) + panic("mount: lost mount"); + for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { + fdp = p->p_fd; + if (fdp->fd_cdir == olddp) { + vrele(fdp->fd_cdir); + VREF(newdp); + fdp->fd_cdir = newdp; + } + if (fdp->fd_rdir == olddp) { + vrele(fdp->fd_rdir); + VREF(newdp); + fdp->fd_rdir = newdp; + } + } + if (rootvnode == olddp) { + vrele(rootvnode); + VREF(newdp); + rootvnode = newdp; + } + vput(newdp); +} + +/* * Unmount a file system. * * Note: unmount takes a path to the vnode mounted on as argument, @@ -237,47 +352,51 @@ struct unmount_args { int unmount(p, uap, retval) struct proc *p; - register struct unmount_args *uap; - int *retval; + register struct unmount_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct mount *mp; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); + if (error = namei(&nd)) return (error); vp = nd.ni_vp; + mp = vp->v_mount; /* - * Unless this is a user mount, then must - * have suser privilege. + * Only root, or the user that did the original mount is + * permitted to unmount this filesystem. */ - if (((vp->v_mount->mnt_flag & MNT_USER) == 0) && + if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) && (error = suser(p->p_ucred, &p->p_acflag))) { vput(vp); return (error); } /* - * Must be the root of the filesystem + * Don't allow unmounting the root file system. */ - if ((vp->v_flag & VROOT) == 0) { + if (mp->mnt_flag & MNT_ROOTFS) { vput(vp); return (EINVAL); } - mp = vp->v_mount; - vput(vp); /* - * Don't allow unmount of the root filesystem + * Must be the root of the filesystem */ - if (mp->mnt_flag & MNT_ROOTFS) + if ((vp->v_flag & VROOT) == 0) { + vput(vp); return (EINVAL); - - return (dounmount(mp, uap->flags, p)); + } + vput(vp); + return (dounmount(mp, SCARG(uap, flags), p)); } /* @@ -292,74 +411,86 @@ dounmount(mp, flags, p) struct vnode *coveredvp; int error; - coveredvp = mp->mnt_vnodecovered; - if (vfs_busy(mp)) - return (EBUSY); + simple_lock(&mountlist_slock); mp->mnt_flag |= MNT_UNMOUNT; - error = vfs_lock(mp); - if (error) - return (error); - + lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p); mp->mnt_flag &=~ MNT_ASYNC; vfs_msync(mp, MNT_NOWAIT); vnode_pager_umount(mp); /* release cached vnodes */ cache_purgevfs(mp); /* remove cache entries for this file sys */ - if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 || + if (((mp->mnt_flag & MNT_RDONLY) || + (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) || (flags & MNT_FORCE)) error = VFS_UNMOUNT(mp, flags, p); - mp->mnt_flag &= ~MNT_UNMOUNT; - vfs_unbusy(mp); + simple_lock(&mountlist_slock); if (error) { - vfs_unlock(mp); - } else { + mp->mnt_flag &= ~MNT_UNMOUNT; + lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE, + &mountlist_slock, p); + return (error); + } + CIRCLEQ_REMOVE(&mountlist, mp, mnt_list); + if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { + coveredvp->v_mountedhere = (struct mount *)0; vrele(coveredvp); - CIRCLEQ_REMOVE(&mountlist, mp, mnt_list); - mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; - vfs_unlock(mp); - mp->mnt_vfc->vfc_refcount--; - if (mp->mnt_vnodelist.lh_first != NULL) - panic("unmount: dangling vnode"); - free((caddr_t)mp, M_MOUNT); } - return (error); + mp->mnt_vfc->vfc_refcount--; + if (mp->mnt_vnodelist.lh_first != NULL) + panic("unmount: dangling vnode"); + lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p); + if (mp->mnt_flag & MNT_MWAIT) + wakeup((caddr_t)mp); + free((caddr_t)mp, M_MOUNT); + return (0); } /* * Sync each mounted filesystem. */ - #ifndef _SYS_SYSPROTO_H_ struct sync_args { int dummy; }; #endif +#ifdef DEBUG +int syncprt = 0; +SYSCTL_INT(_debug, 0, syncprt, CTLFLAG_RW, &syncprt, 0, ""); +#endif + /* ARGSUSED */ int sync(p, uap, retval) struct proc *p; struct sync_args *uap; - int *retval; + register_t *retval; { - register struct mount *mp; + register struct mount *mp, *nmp; int asyncflag; - for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = mp->mnt_list.cqe_next) { - /* - * The lock check below is to avoid races with mount - * and unmount. - */ - if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 && - !vfs_busy(mp)) { + simple_lock(&mountlist_slock); + for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { + if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { + nmp = mp->mnt_list.cqe_next; + continue; + } + if ((mp->mnt_flag & MNT_RDONLY) == 0) { asyncflag = mp->mnt_flag & MNT_ASYNC; mp->mnt_flag &= ~MNT_ASYNC; vfs_msync(mp, MNT_NOWAIT); VFS_SYNC(mp, MNT_NOWAIT, p != NULL ? p->p_ucred : NOCRED, p); if (asyncflag) mp->mnt_flag |= MNT_ASYNC; - vfs_unbusy(mp); } + simple_lock(&mountlist_slock); + nmp = mp->mnt_list.cqe_next; + vfs_unbusy(mp, p); } + simple_unlock(&mountlist_slock); +#ifdef DIAGNOSTIC + if (syncprt) + vfs_bufstats(); +#endif /* DIAGNOSTIC */ return (0); } @@ -378,20 +509,25 @@ struct quotactl_args { int quotactl(p, uap, retval) struct proc *p; - register struct quotactl_args *uap; - int *retval; + register struct quotactl_args /* { + syscallarg(char *) path; + syscallarg(int) cmd; + syscallarg(int) uid; + syscallarg(caddr_t) arg; + } */ *uap; + register_t *retval; { register struct mount *mp; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + if (error = namei(&nd)) return (error); mp = nd.ni_vp->v_mount; vrele(nd.ni_vp); - return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p)); + return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), + SCARG(uap, arg), p)); } /* @@ -407,17 +543,19 @@ struct statfs_args { int statfs(p, uap, retval) struct proc *p; - register struct statfs_args *uap; - int *retval; + register struct statfs_args /* { + syscallarg(char *) path; + syscallarg(struct statfs *) buf; + } */ *uap; + register_t *retval; { register struct mount *mp; register struct statfs *sp; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + if (error = namei(&nd)) return (error); mp = nd.ni_vp->v_mount; sp = &mp->mnt_stat; @@ -426,7 +564,7 @@ statfs(p, uap, retval) if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); + return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); } /* @@ -442,16 +580,18 @@ struct fstatfs_args { int fstatfs(p, uap, retval) struct proc *p; - register struct fstatfs_args *uap; - int *retval; + register struct fstatfs_args /* { + syscallarg(int) fd; + syscallarg(struct statfs *) buf; + } */ *uap; + register_t *retval; { struct file *fp; struct mount *mp; register struct statfs *sp; int error; - error = getvnode(p->p_fd, uap->fd, &fp); - if (error) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); mp = ((struct vnode *)fp->f_data)->v_mount; sp = &mp->mnt_stat; @@ -459,7 +599,7 @@ fstatfs(p, uap, retval) if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); + return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); } /* @@ -475,48 +615,55 @@ struct getfsstat_args { int getfsstat(p, uap, retval) struct proc *p; - register struct getfsstat_args *uap; - int *retval; + register struct getfsstat_args /* { + syscallarg(struct statfs *) buf; + syscallarg(long) bufsize; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { register struct mount *mp, *nmp; register struct statfs *sp; caddr_t sfsp; long count, maxcount, error; - maxcount = uap->bufsize / sizeof(struct statfs); - sfsp = (caddr_t)uap->buf; + maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); + sfsp = (caddr_t)SCARG(uap, buf); count = 0; + simple_lock(&mountlist_slock); for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { - if (vfs_busy(mp)) { + if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { nmp = mp->mnt_list.cqe_next; continue; } - if (sfsp && count < maxcount && - ((mp->mnt_flag & MNT_MLOCK) == 0)) { + if (sfsp && count < maxcount) { sp = &mp->mnt_stat; /* * If MNT_NOWAIT is specified, do not refresh the * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. */ - if (((uap->flags & MNT_NOWAIT) == 0 || - (uap->flags & MNT_WAIT)) && + if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 || + (SCARG(uap, flags) & MNT_WAIT)) && (error = VFS_STATFS(mp, sp, p))) { + simple_lock(&mountlist_slock); nmp = mp->mnt_list.cqe_next; - vfs_unbusy(mp); + vfs_unbusy(mp, p); continue; } sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; error = copyout((caddr_t)sp, sfsp, sizeof(*sp)); if (error) { - vfs_unbusy(mp); + vfs_unbusy(mp, p); return (error); } sfsp += sizeof(*sp); } count++; + simple_lock(&mountlist_slock); nmp = mp->mnt_list.cqe_next; - vfs_unbusy(mp); + vfs_unbusy(mp, p); } + simple_unlock(&mountlist_slock); if (sfsp && count > maxcount) *retval = maxcount; else @@ -536,27 +683,41 @@ struct fchdir_args { int fchdir(p, uap, retval) struct proc *p; - struct fchdir_args *uap; - int *retval; + struct fchdir_args /* { + syscallarg(int) fd; + } */ *uap; + register_t *retval; { register struct filedesc *fdp = p->p_fd; - register struct vnode *vp; + struct vnode *vp, *tdp; + struct mount *mp; struct file *fp; int error; - error = getvnode(fdp, uap->fd, &fp); - if (error) + if (error = getvnode(fdp, SCARG(uap, fd), &fp)) return (error); vp = (struct vnode *)fp->f_data; - VOP_LOCK(vp); + VREF(vp); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); if (vp->v_type != VDIR) error = ENOTDIR; else error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); - VOP_UNLOCK(vp); - if (error) + while (!error && (mp = vp->v_mountedhere) != NULL) { + if (vfs_busy(mp, 0, 0, p)) + continue; + error = VFS_ROOT(mp, &tdp); + vfs_unbusy(mp, p); + if (error) + break; + vput(vp); + vp = tdp; + } + if (error) { + vput(vp); return (error); - VREF(vp); + } + VOP_UNLOCK(vp, 0, p); vrele(fdp->fd_cdir); fdp->fd_cdir = vp; return (0); @@ -574,16 +735,18 @@ struct chdir_args { int chdir(p, uap, retval) struct proc *p; - struct chdir_args *uap; - int *retval; + struct chdir_args /* { + syscallarg(char *) path; + } */ *uap; + register_t *retval; { register struct filedesc *fdp = p->p_fd; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); - error = change_dir(&nd, p); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); + if (error = change_dir(&nd, p)) return (error); vrele(fdp->fd_cdir); fdp->fd_cdir = nd.ni_vp; @@ -602,8 +765,10 @@ struct chroot_args { int chroot(p, uap, retval) struct proc *p; - struct chroot_args *uap; - int *retval; + struct chroot_args /* { + syscallarg(char *) path; + } */ *uap; + register_t *retval; { register struct filedesc *fdp = p->p_fd; int error; @@ -612,9 +777,9 @@ chroot(p, uap, retval) error = suser(p->p_ucred, &p->p_acflag); if (error) return (error); - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); - error = change_dir(&nd, p); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); + if (error = change_dir(&nd, p)) return (error); if (fdp->fd_rdir != NULL) vrele(fdp->fd_rdir); @@ -641,9 +806,10 @@ change_dir(ndp, p) error = ENOTDIR; else error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); - VOP_UNLOCK(vp); if (error) - vrele(vp); + vput(vp); + else + VOP_UNLOCK(vp, 0, p); return (error); } @@ -661,8 +827,12 @@ struct open_args { int open(p, uap, retval) struct proc *p; - register struct open_args *uap; - int *retval; + register struct open_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + syscallarg(int) mode; + } */ *uap; + register_t *retval; { register struct filedesc *fdp = p->p_fd; register struct file *fp; @@ -677,17 +847,17 @@ open(p, uap, retval) if (error) return (error); fp = nfp; - flags = FFLAGS(uap->flags); - cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); + flags = FFLAGS(SCARG(uap, flags)); + cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); p->p_dupfd = -indx - 1; /* XXX check for fdopen */ error = vn_open(&nd, flags, cmode); if (error) { ffree(fp); if ((error == ENODEV || error == ENXIO) && - p->p_dupfd >= 0 && /* XXX from fdopen */ + p->p_dupfd >= 0 && /* XXX from fdopen */ (error = - dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { + dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { *retval = indx; return (0); } @@ -714,18 +884,17 @@ open(p, uap, retval) type = F_FLOCK; if ((flags & FNONBLOCK) == 0) type |= F_WAIT; - VOP_UNLOCK(vp); - error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type); - if (error) { + VOP_UNLOCK(vp, 0, p); + if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { (void) vn_close(vp, fp->f_flag, fp->f_cred, p); ffree(fp); fdp->fd_ofiles[indx] = NULL; return (error); } - VOP_LOCK(vp); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); fp->f_flag |= FHASLOCK; } - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); *retval = indx; return (0); } @@ -743,15 +912,22 @@ struct ocreat_args { int ocreat(p, uap, retval) struct proc *p; - register struct ocreat_args *uap; - int *retval; + register struct ocreat_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + } */ *uap; + register_t *retval; { - struct open_args openuap; - - openuap.path = uap->path; - openuap.mode = uap->mode; - openuap.flags = O_WRONLY | O_CREAT | O_TRUNC; - return (open(p, &openuap, retval)); + struct open_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + syscallarg(int) mode; + } */ nuap; + + SCARG(&nuap, path) = SCARG(uap, path); + SCARG(&nuap, mode) = SCARG(uap, mode); + SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; + return (open(p, &nuap, retval)); } #endif /* COMPAT_43 */ @@ -769,30 +945,35 @@ struct mknod_args { int mknod(p, uap, retval) struct proc *p; - register struct mknod_args *uap; - int *retval; + register struct mknod_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + syscallarg(int) dev; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; int error; + int whiteout; struct nameidata nd; error = suser(p->p_ucred, &p->p_acflag); if (error) return (error); - NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); + if (error = namei(&nd)) return (error); vp = nd.ni_vp; if (vp != NULL) error = EEXIST; else { VATTR_NULL(&vattr); - vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask; - vattr.va_rdev = uap->dev; + vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; + vattr.va_rdev = SCARG(uap, dev); + whiteout = 0; - switch (uap->mode & S_IFMT) { + switch (SCARG(uap, mode) & S_IFMT) { case S_IFMT: /* used by badsect to flag bad sectors */ vattr.va_type = VBAD; break; @@ -802,14 +983,25 @@ mknod(p, uap, retval) case S_IFBLK: vattr.va_type = VBLK; break; + case S_IFWHT: + whiteout = 1; + break; default: error = EINVAL; break; } } if (!error) { - LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); - error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + if (whiteout) { + error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); + if (error) + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + vput(nd.ni_dvp); + } else { + error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, + &nd.ni_cnd, &vattr); + } } else { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == vp) @@ -823,7 +1015,7 @@ mknod(p, uap, retval) } /* - * Create named pipe. + * Create a named pipe. */ #ifndef _SYS_SYSPROTO_H_ struct mkfifo_args { @@ -835,16 +1027,21 @@ struct mkfifo_args { int mkfifo(p, uap, retval) struct proc *p; - register struct mkfifo_args *uap; - int *retval; + register struct mkfifo_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + } */ *uap; + register_t *retval; { +#ifndef FIFO + return (EOPNOTSUPP); +#else struct vattr vattr; int error; struct nameidata nd; - NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); + if (error = namei(&nd)) return (error); if (nd.ni_vp != NULL) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); @@ -857,9 +1054,10 @@ mkfifo(p, uap, retval) } VATTR_NULL(&vattr); vattr.va_type = VFIFO; - vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask; - LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); +#endif /* FIFO */ } /* @@ -875,22 +1073,24 @@ struct link_args { int link(p, uap, retval) struct proc *p; - register struct link_args *uap; - int *retval; + register struct link_args /* { + syscallarg(char *) path; + syscallarg(char *) link; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct nameidata nd; int error; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + if (error = namei(&nd)) return (error); vp = nd.ni_vp; if (vp->v_type == VDIR) error = EPERM; /* POSIX */ else { - NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p); + NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); error = namei(&nd); if (!error) { if (nd.ni_vp != NULL) { @@ -903,10 +1103,9 @@ link(p, uap, retval) vrele(nd.ni_vp); error = EEXIST; } else { - LEASE_CHECK(nd.ni_dvp, - p, p->p_ucred, LEASE_WRITE); - LEASE_CHECK(vp, - p, p->p_ucred, LEASE_WRITE); + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, + LEASE_WRITE); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); } } @@ -928,8 +1127,11 @@ struct symlink_args { int symlink(p, uap, retval) struct proc *p; - register struct symlink_args *uap; - int *retval; + register struct symlink_args /* { + syscallarg(char *) path; + syscallarg(char *) link; + } */ *uap; + register_t *retval; { struct vattr vattr; char *path; @@ -937,12 +1139,10 @@ symlink(p, uap, retval) struct nameidata nd; MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); - error = copyinstr(uap->path, path, MAXPATHLEN, NULL); - if (error) + if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) goto out; - NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p); - error = namei(&nd); - if (error) + NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); + if (error = namei(&nd)) goto out; if (nd.ni_vp) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); @@ -956,7 +1156,7 @@ symlink(p, uap, retval) } VATTR_NULL(&vattr); vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; - LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); out: FREE(path, M_NAMEI); @@ -964,6 +1164,45 @@ out: } /* + * Delete a whiteout from the filesystem. + */ +/* ARGSUSED */ +int +undelete(p, uap, retval) + struct proc *p; + register struct undelete_args /* { + syscallarg(char *) path; + } */ *uap; + register_t *retval; +{ + int error; + struct nameidata nd; + + NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, + SCARG(uap, path), p); + error = namei(&nd); + if (error) + return (error); + + if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); + else + vput(nd.ni_dvp); + if (nd.ni_vp) + vrele(nd.ni_vp); + return (EEXIST); + } + + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + vput(nd.ni_dvp); + return (error); +} + +/* * Delete a name from the filesystem. */ #ifndef _SYS_SYSPROTO_H_ @@ -975,20 +1214,21 @@ struct unlink_args { int unlink(p, uap, retval) struct proc *p; - struct unlink_args *uap; - int *retval; + struct unlink_args /* { + syscallarg(char *) path; + } */ *uap; + register_t *retval; { register struct vnode *vp; int error; struct nameidata nd; - NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); + if (error = namei(&nd)) return (error); vp = nd.ni_vp; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); if (vp->v_type == VDIR) error = EPERM; /* POSIX */ @@ -1001,11 +1241,11 @@ unlink(p, uap, retval) if (vp->v_flag & VROOT) error = EBUSY; else - (void) vnode_pager_uncache(vp); + (void) vnode_pager_uncache(vp, p); } if (!error) { - LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + VOP_LEASE(nd.ni_dvp, 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); @@ -1013,7 +1253,8 @@ unlink(p, uap, retval) vrele(nd.ni_dvp); else vput(nd.ni_dvp); - vput(vp); + if (vp != NULLVP) + vput(vp); } return (error); } @@ -1032,8 +1273,13 @@ struct lseek_args { int lseek(p, uap, retval) struct proc *p; - register struct lseek_args *uap; - int *retval; + register struct lseek_args /* { + syscallarg(int) fd; + syscallarg(int) pad; + syscallarg(off_t) offset; + syscallarg(int) whence; + } */ *uap; + register_t *retval; /* XXX */ { struct ucred *cred = p->p_ucred; register struct filedesc *fdp = p->p_fd; @@ -1041,23 +1287,23 @@ lseek(p, uap, retval) struct vattr vattr; int error; - if ((u_int)uap->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL) + if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) return (EBADF); if (fp->f_type != DTYPE_VNODE) return (ESPIPE); - switch (uap->whence) { + switch (SCARG(uap, whence)) { case L_INCR: - fp->f_offset += uap->offset; + fp->f_offset += SCARG(uap, offset); break; case L_XTND: error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p); if (error) return (error); - fp->f_offset = uap->offset + vattr.va_size; + fp->f_offset = SCARG(uap, offset) + vattr.va_size; break; case L_SET: - fp->f_offset = uap->offset; + fp->f_offset = SCARG(uap, offset); break; default: return (EINVAL); @@ -1080,17 +1326,26 @@ struct olseek_args { int olseek(p, uap, retval) struct proc *p; - register struct olseek_args *uap; - int *retval; + register struct olseek_args /* { + syscallarg(int) fd; + syscallarg(long) offset; + syscallarg(int) whence; + } */ *uap; + register_t *retval; { - struct lseek_args nuap; + struct lseek_args /* { + syscallarg(int) fd; + syscallarg(int) pad; + syscallarg(off_t) offset; + syscallarg(int) whence; + } */ nuap; off_t qret; int error; - nuap.fd = uap->fd; - nuap.offset = uap->offset; - nuap.whence = uap->whence; - error = lseek(p, &nuap, (int *)&qret); + SCARG(&nuap, fd) = SCARG(uap, fd); + SCARG(&nuap, offset) = SCARG(uap, offset); + SCARG(&nuap, whence) = SCARG(uap, whence); + error = lseek(p, &nuap, (register_t *) &qret); *(long *)retval = qret; return (error); } @@ -1108,8 +1363,11 @@ struct access_args { int access(p, uap, retval) struct proc *p; - register struct access_args *uap; - int *retval; + register struct access_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { register struct ucred *cred = p->p_ucred; register struct vnode *vp; @@ -1120,20 +1378,20 @@ access(p, uap, retval) t_gid = cred->cr_groups[0]; cred->cr_uid = p->p_cred->p_ruid; cred->cr_groups[0] = p->p_cred->p_rgid; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); + if (error = namei(&nd)) goto out1; vp = nd.ni_vp; /* Flags == 0 means only check for existence. */ - if (uap->flags) { + if (SCARG(uap, flags)) { flags = 0; - if (uap->flags & R_OK) + if (SCARG(uap, flags) & R_OK) flags |= VREAD; - if (uap->flags & W_OK) + if (SCARG(uap, flags) & W_OK) flags |= VWRITE; - if (uap->flags & X_OK) + if (SCARG(uap, flags) & X_OK) flags |= VEXEC; if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) error = VOP_ACCESS(vp, flags, cred, p); @@ -1159,24 +1417,27 @@ struct ostat_args { int ostat(p, uap, retval) struct proc *p; - register struct ostat_args *uap; - int *retval; + register struct ostat_args /* { + syscallarg(char *) path; + syscallarg(struct ostat *) ub; + } */ *uap; + register_t *retval; { struct stat sb; struct ostat osb; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); + if (error = namei(&nd)) return (error); error = vn_stat(nd.ni_vp, &sb, p); vput(nd.ni_vp); if (error) return (error); cvtstat(&sb, &osb); - error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); + error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); return (error); } @@ -1193,8 +1454,11 @@ struct olstat_args { int olstat(p, uap, retval) struct proc *p; - register struct olstat_args *uap; - int *retval; + register struct olstat_args /* { + syscallarg(char *) path; + syscallarg(struct ostat *) ub; + } */ *uap; + register_t *retval; { struct vnode *vp, *dvp; struct stat sb, sb1; @@ -1203,9 +1467,8 @@ olstat(p, uap, retval) struct nameidata nd; NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, - uap->path, p); - error = namei(&nd); - if (error) + SCARG(uap, path), p); + if (error = namei(&nd)) return (error); /* * For symbolic links, always return the attributes of its @@ -1240,7 +1503,7 @@ olstat(p, uap, retval) sb.st_blocks = sb1.st_blocks; } cvtstat(&sb, &osb); - error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); + error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); return (error); } @@ -1287,22 +1550,25 @@ struct stat_args { int stat(p, uap, retval) struct proc *p; - register struct stat_args *uap; - int *retval; + register struct stat_args /* { + syscallarg(char *) path; + syscallarg(struct stat *) ub; + } */ *uap; + register_t *retval; { struct stat sb; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); + if (error = namei(&nd)) return (error); error = vn_stat(nd.ni_vp, &sb, p); vput(nd.ni_vp); if (error) return (error); - error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); + error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); return (error); } @@ -1319,8 +1585,11 @@ struct lstat_args { int lstat(p, uap, retval) struct proc *p; - register struct lstat_args *uap; - int *retval; + register struct lstat_args /* { + syscallarg(char *) path; + syscallarg(struct stat *) ub; + } */ *uap; + register_t *retval; { int error; struct vnode *vp, *dvp; @@ -1328,13 +1597,12 @@ lstat(p, uap, retval) struct nameidata nd; NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, - uap->path, p); - error = namei(&nd); - if (error) + SCARG(uap, path), p); + if (error = namei(&nd)) return (error); /* - * For symbolic links, always return the attributes of its - * containing directory, except for mode, size, and links. + * For symbolic links, always return the attributes of its containing + * directory, except for mode, size, inode number, and links. */ vp = nd.ni_vp; dvp = nd.ni_dvp; @@ -1363,8 +1631,9 @@ lstat(p, uap, retval) sb.st_nlink = sb1.st_nlink; sb.st_size = sb1.st_size; sb.st_blocks = sb1.st_blocks; + sb.st_ino = sb1.st_ino; } - error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); + error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); return (error); } @@ -1381,17 +1650,20 @@ struct pathconf_args { int pathconf(p, uap, retval) struct proc *p; - register struct pathconf_args *uap; - int *retval; + register struct pathconf_args /* { + syscallarg(char *) path; + syscallarg(int) name; + } */ *uap; + register_t *retval; { int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); + if (error = namei(&nd)) return (error); - error = VOP_PATHCONF(nd.ni_vp, uap->name, retval); + error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval); vput(nd.ni_vp); return (error); } @@ -1410,8 +1682,12 @@ struct readlink_args { int readlink(p, uap, retval) struct proc *p; - register struct readlink_args *uap; - int *retval; + register struct readlink_args /* { + syscallarg(char *) path; + syscallarg(char *) buf; + syscallarg(int) count; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct iovec aiov; @@ -1419,27 +1695,27 @@ readlink(p, uap, retval) int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); + if (error = namei(&nd)) return (error); vp = nd.ni_vp; if (vp->v_type != VLNK) error = EINVAL; else { - aiov.iov_base = uap->buf; - aiov.iov_len = uap->count; + aiov.iov_base = SCARG(uap, buf); + aiov.iov_len = SCARG(uap, count); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = 0; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; - auio.uio_resid = uap->count; + auio.uio_resid = SCARG(uap, count); error = VOP_READLINK(vp, &auio, p->p_ucred); } vput(vp); - *retval = uap->count - auio.uio_resid; + *retval = SCARG(uap, count) - auio.uio_resid; return (error); } @@ -1456,23 +1732,25 @@ struct chflags_args { int chflags(p, uap, retval) struct proc *p; - register struct chflags_args *uap; - int *retval; + register struct chflags_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + if (error = namei(&nd)) return (error); vp = nd.ni_vp; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); VATTR_NULL(&vattr); - vattr.va_flags = uap->flags; + vattr.va_flags = SCARG(uap, flags); error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); @@ -1491,24 +1769,26 @@ struct fchflags_args { int fchflags(p, uap, retval) struct proc *p; - register struct fchflags_args *uap; - int *retval; + register struct fchflags_args /* { + syscallarg(int) fd; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { struct vattr vattr; struct vnode *vp; struct file *fp; int error; - error = getvnode(p->p_fd, uap->fd, &fp); - if (error) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); vp = (struct vnode *)fp->f_data; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); VATTR_NULL(&vattr); - vattr.va_flags = uap->flags; + vattr.va_flags = SCARG(uap, flags); error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); return (error); } @@ -1525,23 +1805,25 @@ struct chmod_args { int chmod(p, uap, retval) struct proc *p; - register struct chmod_args *uap; - int *retval; + register struct chmod_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + if (error = namei(&nd)) return (error); vp = nd.ni_vp; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); VATTR_NULL(&vattr); - vattr.va_mode = uap->mode & ALLPERMS; + vattr.va_mode = SCARG(uap, mode) & ALLPERMS; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); @@ -1560,24 +1842,26 @@ struct fchmod_args { int fchmod(p, uap, retval) struct proc *p; - register struct fchmod_args *uap; - int *retval; + register struct fchmod_args /* { + syscallarg(int) fd; + syscallarg(int) mode; + } */ *uap; + register_t *retval; { struct vattr vattr; struct vnode *vp; struct file *fp; int error; - error = getvnode(p->p_fd, uap->fd, &fp); - if (error) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); vp = (struct vnode *)fp->f_data; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); VATTR_NULL(&vattr); - vattr.va_mode = uap->mode & ALLPERMS; + vattr.va_mode = SCARG(uap, mode) & ALLPERMS; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); return (error); } @@ -1595,24 +1879,27 @@ struct chown_args { int chown(p, uap, retval) struct proc *p; - register struct chown_args *uap; - int *retval; + register struct chown_args /* { + syscallarg(char *) path; + syscallarg(int) uid; + syscallarg(int) gid; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + if (error = namei(&nd)) return (error); vp = nd.ni_vp; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); VATTR_NULL(&vattr); - vattr.va_uid = uap->uid; - vattr.va_gid = uap->gid; + vattr.va_uid = SCARG(uap, uid); + vattr.va_gid = SCARG(uap, gid); error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); @@ -1632,25 +1919,28 @@ struct fchown_args { int fchown(p, uap, retval) struct proc *p; - register struct fchown_args *uap; - int *retval; + register struct fchown_args /* { + syscallarg(int) fd; + syscallarg(int) uid; + syscallarg(int) gid; + } */ *uap; + register_t *retval; { struct vattr vattr; struct vnode *vp; struct file *fp; int error; - error = getvnode(p->p_fd, uap->fd, &fp); - if (error) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); vp = (struct vnode *)fp->f_data; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); VATTR_NULL(&vattr); - vattr.va_uid = uap->uid; - vattr.va_gid = uap->gid; + vattr.va_uid = SCARG(uap, uid); + vattr.va_gid = SCARG(uap, gid); error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); return (error); } @@ -1667,8 +1957,11 @@ struct utimes_args { int utimes(p, uap, retval) struct proc *p; - register struct utimes_args *uap; - int *retval; + register struct utimes_args /* { + syscallarg(char *) path; + syscallarg(struct timeval *) tptr; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct timeval tv[2]; @@ -1677,22 +1970,19 @@ utimes(p, uap, retval) struct nameidata nd; VATTR_NULL(&vattr); - if (uap->tptr == NULL) { + if (SCARG(uap, tptr) == NULL) { microtime(&tv[0]); tv[1] = tv[0]; vattr.va_vaflags |= VA_UTIMES_NULL; - } else { - error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); - if (error) - return (error); - } - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv, + sizeof (tv))) + return (error); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + if (error = namei(&nd)) return (error); vp = nd.ni_vp; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); vattr.va_atime.tv_sec = tv[0].tv_sec; vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000; vattr.va_mtime.tv_sec = tv[1].tv_sec; @@ -1716,8 +2006,12 @@ struct truncate_args { int truncate(p, uap, retval) struct proc *p; - register struct truncate_args *uap; - int *retval; + register struct truncate_args /* { + syscallarg(char *) path; + syscallarg(int) pad; + syscallarg(off_t) length; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; @@ -1726,19 +2020,18 @@ truncate(p, uap, retval) if (uap->length < 0) return(EINVAL); - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + if (error = namei(&nd)) return (error); vp = nd.ni_vp; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); if (vp->v_type == VDIR) error = EISDIR; else if ((error = vn_writechk(vp)) == 0 && (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { VATTR_NULL(&vattr); - vattr.va_size = uap->length; + vattr.va_size = SCARG(uap, length); error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } vput(vp); @@ -1759,8 +2052,12 @@ struct ftruncate_args { int ftruncate(p, uap, retval) struct proc *p; - register struct ftruncate_args *uap; - int *retval; + register struct ftruncate_args /* { + syscallarg(int) fd; + syscallarg(int) pad; + syscallarg(off_t) length; + } */ *uap; + register_t *retval; { struct vattr vattr; struct vnode *vp; @@ -1769,22 +2066,21 @@ ftruncate(p, uap, retval) if (uap->length < 0) return(EINVAL); - error = getvnode(p->p_fd, uap->fd, &fp); - if (error) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); 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); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); if (vp->v_type == VDIR) error = EISDIR; else if ((error = vn_writechk(vp)) == 0) { VATTR_NULL(&vattr); - vattr.va_size = uap->length; + vattr.va_size = SCARG(uap, length); error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); } - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); return (error); } @@ -1802,13 +2098,20 @@ struct otruncate_args { int otruncate(p, uap, retval) struct proc *p; - register struct otruncate_args *uap; - int *retval; + register struct otruncate_args /* { + syscallarg(char *) path; + syscallarg(long) length; + } */ *uap; + register_t *retval; { - struct truncate_args nuap; - - nuap.path = uap->path; - nuap.length = uap->length; + struct truncate_args /* { + syscallarg(char *) path; + syscallarg(int) pad; + syscallarg(off_t) length; + } */ nuap; + + SCARG(&nuap, path) = SCARG(uap, path); + SCARG(&nuap, length) = SCARG(uap, length); return (truncate(p, &nuap, retval)); } @@ -1825,13 +2128,20 @@ struct oftruncate_args { int oftruncate(p, uap, retval) struct proc *p; - register struct oftruncate_args *uap; - int *retval; + register struct oftruncate_args /* { + syscallarg(int) fd; + syscallarg(long) length; + } */ *uap; + register_t *retval; { - struct ftruncate_args nuap; - - nuap.fd = uap->fd; - nuap.length = uap->length; + struct ftruncate_args /* { + syscallarg(int) fd; + syscallarg(int) pad; + syscallarg(off_t) length; + } */ nuap; + + SCARG(&nuap, fd) = SCARG(uap, fd); + SCARG(&nuap, length) = SCARG(uap, length); return (ftruncate(p, &nuap, retval)); } #endif /* COMPAT_43 || COMPAT_SUNOS */ @@ -1848,24 +2158,25 @@ struct fsync_args { int fsync(p, uap, retval) struct proc *p; - struct fsync_args *uap; - int *retval; + struct fsync_args /* { + syscallarg(int) fd; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct file *fp; int error; - error = getvnode(p->p_fd, uap->fd, &fp); - if (error) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); vp = (struct vnode *)fp->f_data; - VOP_LOCK(vp); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); if (vp->v_object) { vm_object_page_clean(vp->v_object, 0, 0 ,0, FALSE); } error = VOP_FSYNC(vp, fp->f_cred, (vp->v_mount->mnt_flag & MNT_ASYNC) ? MNT_NOWAIT : MNT_WAIT, p); - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); return (error); } @@ -1883,29 +2194,29 @@ struct rename_args { int rename(p, uap, retval) struct proc *p; - register struct rename_args *uap; - int *retval; + register struct rename_args /* { + syscallarg(char *) from; + syscallarg(char *) to; + } */ *uap; + register_t *retval; { register struct vnode *tvp, *fvp, *tdvp; struct nameidata fromnd, tond; int error; NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, - uap->from, p); - error = namei(&fromnd); - if (error) + SCARG(uap, from), p); + if (error = namei(&fromnd)) return (error); fvp = fromnd.ni_vp; NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, - UIO_USERSPACE, uap->to, p); + UIO_USERSPACE, SCARG(uap, to), p); if (fromnd.ni_vp->v_type == VDIR) tond.ni_cnd.cn_flags |= WILLBEDIR; - error = namei(&tond); - if (error) { + if (error = namei(&tond)) { /* Translate error code for rename("dir1", "dir2/."). */ if (error == EISDIR && fvp->v_type == VDIR) error = EINVAL; - VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); vrele(fromnd.ni_dvp); vrele(fvp); @@ -1936,13 +2247,12 @@ rename(p, uap, retval) error = -1; out: if (!error) { - LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE); - if (fromnd.ni_dvp != tdvp) { - LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); - } + VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE); + if (fromnd.ni_dvp != tdvp) + VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); if (tvp) { - LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE); - (void) vnode_pager_uncache(tvp); + VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE); + (void) vnode_pager_uncache(tvp, p); } error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); @@ -1982,18 +2292,20 @@ struct mkdir_args { int mkdir(p, uap, retval) struct proc *p; - register struct mkdir_args *uap; - int *retval; + register struct mkdir_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; - NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); nd.ni_cnd.cn_flags |= WILLBEDIR; - error = namei(&nd); - if (error) + if (error = namei(&nd)) return (error); vp = nd.ni_vp; if (vp != NULL) { @@ -2007,8 +2319,8 @@ mkdir(p, uap, retval) } VATTR_NULL(&vattr); vattr.va_type = VDIR; - vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask; - LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask; + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); if (!error) vput(nd.ni_vp); @@ -2027,16 +2339,18 @@ struct rmdir_args { int rmdir(p, uap, retval) struct proc *p; - struct rmdir_args *uap; - int *retval; + struct rmdir_args /* { + syscallarg(char *) path; + } */ *uap; + register_t *retval; { register struct vnode *vp; int error; struct nameidata nd; - NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); + if (error = namei(&nd)) return (error); vp = nd.ni_vp; if (vp->v_type != VDIR) { @@ -2057,8 +2371,8 @@ rmdir(p, uap, retval) error = EBUSY; out: if (!error) { - LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); } else { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); @@ -2086,8 +2400,13 @@ struct ogetdirentries_args { int ogetdirentries(p, uap, retval) struct proc *p; - register struct ogetdirentries_args *uap; - int *retval; + register struct ogetdirentries_args /* { + syscallarg(int) fd; + syscallarg(char *) buf; + syscallarg(u_int) count; + syscallarg(long *) basep; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct file *fp; @@ -2095,30 +2414,31 @@ ogetdirentries(p, uap, retval) struct iovec aiov, kiov; struct dirent *dp, *edp; caddr_t dirbuf; - int error, readcnt; + int error, eofflag, readcnt; long loff; - error = getvnode(p->p_fd, uap->fd, &fp); - if (error) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); if ((fp->f_flag & FREAD) == 0) return (EBADF); vp = (struct vnode *)fp->f_data; +unionread: if (vp->v_type != VDIR) return (EINVAL); - aiov.iov_base = uap->buf; - aiov.iov_len = uap->count; + aiov.iov_base = SCARG(uap, buf); + aiov.iov_len = SCARG(uap, count); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; - auio.uio_resid = uap->count; - VOP_LOCK(vp); + auio.uio_resid = SCARG(uap, count); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); loff = auio.uio_offset = fp->f_offset; # if (BYTE_ORDER != LITTLE_ENDIAN) if (vp->v_mount->mnt_maxsymlinklen <= 0) { - error = VOP_READDIR(vp, &auio, fp->f_cred, NULL, NULL, NULL); + error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, + NULL, NULL); fp->f_offset = auio.uio_offset; } else # endif @@ -2126,13 +2446,14 @@ ogetdirentries(p, uap, retval) kuio = auio; kuio.uio_iov = &kiov; kuio.uio_segflg = UIO_SYSSPACE; - kiov.iov_len = uap->count; - MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK); + kiov.iov_len = SCARG(uap, count); + MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); kiov.iov_base = dirbuf; - error = VOP_READDIR(vp, &kuio, fp->f_cred, NULL, NULL, NULL); + error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, + NULL, NULL); fp->f_offset = kuio.uio_offset; if (error == 0) { - readcnt = uap->count - kuio.uio_resid; + readcnt = SCARG(uap, count) - kuio.uio_resid; edp = (struct dirent *)&dirbuf[readcnt]; for (dp = (struct dirent *)dirbuf; dp < edp; ) { # if (BYTE_ORDER == LITTLE_ENDIAN) @@ -2165,14 +2486,70 @@ ogetdirentries(p, uap, retval) } FREE(dirbuf, M_TEMP); } - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); if (error) return (error); - error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); - *retval = uap->count - auio.uio_resid; + +#ifdef UNION +{ + extern int (**union_vnodeop_p)(); + extern struct vnode *union_dircache __P((struct vnode*, struct proc*)); + + if ((SCARG(uap, count) == auio.uio_resid) && + (vp->v_op == union_vnodeop_p)) { + struct vnode *lvp; + + lvp = union_dircache(vp, p); + if (lvp != NULLVP) { + struct vattr va; + + /* + * If the directory is opaque, + * then don't show lower entries + */ + error = VOP_GETATTR(vp, &va, fp->f_cred, p); + if (va.va_flags & OPAQUE) { + vput(lvp); + lvp = NULL; + } + } + + if (lvp != NULLVP) { + error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); + if (error) { + vput(lvp); + return (error); + } + VOP_UNLOCK(lvp, 0, p); + fp->f_data = (caddr_t) lvp; + fp->f_offset = 0; + error = vn_close(vp, FREAD, fp->f_cred, p); + if (error) + return (error); + vp = lvp; + goto unionread; + } + } +} +#endif /* UNION */ + + if ((SCARG(uap, count) == auio.uio_resid) && + (vp->v_flag & VROOT) && + (vp->v_mount->mnt_flag & MNT_UNION)) { + struct vnode *tvp = vp; + vp = vp->v_mount->mnt_vnodecovered; + VREF(vp); + fp->f_data = (caddr_t) vp; + fp->f_offset = 0; + vrele(tvp); + goto unionread; + } + error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), + sizeof(long)); + *retval = SCARG(uap, count) - auio.uio_resid; return (error); } -#endif +#endif /* COMPAT_43 */ /* * Read a block of directory entries in a file system independent format. @@ -2188,18 +2565,22 @@ struct getdirentries_args { int getdirentries(p, uap, retval) struct proc *p; - register struct getdirentries_args *uap; - int *retval; + register struct getdirentries_args /* { + syscallarg(int) fd; + syscallarg(char *) buf; + syscallarg(u_int) count; + syscallarg(long *) basep; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct file *fp; struct uio auio; struct iovec aiov; long loff; - int error; + int error, eofflag; - error = getvnode(p->p_fd, uap->fd, &fp); - if (error) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); if ((fp->f_flag & FREAD) == 0) return (EBADF); @@ -2207,51 +2588,66 @@ getdirentries(p, uap, retval) unionread: if (vp->v_type != VDIR) return (EINVAL); - aiov.iov_base = uap->buf; - aiov.iov_len = uap->count; + aiov.iov_base = SCARG(uap, buf); + aiov.iov_len = SCARG(uap, count); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; - auio.uio_resid = uap->count; - VOP_LOCK(vp); + auio.uio_resid = SCARG(uap, count); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); loff = auio.uio_offset = fp->f_offset; - error = VOP_READDIR(vp, &auio, fp->f_cred, NULL, NULL, NULL); + error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); fp->f_offset = auio.uio_offset; - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); if (error) return (error); #ifdef UNION { - if ((uap->count == auio.uio_resid) && + extern int (**union_vnodeop_p)(); + extern struct vnode *union_dircache __P((struct vnode*, struct proc*)); + + if ((SCARG(uap, count) == auio.uio_resid) && (vp->v_op == union_vnodeop_p)) { - struct vnode *tvp = vp; + struct vnode *lvp; + + lvp = union_dircache(vp, p); + if (lvp != NULLVP) { + struct vattr va; - vp = union_lowervp(vp); - if (vp != NULLVP) { - VOP_LOCK(vp); - error = VOP_OPEN(vp, FREAD, fp->f_cred, p); - VOP_UNLOCK(vp); + /* + * If the directory is opaque, + * then don't show lower entries + */ + error = VOP_GETATTR(vp, &va, fp->f_cred, p); + if (va.va_flags & OPAQUE) { + vput(lvp); + lvp = NULL; + } + } + if (lvp != NULLVP) { + error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); if (error) { - vrele(vp); + vput(lvp); return (error); } - fp->f_data = (caddr_t) vp; + VOP_UNLOCK(lvp, 0, p); + fp->f_data = (caddr_t) lvp; fp->f_offset = 0; - error = vn_close(tvp, FREAD, fp->f_cred, p); + error = vn_close(vp, FREAD, fp->f_cred, p); if (error) return (error); + vp = lvp; goto unionread; } } } -#endif +#endif /* UNION */ - if ((uap->count == auio.uio_resid) && - vp && + if ((SCARG(uap, count) == auio.uio_resid) && (vp->v_flag & VROOT) && (vp->v_mount->mnt_flag & MNT_UNION)) { struct vnode *tvp = vp; @@ -2262,8 +2658,9 @@ unionread: vrele(tvp); goto unionread; } - error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); - *retval = uap->count - auio.uio_resid; + error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), + sizeof(long)); + *retval = SCARG(uap, count) - auio.uio_resid; return (error); } @@ -2275,17 +2672,19 @@ struct umask_args { int newmask; }; #endif -mode_t /* XXX */ +int umask(p, uap, retval) struct proc *p; - struct umask_args *uap; - int *retval; + struct umask_args /* { + syscallarg(int) newmask; + } */ *uap; + int *retval; /* XXX */ { register struct filedesc *fdp; fdp = p->p_fd; *retval = fdp->fd_cmask; - fdp->fd_cmask = uap->newmask & ALLPERMS; + fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; return (0); } @@ -2302,31 +2701,27 @@ struct revoke_args { int revoke(p, uap, retval) struct proc *p; - register struct revoke_args *uap; - int *retval; + register struct revoke_args /* { + syscallarg(char *) path; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); - error = namei(&nd); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + if (error = namei(&nd)) return (error); vp = nd.ni_vp; - if (vp->v_type != VCHR && vp->v_type != VBLK) { - error = EINVAL; - goto out; - } - error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); - if (error) + if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) goto out; if (p->p_ucred->cr_uid != vattr.va_uid && (error = suser(p->p_ucred, &p->p_acflag))) goto out; if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) - vgoneall(vp); + VOP_REVOKE(vp, REVOKEALL); out: vrele(vp); return (error); |